@dryanovski/react-native-components 1.0.8 → 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.
Files changed (46) hide show
  1. package/lib/module/components/Accordion/Accordion.js +58 -0
  2. package/lib/module/components/Accordion/Accordion.js.map +1 -0
  3. package/lib/module/components/Accordion/AccordionContext.js +12 -0
  4. package/lib/module/components/Accordion/AccordionContext.js.map +1 -0
  5. package/lib/module/components/Accordion/AccordionItem.js +50 -0
  6. package/lib/module/components/Accordion/AccordionItem.js.map +1 -0
  7. package/lib/module/components/Accordion/style.js +11 -0
  8. package/lib/module/components/Accordion/style.js.map +1 -0
  9. package/lib/module/components/Accordion/type.js +4 -0
  10. package/lib/module/components/Accordion/type.js.map +1 -0
  11. package/lib/module/components/Collapse/Collapse.js +114 -0
  12. package/lib/module/components/Collapse/Collapse.js.map +1 -0
  13. package/lib/module/components/Collapse/index.js +5 -0
  14. package/lib/module/components/Collapse/index.js.map +1 -0
  15. package/lib/module/components/Collapse/types.js +4 -0
  16. package/lib/module/components/Collapse/types.js.map +1 -0
  17. package/lib/module/index.js +5 -0
  18. package/lib/module/index.js.map +1 -1
  19. package/lib/typescript/src/components/Accordion/Accordion.d.ts +4 -0
  20. package/lib/typescript/src/components/Accordion/Accordion.d.ts.map +1 -0
  21. package/lib/typescript/src/components/Accordion/AccordionContext.d.ts +12 -0
  22. package/lib/typescript/src/components/Accordion/AccordionContext.d.ts.map +1 -0
  23. package/lib/typescript/src/components/Accordion/AccordionItem.d.ts +5 -0
  24. package/lib/typescript/src/components/Accordion/AccordionItem.d.ts.map +1 -0
  25. package/lib/typescript/src/components/Accordion/style.d.ts +8 -0
  26. package/lib/typescript/src/components/Accordion/style.d.ts.map +1 -0
  27. package/lib/typescript/src/components/Accordion/type.d.ts +56 -0
  28. package/lib/typescript/src/components/Accordion/type.d.ts.map +1 -0
  29. package/lib/typescript/src/components/Collapse/Collapse.d.ts +14 -0
  30. package/lib/typescript/src/components/Collapse/Collapse.d.ts.map +1 -0
  31. package/lib/typescript/src/components/Collapse/index.d.ts +3 -0
  32. package/lib/typescript/src/components/Collapse/index.d.ts.map +1 -0
  33. package/lib/typescript/src/components/Collapse/types.d.ts +51 -0
  34. package/lib/typescript/src/components/Collapse/types.d.ts.map +1 -0
  35. package/lib/typescript/src/index.d.ts +5 -0
  36. package/lib/typescript/src/index.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/components/Accordion/Accordion.tsx +75 -0
  39. package/src/components/Accordion/AccordionContext.tsx +22 -0
  40. package/src/components/Accordion/AccordionItem.tsx +60 -0
  41. package/src/components/Accordion/style.ts +10 -0
  42. package/src/components/Accordion/type.ts +65 -0
  43. package/src/components/Collapse/Collapse.tsx +126 -0
  44. package/src/components/Collapse/index.ts +3 -0
  45. package/src/components/Collapse/types.ts +62 -0
  46. package/src/index.tsx +5 -0
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ import { forwardRef, useCallback, useMemo, useState } from 'react';
4
+ import { View } from 'react-native';
5
+ import { AccordionCtx } from "./AccordionContext.js";
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ export const Accordion = /*#__PURE__*/forwardRef((props, ref) => {
8
+ const {
9
+ children,
10
+ style,
11
+ singleExpand = true,
12
+ defaultExpandedIndices = [],
13
+ animation
14
+ } = props;
15
+ const [expandedIndices, setExpandedIndices] = useState(new Set(defaultExpandedIndices));
16
+ const toggleItem = useCallback(index => {
17
+ setExpandedIndices(prev => {
18
+ const newSet = new Set(prev);
19
+ if (singleExpand) {
20
+ // Single expand mode: only one item can be open at a time
21
+ if (newSet.has(index)) {
22
+ // If clicking the currently open item, close it
23
+ newSet.delete(index);
24
+ } else {
25
+ // Close all others and open this one
26
+ newSet.clear();
27
+ newSet.add(index);
28
+ }
29
+ } else {
30
+ // Multiple expand mode: toggle the clicked item
31
+ if (newSet.has(index)) {
32
+ newSet.delete(index);
33
+ } else {
34
+ newSet.add(index);
35
+ }
36
+ }
37
+ return newSet;
38
+ });
39
+ }, [singleExpand]);
40
+ const isItemExpanded = useCallback(index => expandedIndices.has(index), [expandedIndices]);
41
+ const contextValue = useMemo(() => ({
42
+ expandedIndices,
43
+ toggleItem,
44
+ isItemExpanded,
45
+ singleExpand,
46
+ animationConfig: animation
47
+ }), [expandedIndices, toggleItem, isItemExpanded, singleExpand, animation]);
48
+ return /*#__PURE__*/_jsx(AccordionCtx.Provider, {
49
+ value: contextValue,
50
+ children: /*#__PURE__*/_jsx(View, {
51
+ ref: ref,
52
+ style: style,
53
+ children: children
54
+ })
55
+ });
56
+ });
57
+ Accordion.displayName = 'Accordion';
58
+ //# sourceMappingURL=Accordion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["forwardRef","useCallback","useMemo","useState","View","AccordionCtx","jsx","_jsx","Accordion","props","ref","children","style","singleExpand","defaultExpandedIndices","animation","expandedIndices","setExpandedIndices","Set","toggleItem","index","prev","newSet","has","delete","clear","add","isItemExpanded","contextValue","animationConfig","Provider","value","displayName"],"sourceRoot":"../../../../src","sources":["components/Accordion/Accordion.tsx"],"mappings":";;AAAA,SAASA,UAAU,EAAEC,WAAW,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,OAAO;AAClE,SAASC,IAAI,QAAQ,cAAc;AAEnC,SAASC,YAAY,QAAoC,uBAAoB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAG9E,OAAO,MAAMC,SAAS,gBAAGR,UAAU,CAA0B,CAACS,KAAK,EAAEC,GAAG,KAAK;EAC3E,MAAM;IACJC,QAAQ;IACRC,KAAK;IACLC,YAAY,GAAG,IAAI;IACnBC,sBAAsB,GAAG,EAAE;IAC3BC;EACF,CAAC,GAAGN,KAAK;EAET,MAAM,CAACO,eAAe,EAAEC,kBAAkB,CAAC,GAAGd,QAAQ,CACpD,IAAIe,GAAG,CAACJ,sBAAsB,CAChC,CAAC;EAED,MAAMK,UAAU,GAAGlB,WAAW,CAC3BmB,KAAa,IAAK;IACjBH,kBAAkB,CAAEI,IAAI,IAAK;MAC3B,MAAMC,MAAM,GAAG,IAAIJ,GAAG,CAACG,IAAI,CAAC;MAE5B,IAAIR,YAAY,EAAE;QAChB;QACA,IAAIS,MAAM,CAACC,GAAG,CAACH,KAAK,CAAC,EAAE;UACrB;UACAE,MAAM,CAACE,MAAM,CAACJ,KAAK,CAAC;QACtB,CAAC,MAAM;UACL;UACAE,MAAM,CAACG,KAAK,CAAC,CAAC;UACdH,MAAM,CAACI,GAAG,CAACN,KAAK,CAAC;QACnB;MACF,CAAC,MAAM;QACL;QACA,IAAIE,MAAM,CAACC,GAAG,CAACH,KAAK,CAAC,EAAE;UACrBE,MAAM,CAACE,MAAM,CAACJ,KAAK,CAAC;QACtB,CAAC,MAAM;UACLE,MAAM,CAACI,GAAG,CAACN,KAAK,CAAC;QACnB;MACF;MAEA,OAAOE,MAAM;IACf,CAAC,CAAC;EACJ,CAAC,EACD,CAACT,YAAY,CACf,CAAC;EAED,MAAMc,cAAc,GAAG1B,WAAW,CAC/BmB,KAAa,IAAKJ,eAAe,CAACO,GAAG,CAACH,KAAK,CAAC,EAC7C,CAACJ,eAAe,CAClB,CAAC;EAED,MAAMY,YAAY,GAAG1B,OAAO,CAC1B,OAAO;IACLc,eAAe;IACfG,UAAU;IACVQ,cAAc;IACdd,YAAY;IACZgB,eAAe,EAAEd;EACnB,CAAC,CAAC,EACF,CAACC,eAAe,EAAEG,UAAU,EAAEQ,cAAc,EAAEd,YAAY,EAAEE,SAAS,CACvE,CAAC;EAED,oBACER,IAAA,CAACF,YAAY,CAACyB,QAAQ;IAACC,KAAK,EAAEH,YAAa;IAAAjB,QAAA,eACzCJ,IAAA,CAACH,IAAI;MAACM,GAAG,EAAEA,GAAI;MAACE,KAAK,EAAEA,KAAM;MAAAD,QAAA,EAC1BA;IAAQ,CACL;EAAC,CACc,CAAC;AAE5B,CAAC,CAAC;AAEFH,SAAS,CAACwB,WAAW,GAAG,WAAW","ignoreList":[]}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ export const AccordionCtx = /*#__PURE__*/React.createContext(undefined);
5
+ export const useAccordionContext = () => {
6
+ const context = React.useContext(AccordionCtx);
7
+ if (!context) {
8
+ throw new Error('AccordionItem must be used within an Accordion component');
9
+ }
10
+ return context;
11
+ };
12
+ //# sourceMappingURL=AccordionContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","AccordionCtx","createContext","undefined","useAccordionContext","context","useContext","Error"],"sourceRoot":"../../../../src","sources":["components/Accordion/AccordionContext.tsx"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AAWzB,OAAO,MAAMC,YAAY,gBAAGD,KAAK,CAACE,aAAa,CAE7CC,SAAS,CAAC;AAEZ,OAAO,MAAMC,mBAAmB,GAAGA,CAAA,KAAM;EACvC,MAAMC,OAAO,GAAGL,KAAK,CAACM,UAAU,CAACL,YAAY,CAAC;EAC9C,IAAI,CAACI,OAAO,EAAE;IACZ,MAAM,IAAIE,KAAK,CAAC,0DAA0D,CAAC;EAC7E;EACA,OAAOF,OAAO;AAChB,CAAC","ignoreList":[]}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ import { forwardRef, useCallback, useMemo } from 'react';
4
+ import { Text, TouchableOpacity, View } from 'react-native';
5
+ import { Collapse } from "../Collapse/index.js";
6
+ import { useAccordionContext } from "./AccordionContext.js";
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ export let itemIndexCounter = 0;
9
+ export const AccordionItem = /*#__PURE__*/forwardRef((props, ref) => {
10
+ const {
11
+ children,
12
+ title,
13
+ onPress,
14
+ isExpanded: externalIsExpanded,
15
+ style
16
+ } = props;
17
+ const {
18
+ toggleItem,
19
+ isItemExpanded,
20
+ animationConfig
21
+ } = useAccordionContext();
22
+
23
+ // Assign a unique index to this item
24
+ const itemIndex = useMemo(() => itemIndexCounter++, []);
25
+
26
+ // Use external isExpanded if provided, otherwise use context state
27
+ const isExpanded = externalIsExpanded !== undefined ? externalIsExpanded : isItemExpanded(itemIndex);
28
+ const handlePress = useCallback(event => {
29
+ if (onPress) {
30
+ onPress(event);
31
+ }
32
+ toggleItem(itemIndex);
33
+ }, [onPress, toggleItem, itemIndex]);
34
+ return /*#__PURE__*/_jsxs(View, {
35
+ ref: ref,
36
+ style: style,
37
+ children: [/*#__PURE__*/_jsx(TouchableOpacity, {
38
+ onPress: handlePress,
39
+ children: /*#__PURE__*/_jsx(Text, {
40
+ children: title
41
+ })
42
+ }), /*#__PURE__*/_jsx(Collapse, {
43
+ isExpanded: isExpanded,
44
+ animationConfig: animationConfig,
45
+ children: children
46
+ })]
47
+ });
48
+ });
49
+ AccordionItem.displayName = 'AccordionItem';
50
+ //# sourceMappingURL=AccordionItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["forwardRef","useCallback","useMemo","Text","TouchableOpacity","View","Collapse","useAccordionContext","jsx","_jsx","jsxs","_jsxs","itemIndexCounter","AccordionItem","props","ref","children","title","onPress","isExpanded","externalIsExpanded","style","toggleItem","isItemExpanded","animationConfig","itemIndex","undefined","handlePress","event","displayName"],"sourceRoot":"../../../../src","sources":["components/Accordion/AccordionItem.tsx"],"mappings":";;AAAA,SAASA,UAAU,EAAEC,WAAW,EAAEC,OAAO,QAAQ,OAAO;AACxD,SACEC,IAAI,EACJC,gBAAgB,EAChBC,IAAI,QAEC,cAAc;AAErB,SAASC,QAAQ,QAAQ,sBAAa;AACtC,SAASC,mBAAmB,QAAQ,uBAAoB;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAGzD,OAAO,IAAIC,gBAAgB,GAAG,CAAC;AAE/B,OAAO,MAAMC,aAAa,gBAAGb,UAAU,CACrC,CAACc,KAAK,EAAEC,GAAG,KAAK;EACd,MAAM;IACJC,QAAQ;IACRC,KAAK;IACLC,OAAO;IACPC,UAAU,EAAEC,kBAAkB;IAC9BC;EACF,CAAC,GAAGP,KAAK;EAET,MAAM;IAAEQ,UAAU;IAAEC,cAAc;IAAEC;EAAgB,CAAC,GACnDjB,mBAAmB,CAAC,CAAC;;EAEvB;EACA,MAAMkB,SAAS,GAAGvB,OAAO,CAAC,MAAMU,gBAAgB,EAAE,EAAE,EAAE,CAAC;;EAEvD;EACA,MAAMO,UAAU,GACdC,kBAAkB,KAAKM,SAAS,GAC5BN,kBAAkB,GAClBG,cAAc,CAACE,SAAS,CAAC;EAE/B,MAAME,WAAW,GAAG1B,WAAW,CAC5B2B,KAA4B,IAAK;IAChC,IAAIV,OAAO,EAAE;MACXA,OAAO,CAACU,KAAK,CAAC;IAChB;IACAN,UAAU,CAACG,SAAS,CAAC;EACvB,CAAC,EACD,CAACP,OAAO,EAAEI,UAAU,EAAEG,SAAS,CACjC,CAAC;EAED,oBACEd,KAAA,CAACN,IAAI;IAACU,GAAG,EAAEA,GAAI;IAACM,KAAK,EAAEA,KAAM;IAAAL,QAAA,gBAC3BP,IAAA,CAACL,gBAAgB;MAACc,OAAO,EAAES,WAAY;MAAAX,QAAA,eACrCP,IAAA,CAACN,IAAI;QAAAa,QAAA,EAAEC;MAAK,CAAO;IAAC,CACJ,CAAC,eACnBR,IAAA,CAACH,QAAQ;MAACa,UAAU,EAAEA,UAAW;MAACK,eAAe,EAAEA,eAAgB;MAAAR,QAAA,EAChEA;IAAQ,CACD,CAAC;EAAA,CACP,CAAC;AAEX,CACF,CAAC;AAEDH,aAAa,CAACgB,WAAW,GAAG,eAAe","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ import { StyleSheet } from 'react-native';
4
+ export const accordionStyles = StyleSheet.create({
5
+ measurementView: {
6
+ position: 'absolute',
7
+ opacity: 0,
8
+ zIndex: -1
9
+ }
10
+ });
11
+ //# sourceMappingURL=style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["StyleSheet","accordionStyles","create","measurementView","position","opacity","zIndex"],"sourceRoot":"../../../../src","sources":["components/Accordion/style.ts"],"mappings":";;AAAA,SAASA,UAAU,QAAQ,cAAc;AAEzC,OAAO,MAAMC,eAAe,GAAGD,UAAU,CAACE,MAAM,CAAC;EAC/CC,eAAe,EAAE;IACfC,QAAQ,EAAE,UAAU;IACpBC,OAAO,EAAE,CAAC;IACVC,MAAM,EAAE,CAAC;EACX;AACF,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["components/Accordion/type.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+
3
+ import { useCallback, useEffect, useState } from 'react';
4
+ import { View } from 'react-native';
5
+ import Animated, { useAnimatedStyle, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ const DEFAULT_ANIMATION = {
8
+ type: 'timing',
9
+ duration: 100
10
+ };
11
+ const DEFAULT_SPRING = {
12
+ damping: 20,
13
+ stiffness: 300
14
+ };
15
+
16
+ /**
17
+ * Collapse - A reusable component for smooth expand/collapse animations
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * <Collapse isExpanded={isOpen}>
22
+ * <Text>Your content here</Text>
23
+ * </Collapse>
24
+ * ```
25
+ */
26
+ export const Collapse = ({
27
+ isExpanded,
28
+ children,
29
+ animationConfig,
30
+ style,
31
+ contentStyle,
32
+ onMeasured
33
+ }) => {
34
+ const [contentHeight, setContentHeight] = useState(null);
35
+ const [shouldRender, setShouldRender] = useState(isExpanded);
36
+ const heightValue = useSharedValue(isExpanded ? 'auto' : 0);
37
+ const opacityValue = useSharedValue(isExpanded ? 1 : 0);
38
+ const config = animationConfig || DEFAULT_ANIMATION;
39
+ const isSpring = config.type === 'spring';
40
+ const duration = config.duration || 100;
41
+
42
+ // Measure content height
43
+ const onLayout = useCallback(event => {
44
+ const {
45
+ height
46
+ } = event.nativeEvent.layout;
47
+ if (height > 0 && contentHeight !== height) {
48
+ setContentHeight(height);
49
+ onMeasured?.(height);
50
+ }
51
+ }, [contentHeight, onMeasured]);
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
+ if (isSpring) {
72
+ const springConfig = config.springConfig || DEFAULT_SPRING;
73
+ heightValue.value = withSpring(targetHeight, springConfig);
74
+ opacityValue.value = withSpring(targetOpacity, springConfig);
75
+
76
+ // Remove from DOM after collapse animation
77
+ if (!isExpanded) {
78
+ const stiffness = springConfig.stiffness || 300;
79
+ const damping = springConfig.damping || 20;
80
+ const settleTime = 1000 / stiffness * damping * 10;
81
+ setTimeout(() => setShouldRender(false), settleTime);
82
+ }
83
+ } else {
84
+ const timingConfig = 'timingConfig' in config && config.timingConfig ? config.timingConfig : {
85
+ duration
86
+ };
87
+ heightValue.value = withTiming(targetHeight, timingConfig);
88
+ opacityValue.value = withTiming(targetOpacity, timingConfig);
89
+
90
+ // Remove from DOM after collapse animation
91
+ if (!isExpanded) {
92
+ setTimeout(() => setShouldRender(false), duration);
93
+ }
94
+ }
95
+ }, [isExpanded, contentHeight, isSpring, duration, config, heightValue, opacityValue]);
96
+ const animatedStyle = useAnimatedStyle(() => ({
97
+ height: heightValue.value,
98
+ opacity: opacityValue.value,
99
+ overflow: 'hidden'
100
+ }));
101
+ if (!shouldRender) {
102
+ return null;
103
+ }
104
+ return /*#__PURE__*/_jsx(Animated.View, {
105
+ style: [animatedStyle, style],
106
+ children: /*#__PURE__*/_jsx(View, {
107
+ onLayout: onLayout,
108
+ style: contentStyle,
109
+ children: children
110
+ })
111
+ });
112
+ };
113
+ Collapse.displayName = 'Collapse';
114
+ //# sourceMappingURL=Collapse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useCallback","useEffect","useState","View","Animated","useAnimatedStyle","useSharedValue","withSpring","withTiming","jsx","_jsx","DEFAULT_ANIMATION","type","duration","DEFAULT_SPRING","damping","stiffness","Collapse","isExpanded","children","animationConfig","style","contentStyle","onMeasured","contentHeight","setContentHeight","shouldRender","setShouldRender","heightValue","opacityValue","config","isSpring","onLayout","event","height","nativeEvent","layout","value","targetHeight","targetOpacity","springConfig","settleTime","setTimeout","timingConfig","animatedStyle","opacity","overflow","displayName"],"sourceRoot":"../../../../src","sources":["components/Collapse/Collapse.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ export * from "./Collapse.js";
4
+ export * from "./types.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["components/Collapse/index.ts"],"mappings":";;AAAA,cAAc,eAAY;AAC1B,cAAc,YAAS","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["components/Collapse/types.ts"],"mappings":"","ignoreList":[]}
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
 
