react-native-pro-accordion 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 +476 -0
- package/index.js +3 -0
- package/lib/commonjs/components/Accordion.js +130 -0
- package/lib/commonjs/components/Accordion.js.map +1 -0
- package/lib/commonjs/components/AccordionContent.js +125 -0
- package/lib/commonjs/components/AccordionContent.js.map +1 -0
- package/lib/commonjs/components/AccordionItem.js +146 -0
- package/lib/commonjs/components/AccordionItem.js.map +1 -0
- package/lib/commonjs/components/AccordionSeparator.js +159 -0
- package/lib/commonjs/components/AccordionSeparator.js.map +1 -0
- package/lib/commonjs/core/AccordionContext.js +82 -0
- package/lib/commonjs/core/AccordionContext.js.map +1 -0
- package/lib/commonjs/core/AccordionRef.js +64 -0
- package/lib/commonjs/core/AccordionRef.js.map +1 -0
- package/lib/commonjs/core/types.js +6 -0
- package/lib/commonjs/core/types.js.map +1 -0
- package/lib/commonjs/hooks/useAccordion.js +18 -0
- package/lib/commonjs/hooks/useAccordion.js.map +1 -0
- package/lib/commonjs/hooks/useAccordionAccessibility.js +39 -0
- package/lib/commonjs/hooks/useAccordionAccessibility.js.map +1 -0
- package/lib/commonjs/hooks/useAccordionAnimation.js +135 -0
- package/lib/commonjs/hooks/useAccordionAnimation.js.map +1 -0
- package/lib/commonjs/hooks/useAccordionKeyboard.js +43 -0
- package/lib/commonjs/hooks/useAccordionKeyboard.js.map +1 -0
- package/lib/commonjs/hooks/useAccordionState.js +96 -0
- package/lib/commonjs/hooks/useAccordionState.js.map +1 -0
- package/lib/commonjs/index.js +176 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/theme/ThemeContext.js +48 -0
- package/lib/commonjs/theme/ThemeContext.js.map +1 -0
- package/lib/commonjs/theme/defaultTheme.js +79 -0
- package/lib/commonjs/theme/defaultTheme.js.map +1 -0
- package/lib/commonjs/theme/types.js +6 -0
- package/lib/commonjs/theme/types.js.map +1 -0
- package/lib/commonjs/utils/animations.js +41 -0
- package/lib/commonjs/utils/animations.js.map +1 -0
- package/lib/commonjs/utils/layout.js +155 -0
- package/lib/commonjs/utils/layout.js.map +1 -0
- package/lib/commonjs/utils/validators.js +26 -0
- package/lib/commonjs/utils/validators.js.map +1 -0
- package/lib/module/components/Accordion.js +125 -0
- package/lib/module/components/Accordion.js.map +1 -0
- package/lib/module/components/AccordionContent.js +120 -0
- package/lib/module/components/AccordionContent.js.map +1 -0
- package/lib/module/components/AccordionItem.js +141 -0
- package/lib/module/components/AccordionItem.js.map +1 -0
- package/lib/module/components/AccordionSeparator.js +155 -0
- package/lib/module/components/AccordionSeparator.js.map +1 -0
- package/lib/module/core/AccordionContext.js +75 -0
- package/lib/module/core/AccordionContext.js.map +1 -0
- package/lib/module/core/AccordionRef.js +59 -0
- package/lib/module/core/AccordionRef.js.map +1 -0
- package/lib/module/core/types.js +136 -0
- package/lib/module/core/types.js.map +1 -0
- package/lib/module/hooks/useAccordion.js +14 -0
- package/lib/module/hooks/useAccordion.js.map +1 -0
- package/lib/module/hooks/useAccordionAccessibility.js +34 -0
- package/lib/module/hooks/useAccordionAccessibility.js.map +1 -0
- package/lib/module/hooks/useAccordionAnimation.js +131 -0
- package/lib/module/hooks/useAccordionAnimation.js.map +1 -0
- package/lib/module/hooks/useAccordionKeyboard.js +38 -0
- package/lib/module/hooks/useAccordionKeyboard.js.map +1 -0
- package/lib/module/hooks/useAccordionState.js +92 -0
- package/lib/module/hooks/useAccordionState.js.map +1 -0
- package/lib/module/index.js +43 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/theme/ThemeContext.js +41 -0
- package/lib/module/theme/ThemeContext.js.map +1 -0
- package/lib/module/theme/defaultTheme.js +75 -0
- package/lib/module/theme/defaultTheme.js.map +1 -0
- package/lib/module/theme/types.js +66 -0
- package/lib/module/theme/types.js.map +1 -0
- package/lib/module/utils/animations.js +35 -0
- package/lib/module/utils/animations.js.map +1 -0
- package/lib/module/utils/layout.js +147 -0
- package/lib/module/utils/layout.js.map +1 -0
- package/lib/module/utils/validators.js +20 -0
- package/lib/module/utils/validators.js.map +1 -0
- package/package.json +25 -0
- package/src/components/Accordion.js +164 -0
- package/src/components/AccordionContent.js +149 -0
- package/src/components/AccordionItem.js +146 -0
- package/src/components/AccordionSeparator.js +168 -0
- package/src/core/AccordionContext.js +86 -0
- package/src/core/AccordionRef.js +69 -0
- package/src/core/types.js +133 -0
- package/src/hooks/useAccordion.js +14 -0
- package/src/hooks/useAccordionAccessibility.js +30 -0
- package/src/hooks/useAccordionAnimation.js +165 -0
- package/src/hooks/useAccordionKeyboard.js +38 -0
- package/src/hooks/useAccordionState.js +119 -0
- package/src/index.js +56 -0
- package/src/theme/ThemeContext.js +40 -0
- package/src/theme/defaultTheme.js +73 -0
- package/src/theme/types.js +63 -0
- package/src/utils/animations.js +38 -0
- package/src/utils/layout.js +138 -0
- package/src/utils/validators.js +20 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export const defaultLightTheme = {
|
|
2
|
+
colors: {
|
|
3
|
+
background: "#FFFFFF",
|
|
4
|
+
surface: "#F5F5F5",
|
|
5
|
+
primary: "#2196F3",
|
|
6
|
+
text: "#000000",
|
|
7
|
+
textSecondary: "#666666",
|
|
8
|
+
border: "#E0E0E0",
|
|
9
|
+
disabled: "#BDBDBD",
|
|
10
|
+
icon: "#666666",
|
|
11
|
+
},
|
|
12
|
+
spacing: {
|
|
13
|
+
xs: 4,
|
|
14
|
+
sm: 8,
|
|
15
|
+
md: 16,
|
|
16
|
+
lg: 24,
|
|
17
|
+
xl: 32,
|
|
18
|
+
},
|
|
19
|
+
typography: {
|
|
20
|
+
header: {
|
|
21
|
+
fontSize: 16,
|
|
22
|
+
fontWeight: "500",
|
|
23
|
+
color: "#000000",
|
|
24
|
+
},
|
|
25
|
+
content: {
|
|
26
|
+
fontSize: 14,
|
|
27
|
+
lineHeight: 20,
|
|
28
|
+
color: "#333333",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
borderRadius: {
|
|
32
|
+
sm: 4,
|
|
33
|
+
md: 8,
|
|
34
|
+
lg: 12,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const defaultDarkTheme = {
|
|
39
|
+
colors: {
|
|
40
|
+
background: "#121212",
|
|
41
|
+
surface: "#1E1E1E",
|
|
42
|
+
primary: "#64B5F6",
|
|
43
|
+
text: "#FFFFFF",
|
|
44
|
+
textSecondary: "#B0B0B0",
|
|
45
|
+
border: "#2C2C2C",
|
|
46
|
+
disabled: "#6B6B6B",
|
|
47
|
+
icon: "#B0B0B0",
|
|
48
|
+
},
|
|
49
|
+
spacing: {
|
|
50
|
+
xs: 4,
|
|
51
|
+
sm: 8,
|
|
52
|
+
md: 16,
|
|
53
|
+
lg: 24,
|
|
54
|
+
xl: 32,
|
|
55
|
+
},
|
|
56
|
+
typography: {
|
|
57
|
+
header: {
|
|
58
|
+
fontSize: 16,
|
|
59
|
+
fontWeight: "500",
|
|
60
|
+
color: "#FFFFFF",
|
|
61
|
+
},
|
|
62
|
+
content: {
|
|
63
|
+
fontSize: 14,
|
|
64
|
+
lineHeight: 20,
|
|
65
|
+
color: "#E0E0E0",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
borderRadius: {
|
|
69
|
+
sm: 4,
|
|
70
|
+
md: 8,
|
|
71
|
+
lg: 12,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme type definitions for JSDoc
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} ThemeColors
|
|
7
|
+
* @property {string} background - Background color
|
|
8
|
+
* @property {string} surface - Surface/card color
|
|
9
|
+
* @property {string} primary - Primary accent color
|
|
10
|
+
* @property {string} text - Primary text color
|
|
11
|
+
* @property {string} textSecondary - Secondary text color
|
|
12
|
+
* @property {string} border - Border color
|
|
13
|
+
* @property {string} disabled - Disabled state color
|
|
14
|
+
* @property {string} icon - Icon color
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} ThemeSpacing
|
|
19
|
+
* @property {number} xs - Extra small spacing (4px)
|
|
20
|
+
* @property {number} sm - Small spacing (8px)
|
|
21
|
+
* @property {number} md - Medium spacing (16px)
|
|
22
|
+
* @property {number} lg - Large spacing (24px)
|
|
23
|
+
* @property {number} xl - Extra large spacing (32px)
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {Object} ThemeTypography
|
|
28
|
+
* @property {Object} header - Header text style
|
|
29
|
+
* @property {Object} content - Content text style
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {Object} ThemeBorderRadius
|
|
34
|
+
* @property {number} sm - Small border radius (4px)
|
|
35
|
+
* @property {number} md - Medium border radius (8px)
|
|
36
|
+
* @property {number} lg - Large border radius (12px)
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {Object} CompleteAccordionTheme
|
|
41
|
+
* @property {ThemeColors} colors
|
|
42
|
+
* @property {ThemeSpacing} spacing
|
|
43
|
+
* @property {ThemeTypography} typography
|
|
44
|
+
* @property {ThemeBorderRadius} borderRadius
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @typedef {Object} ThemeContextValue
|
|
49
|
+
* @property {CompleteAccordionTheme} theme
|
|
50
|
+
* @property {boolean} darkMode
|
|
51
|
+
* @property {Function} setDarkMode
|
|
52
|
+
* @property {Function} toggleDarkMode
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @typedef {Object} ThemeProviderProps
|
|
57
|
+
* @property {React.ReactNode} children
|
|
58
|
+
* @property {Partial<CompleteAccordionTheme>} [theme]
|
|
59
|
+
* @property {boolean} [darkMode]
|
|
60
|
+
* @property {Function} [onDarkModeChange]
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { withTiming, withSpring, Easing } from "react-native-reanimated";
|
|
2
|
+
|
|
3
|
+
export const getAnimatedHeight = (expanded, contentHeight, config) => {
|
|
4
|
+
const toValue = expanded ? contentHeight : 0;
|
|
5
|
+
|
|
6
|
+
if (config.type === "spring") {
|
|
7
|
+
return withSpring(toValue, {
|
|
8
|
+
damping: config.damping ?? 10,
|
|
9
|
+
mass: config.mass ?? 1,
|
|
10
|
+
stiffness: config.stiffness ?? 100,
|
|
11
|
+
overshootClamping: config.overshootClamping ?? false,
|
|
12
|
+
restSpeedThreshold: config.restSpeedThreshold ?? 0.01,
|
|
13
|
+
restDisplacementThreshold: config.restDisplacementThreshold ?? 0.01,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return withTiming(toValue, {
|
|
18
|
+
duration: config.duration ?? 300,
|
|
19
|
+
easing: config.easing ?? Easing.inOut(Easing.ease),
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const getAnimatedOpacity = (expanded, config) => {
|
|
24
|
+
const toValue = expanded ? 1 : 0;
|
|
25
|
+
|
|
26
|
+
if (config.type === "spring") {
|
|
27
|
+
return withSpring(toValue, {
|
|
28
|
+
damping: config.damping ?? 10,
|
|
29
|
+
mass: config.mass ?? 1,
|
|
30
|
+
stiffness: config.stiffness ?? 100,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return withTiming(toValue, {
|
|
35
|
+
duration: (config.duration ?? 300) * 0.6,
|
|
36
|
+
easing: config.easing ?? Easing.inOut(Easing.ease),
|
|
37
|
+
});
|
|
38
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { useState, useCallback, useRef, useEffect } from "react";
|
|
2
|
+
import { LayoutAnimation, Platform, UIManager } from "react-native";
|
|
3
|
+
|
|
4
|
+
// Enable LayoutAnimation on Android
|
|
5
|
+
if (
|
|
6
|
+
Platform.OS === "android" &&
|
|
7
|
+
UIManager.setLayoutAnimationEnabledExperimental
|
|
8
|
+
) {
|
|
9
|
+
UIManager.setLayoutAnimationEnabledExperimental(true);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Hook for measuring content height
|
|
14
|
+
* @returns {Object} Height measurement utilities
|
|
15
|
+
*/
|
|
16
|
+
export const useContentHeight = () => {
|
|
17
|
+
const [height, setHeight] = useState(0);
|
|
18
|
+
const [isMeasured, setIsMeasured] = useState(false);
|
|
19
|
+
const measuredHeightRef = useRef(0);
|
|
20
|
+
|
|
21
|
+
const onLayout = useCallback((event) => {
|
|
22
|
+
const newHeight = event.nativeEvent.layout.height;
|
|
23
|
+
if (newHeight !== measuredHeightRef.current && newHeight > 0) {
|
|
24
|
+
measuredHeightRef.current = newHeight;
|
|
25
|
+
setHeight(newHeight);
|
|
26
|
+
setIsMeasured(true);
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
const resetHeight = useCallback(() => {
|
|
31
|
+
setHeight(0);
|
|
32
|
+
setIsMeasured(false);
|
|
33
|
+
measuredHeightRef.current = 0;
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
height,
|
|
38
|
+
isMeasured,
|
|
39
|
+
onLayout,
|
|
40
|
+
resetHeight,
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Hook for measuring multiple content heights
|
|
46
|
+
* @returns {Object} Map of heights for multiple items
|
|
47
|
+
*/
|
|
48
|
+
export const useMultipleContentHeights = () => {
|
|
49
|
+
const [heights, setHeights] = useState({});
|
|
50
|
+
const measuredRefs = useRef({});
|
|
51
|
+
|
|
52
|
+
const onLayout = useCallback((id, event) => {
|
|
53
|
+
const newHeight = event.nativeEvent.layout.height;
|
|
54
|
+
if (newHeight !== measuredRefs.current[id] && newHeight > 0) {
|
|
55
|
+
measuredRefs.current[id] = newHeight;
|
|
56
|
+
setHeights((prev) => ({ ...prev, [id]: newHeight }));
|
|
57
|
+
}
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
const getHeight = useCallback(
|
|
61
|
+
(id) => {
|
|
62
|
+
return heights[id] || 0;
|
|
63
|
+
},
|
|
64
|
+
[heights],
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const resetHeights = useCallback(() => {
|
|
68
|
+
setHeights({});
|
|
69
|
+
measuredRefs.current = {};
|
|
70
|
+
}, []);
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
heights,
|
|
74
|
+
getHeight,
|
|
75
|
+
onLayout,
|
|
76
|
+
resetHeights,
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Animates layout changes
|
|
82
|
+
* @param {Object} config - Animation configuration
|
|
83
|
+
*/
|
|
84
|
+
export const animateLayout = (config = {}) => {
|
|
85
|
+
const { duration = 300, type = "easeInEaseOut", property = "all" } = config;
|
|
86
|
+
|
|
87
|
+
LayoutAnimation.configureNext(
|
|
88
|
+
LayoutAnimation.create(duration, type, property),
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Smooth scroll to an accordion item
|
|
94
|
+
* @param {Object} scrollViewRef - Reference to ScrollView
|
|
95
|
+
* @param {number} yPosition - Y position to scroll to
|
|
96
|
+
* @param {Object} options - Scroll options
|
|
97
|
+
*/
|
|
98
|
+
export const scrollToAccordionItem = (
|
|
99
|
+
scrollViewRef,
|
|
100
|
+
yPosition,
|
|
101
|
+
options = {},
|
|
102
|
+
) => {
|
|
103
|
+
const { animated = true, duration = 300, offset = 0 } = options;
|
|
104
|
+
|
|
105
|
+
if (!scrollViewRef?.current) return;
|
|
106
|
+
|
|
107
|
+
const targetY = yPosition - offset;
|
|
108
|
+
|
|
109
|
+
if (Platform.OS === "ios") {
|
|
110
|
+
scrollViewRef.current.scrollTo({ y: targetY, animated });
|
|
111
|
+
} else {
|
|
112
|
+
if (animated && duration) {
|
|
113
|
+
// For Android with custom duration
|
|
114
|
+
scrollViewRef.current.scrollTo({ y: targetY, animated: false });
|
|
115
|
+
// You might need a custom scroll animation library for smooth Android scrolling
|
|
116
|
+
} else {
|
|
117
|
+
scrollViewRef.current.scrollTo({ y: targetY, animated });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get element position relative to parent
|
|
124
|
+
* @param {Object} elementRef - Reference to element
|
|
125
|
+
* @returns {Promise<Object>} Position information
|
|
126
|
+
*/
|
|
127
|
+
export const getElementPosition = (elementRef) => {
|
|
128
|
+
return new Promise((resolve) => {
|
|
129
|
+
if (!elementRef?.current) {
|
|
130
|
+
resolve({ x: 0, y: 0, width: 0, height: 0 });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
elementRef.current.measure((x, y, width, height, pageX, pageY) => {
|
|
135
|
+
resolve({ x: pageX, y: pageY, width, height });
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const validateAnimationConfig = (config) => {
|
|
2
|
+
if (config.type === "timing") {
|
|
3
|
+
return !(config.duration !== undefined && config.duration <= 0);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
if (config.type === "spring") {
|
|
7
|
+
const { damping, mass, stiffness } = config;
|
|
8
|
+
return !(
|
|
9
|
+
(damping !== undefined && damping <= 0) ||
|
|
10
|
+
(mass !== undefined && mass <= 0) ||
|
|
11
|
+
(stiffness !== undefined && stiffness <= 0)
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return false;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const validateAccordionMode = (mode) => {
|
|
19
|
+
return mode === "single" || mode === "multiple";
|
|
20
|
+
};
|