3
3
  // Export Components
4
+ export * from "./components/Accordion/Accordion.js";
5
+ export * from "./components/Accordion/AccordionItem.js";
6
+ export * from "./components/Collapse/index.js";
4
7
  export * from "./components/Button/Button.js";
5
8
  export * from "./components/Button/DangerButton.js";
6
9
  export * from "./components/Button/GhostButton.js";
@@ -13,6 +16,8 @@ export * from "./components/Layout/VStack.js";
13
16
  export * from "./components/Surface/Surface.js";
14
17
 
15
18
  // types
19
+ export * from "./components/Accordion/type.js";
20
+ export * from "./components/Collapse/types.js";
16
21
  export * from "./components/Button/types.js";
17
22
  export * from "./components/Card/types.js";
18
23
  export * from "./components/Divider/types.js";
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA;AACA,cAAc,+BAA4B;AAC1C,cAAc,qCAAkC;AAChD,cAAc,oCAAiC;AAC/C,cAAc,sCAAmC;AACjD,cAAc,wCAAqC;AACnD,cAAc,2BAAwB;AACtC,cAAc,iCAA8B;AAC5C,cAAc,+BAA4B;AAC1C,cAAc,+BAA4B;AAC1C,cAAc,iCAA8B;;AAE5C;AACA,cAAc,8BAA2B;AACzC,cAAc,4BAAyB;AACvC,cAAc,+BAA4B;AAC1C,cAAc,qCAAkC;AAChD,cAAc,+BAA4B;AAC1C,cAAc,0BAAuB;;AAErC;AACA,cAAc,8BAA2B","ignoreList":[]}
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA;AACA,cAAc,qCAAkC;AAChD,cAAc,yCAAsC;AACpD,cAAc,gCAAuB;AACrC,cAAc,+BAA4B;AAC1C,cAAc,qCAAkC;AAChD,cAAc,oCAAiC;AAC/C,cAAc,sCAAmC;AACjD,cAAc,wCAAqC;AACnD,cAAc,2BAAwB;AACtC,cAAc,iCAA8B;AAC5C,cAAc,+BAA4B;AAC1C,cAAc,+BAA4B;AAC1C,cAAc,iCAA8B;;AAE5C;AACA,cAAc,gCAA6B;AAC3C,cAAc,gCAA6B;AAC3C,cAAc,8BAA2B;AACzC,cAAc,4BAAyB;AACvC,cAAc,+BAA4B;AAC1C,cAAc,qCAAkC;AAChD,cAAc,+BAA4B;AAC1C,cAAc,0BAAuB;;AAErC;AACA,cAAc,8BAA2B","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ import { View } from 'react-native';
2
+ import type { AccordionProps } from './type';
3
+ export declare const Accordion: import("react").ForwardRefExoticComponent<AccordionProps & import("react").RefAttributes<View>>;
4
+ //# sourceMappingURL=Accordion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../../../src/components/Accordion/Accordion.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAGpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,SAAS,iGAkEpB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { AnimationConfig } from '../Collapse/types';
3
+ export type AccordionContextValue = {
4
+ expandedIndices: Set<number>;
5
+ toggleItem: (index: number) => void;
6
+ isItemExpanded: (index: number) => boolean;
7
+ singleExpand: boolean;
8
+ animationConfig?: AnimationConfig;
9
+ };
10
+ export declare const AccordionCtx: React.Context<AccordionContextValue | undefined>;
11
+ export declare const useAccordionContext: () => AccordionContextValue;
12
+ //# sourceMappingURL=AccordionContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccordionContext.d.ts","sourceRoot":"","sources":["../../../../../src/components/Accordion/AccordionContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,YAAY,kDAEb,CAAC;AAEb,eAAO,MAAM,mBAAmB,6BAM/B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { View } from 'react-native';
2
+ import type { AccordionItemProps } from './type';
3
+ export declare let itemIndexCounter: number;
4
+ export declare const AccordionItem: import("react").ForwardRefExoticComponent<AccordionItemProps & import("react").RefAttributes<View>>;
5
+ //# sourceMappingURL=AccordionItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccordionItem.d.ts","sourceRoot":"","sources":["../../../../../src/components/Accordion/AccordionItem.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,IAAI,EAEL,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD,eAAO,IAAI,gBAAgB,QAAI,CAAC;AAEhC,eAAO,MAAM,aAAa,qGA2CzB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare const accordionStyles: {
2
+ measurementView: {
3
+ position: "absolute";
4
+ opacity: number;
5
+ zIndex: number;
6
+ };
7
+ };
8
+ //# sourceMappingURL=style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../../../../src/components/Accordion/style.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe;;;;;;CAM1B,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { StyleProp, TouchableOpacityProps, ViewStyle } from 'react-native';
2
+ import type { AnimationConfig } from '../Collapse/types';
3
+ export type AccordionProps = {
4
+ /**
5
+ * Style for the accordion component.
6
+ * Optional.
7
+ */
8
+ style?: StyleProp<ViewStyle>;
9
+ /**
10
+ * Content of the accordion (AccordionItems).
11
+ */
12
+ children?: React.ReactNode;
13
+ /**
14
+ * Whether only one item can be expanded at a time.
15
+ * If true, expanding one item will collapse all others.
16
+ * If false, multiple items can be expanded simultaneously.
17
+ * @default true
18
+ */
19
+ singleExpand?: boolean;
20
+ /**
21
+ * Initially expanded item indices.
22
+ * Optional.
23
+ */
24
+ defaultExpandedIndices?: number[];
25
+ /**
26
+ * Animation configuration for expanding/collapsing items.
27
+ * @default { type: 'timing', duration: 100 }
28
+ */
29
+ animation?: AnimationConfig;
30
+ };
31
+ export type AccordionItemProps = {
32
+ /**
33
+ * Style for the accordion item component.
34
+ * Optional.
35
+ */
36
+ style?: StyleProp<ViewStyle>;
37
+ /**
38
+ * Content of the accordion item.
39
+ */
40
+ children?: React.ReactNode;
41
+ /**
42
+ * Title of the accordion item.
43
+ */
44
+ title: string;
45
+ /**
46
+ * Function to be called when the accordion item is pressed.
47
+ */
48
+ onPress?: TouchableOpacityProps['onPress'];
49
+ /**
50
+ * Whether the accordion item is expanded.
51
+ * This is controlled internally by the Accordion context.
52
+ * Optional - for external control.
53
+ */
54
+ isExpanded?: boolean;
55
+ };
56
+ //# sourceMappingURL=type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../../../src/components/Accordion/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAElC;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAE3C;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type FC } from 'react';
2
+ import type { CollapseProps } from './types';
3
+ /**
4
+ * Collapse - A reusable component for smooth expand/collapse animations
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * <Collapse isExpanded={isOpen}>
9
+ * <Text>Your content here</Text>
10
+ * </Collapse>
11
+ * ```
12
+ */
13
+ export declare const Collapse: FC<CollapseProps>;
14
+ //# sourceMappingURL=Collapse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collapse.d.ts","sourceRoot":"","sources":["../../../../../src/components/Collapse/Collapse.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAQlE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAK7C;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,CAoGtC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './Collapse';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Collapse/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+ import type { WithSpringConfig, WithTimingConfig } from 'react-native-reanimated';
3
+ export type AnimationType = 'timing' | 'spring';
4
+ export type AnimationConfig = {
5
+ /**
6
+ * Type of animation to use.
7
+ * @default 'timing'
8
+ */
9
+ type?: AnimationType;
10
+ /**
11
+ * Duration of the animation in milliseconds (for timing animation).
12
+ * @default 100
13
+ */
14
+ duration?: number;
15
+ /**
16
+ * Timing animation configuration.
17
+ */
18
+ timingConfig?: WithTimingConfig;
19
+ /**
20
+ * Spring animation configuration.
21
+ */
22
+ springConfig?: WithSpringConfig;
23
+ };
24
+ export type CollapseProps = {
25
+ /**
26
+ * Whether the content is expanded or collapsed.
27
+ */
28
+ isExpanded: boolean;
29
+ /**
30
+ * Content to animate.
31
+ */
32
+ children: React.ReactNode;
33
+ /**
34
+ * Animation configuration.
35
+ * @default { type: 'timing', duration: 100 }
36
+ */
37
+ animationConfig?: AnimationConfig;
38
+ /**
39
+ * Style for the animated container.
40
+ */
41
+ style?: StyleProp<ViewStyle>;
42
+ /**
43
+ * Style for the content wrapper.
44
+ */
45
+ contentStyle?: StyleProp<ViewStyle>;
46
+ /**
47
+ * Callback when measurement is complete.
48
+ */
49
+ onMeasured?: (height: number) => void;
50
+ };
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/components/Collapse/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAElF,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IAErB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAEhC;;OAEG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,UAAU,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAE1B;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAElC;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE7B;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAEpC;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC"}
@@ -1,3 +1,6 @@
1
+ export * from './components/Accordion/Accordion';
2
+ export * from './components/Accordion/AccordionItem';
3
+ export * from './components/Collapse';
1
4
  export * from './components/Button/Button';
2
5
  export * from './components/Button/DangerButton';
3
6
  export * from './components/Button/GhostButton';
@@ -8,6 +11,8 @@ export * from './components/Divider/Divider';
8
11
  export * from './components/Layout/HStack';
9
12
  export * from './components/Layout/VStack';
10
13
  export * from './components/Surface/Surface';
14
+ export * from './components/Accordion/type';
15
+ export * from './components/Collapse/types';
11
16
  export * from './components/Button/types';
12
17
  export * from './components/Card/types';
13
18
  export * from './components/Divider/types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAG7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AAGtC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,cAAc,kCAAkC,CAAC;AACjD,cAAc,sCAAsC,CAAC;AACrD,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAG7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AAGtC,cAAc,2BAA2B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dryanovski/react-native-components",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Collection of reusable React Native components for building mobile applications.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -0,0 +1,75 @@
1
+ import { forwardRef, useCallback, useMemo, useState } from 'react';
2
+ import { View } from 'react-native';
3
+ import type { ViewRef } from '../../types/general.types';
4
+ import { AccordionCtx, type AccordionContextValue } from './AccordionContext';
5
+ import type { AccordionProps } from './type';
6
+
7
+ export const Accordion = forwardRef<ViewRef, AccordionProps>((props, ref) => {
8
+ const {
9
+ children,
10
+ style,
11
+ singleExpand = true,
12
+ defaultExpandedIndices = [],
13
+ animation,
14
+ } = props;
15
+
16
+ const [expandedIndices, setExpandedIndices] = useState<Set<number>>(
17
+ new Set(defaultExpandedIndices)
18
+ );
19
+
20
+ const toggleItem = useCallback(
21
+ (index: number) => {
22
+ setExpandedIndices((prev) => {
23
+ const newSet = new Set(prev);
24
+
25
+ if (singleExpand) {
26
+ // Single expand mode: only one item can be open at a time
27
+ if (newSet.has(index)) {
28
+ // If clicking the currently open item, close it
29
+ newSet.delete(index);
30
+ } else {
31
+ // Close all others and open this one
32
+ newSet.clear();
33
+ newSet.add(index);
34
+ }
35
+ } else {
36
+ // Multiple expand mode: toggle the clicked item
37
+ if (newSet.has(index)) {
38
+ newSet.delete(index);
39
+ } else {
40
+ newSet.add(index);
41
+ }
42
+ }
43
+
44
+ return newSet;
45
+ });
46
+ },
47
+ [singleExpand]
48
+ );
49
+
50
+ const isItemExpanded = useCallback(
51
+ (index: number) => expandedIndices.has(index),
52
+ [expandedIndices]
53
+ );
54
+
55
+ const contextValue = useMemo<AccordionContextValue>(
56
+ () => ({
57
+ expandedIndices,
58
+ toggleItem,
59
+ isItemExpanded,
60
+ singleExpand,
61
+ animationConfig: animation,
62
+ }),
63
+ [expandedIndices, toggleItem, isItemExpanded, singleExpand, animation]
64
+ );
65
+
66
+ return (
67
+ <AccordionCtx.Provider value={contextValue}>
68
+ <View ref={ref} style={style}>
69
+ {children}
70
+ </View>
71
+ </AccordionCtx.Provider>
72
+ );
73
+ });
74
+
75
+ Accordion.displayName = 'Accordion';
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import type { AnimationConfig } from '../Collapse/types';
3
+
4
+ export type AccordionContextValue = {
5
+ expandedIndices: Set<number>;
6
+ toggleItem: (index: number) => void;
7
+ isItemExpanded: (index: number) => boolean;
8
+ singleExpand: boolean;
9
+ animationConfig?: AnimationConfig;
10
+ };
11
+
12
+ export const AccordionCtx = React.createContext<
13
+ AccordionContextValue | undefined
14
+ >(undefined);
15
+
16
+ export const useAccordionContext = () => {
17
+ const context = React.useContext(AccordionCtx);
18
+ if (!context) {
19
+ throw new Error('AccordionItem must be used within an Accordion component');
20
+ }
21
+ return context;
22
+ };
@@ -0,0 +1,60 @@
1
+ import { forwardRef, useCallback, useMemo } from 'react';
2
+ import {
3
+ Text,
4
+ TouchableOpacity,
5
+ View,
6
+ type GestureResponderEvent,
7
+ } from 'react-native';
8
+ import type { ViewRef } from '../../types/general.types';
9
+ import { Collapse } from '../Collapse';
10
+ import { useAccordionContext } from './AccordionContext';
11
+ import type { AccordionItemProps } from './type';
12
+
13
+ export let itemIndexCounter = 0;
14
+
15
+ export const AccordionItem = forwardRef<ViewRef, AccordionItemProps>(
16
+ (props, ref) => {
17
+ const {
18
+ children,
19
+ title,
20
+ onPress,
21
+ isExpanded: externalIsExpanded,
22
+ style,
23
+ } = props;
24
+
25
+ const { toggleItem, isItemExpanded, animationConfig } =
26
+ useAccordionContext();
27
+
28
+ // Assign a unique index to this item
29
+ const itemIndex = useMemo(() => itemIndexCounter++, []);
30
+
31
+ // Use external isExpanded if provided, otherwise use context state
32
+ const isExpanded =
33
+ externalIsExpanded !== undefined
34
+ ? externalIsExpanded
35
+ : isItemExpanded(itemIndex);
36
+
37
+ const handlePress = useCallback(
38
+ (event: GestureResponderEvent) => {
39
+ if (onPress) {
40
+ onPress(event);
41
+ }
42
+ toggleItem(itemIndex);
43
+ },
44
+ [onPress, toggleItem, itemIndex]
45
+ );
46
+
47
+ return (
48
+ <View ref={ref} style={style}>
49
+ <TouchableOpacity onPress={handlePress}>
50
+ <Text>{title}</Text>
51
+ </TouchableOpacity>
52
+ <Collapse isExpanded={isExpanded} animationConfig={animationConfig}>
53
+ {children}
54
+ </Collapse>
55
+ </View>
56
+ );
57
+ }
58
+ );
59
+
60
+ AccordionItem.displayName = 'AccordionItem';
@@ -0,0 +1,10 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ export const accordionStyles = StyleSheet.create({
4
+ measurementView: {
5
+ position: 'absolute',
6
+ opacity: 0,
7
+ zIndex: -1,
8
+ },
9
+ });
10
+
@@ -0,0 +1,65 @@
1
+ import type { StyleProp, TouchableOpacityProps, ViewStyle } from 'react-native';
2
+ import type { AnimationConfig } from '../Collapse/types';
3
+
4
+ export type AccordionProps = {
5
+ /**
6
+ * Style for the accordion component.
7
+ * Optional.
8
+ */
9
+ style?: StyleProp<ViewStyle>;
10
+
11
+ /**
12
+ * Content of the accordion (AccordionItems).
13
+ */
14
+ children?: React.ReactNode;
15
+
16
+ /**
17
+ * Whether only one item can be expanded at a time.
18
+ * If true, expanding one item will collapse all others.
19
+ * If false, multiple items can be expanded simultaneously.
20
+ * @default true
21
+ */
22
+ singleExpand?: boolean;
23
+
24
+ /**
25
+ * Initially expanded item indices.
26
+ * Optional.
27
+ */
28
+ defaultExpandedIndices?: number[];
29
+
30
+ /**
31
+ * Animation configuration for expanding/collapsing items.
32
+ * @default { type: 'timing', duration: 100 }
33
+ */
34
+ animation?: AnimationConfig;
35
+ };
36
+
37
+ export type AccordionItemProps = {
38
+ /**
39
+ * Style for the accordion item component.
40
+ * Optional.
41
+ */
42
+ style?: StyleProp<ViewStyle>;
43
+
44
+ /**
45
+ * Content of the accordion item.
46
+ */
47
+ children?: React.ReactNode;
48
+
49
+ /**
50
+ * Title of the accordion item.
51
+ */
52
+ title: string;
53
+
54
+ /**
55
+ * Function to be called when the accordion item is pressed.
56
+ */
57
+ onPress?: TouchableOpacityProps['onPress'];
58
+
59
+ /**
60
+ * Whether the accordion item is expanded.
61
+ * This is controlled internally by the Accordion context.
62
+ * Optional - for external control.
63
+ */
64
+ isExpanded?: boolean;
65
+ };
@@ -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,3 @@
1
+ export * from './Collapse';
2
+ export * from './types';
3
+
@@ -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
+
package/src/index.tsx CHANGED
@@ -1,4 +1,7 @@
1
1
  // Export Components
2
+ export * from './components/Accordion/Accordion';
3
+ export * from './components/Accordion/AccordionItem';
4
+ export * from './components/Collapse';
2
5
  export * from './components/Button/Button';
3
6
  export * from './components/Button/DangerButton';
4
7
  export * from './components/Button/GhostButton';
@@ -11,6 +14,8 @@ export * from './components/Layout/VStack';
11
14
  export * from './components/Surface/Surface';
12
15
 
13
16
  // types
17
+ export * from './components/Accordion/type';
18
+ export * from './components/Collapse/types';
14
19
  export * from './components/Button/types';
15
20
  export * from './components/Card/types';
16
21
  export * from './components/Divider/types';