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
package/README.md
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
# react-native-pro-accordion
|
|
2
|
+
|
|
3
|
+
**A feature-rich React Native accordion component with advanced animations, full accessibility, and a powerful theme system.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ✨ Features
|
|
8
|
+
|
|
9
|
+
| Category | Features |
|
|
10
|
+
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| **Core** | Single & Multiple expansion modes, Controlled & Uncontrolled state, Default expanded items, Expand/Collapse all, Disabled items, Read-only mode |
|
|
12
|
+
| **Animation** | Spring & Timing animations, Custom duration & easing, Animated icons, Smooth height detection |
|
|
13
|
+
| **UI** | Custom headers & content, Left/Right icon positioning, Item separators, Nested accordions, Per-item style overrides |
|
|
14
|
+
| **Theme** | Light/Dark mode, Custom theme object, Global ThemeProvider |
|
|
15
|
+
| **Performance** | Memoized components, Lazy rendering, Optimized via Reanimated v3 |
|
|
16
|
+
| **Accessibility** | VoiceOver & TalkBack, Keyboard navigation, ARIA labels, Focus management |
|
|
17
|
+
| **DX** | Full TypeScript support, Ref methods, Event callbacks, JSDoc comments |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 📦 Installation
|
|
22
|
+
|
|
23
|
+
Install directly from the local package (update the path to match your project structure):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# npm
|
|
27
|
+
npm install react-native-pro-accordion
|
|
28
|
+
|
|
29
|
+
# yarn
|
|
30
|
+
yarn add react-native-pro-accordion
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> **Note:** This package uses [Reanimated v3](https://docs.swmansion.com/react-native-reanimated/). Make sure it is installed and configured in your project before using this library.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 🚀 Quick Start
|
|
38
|
+
|
|
39
|
+
```jsx
|
|
40
|
+
import React from "react";
|
|
41
|
+
import { View, Text } from "react-native";
|
|
42
|
+
import { Accordion, AccordionItem } from "react-native-pro-accordion";
|
|
43
|
+
|
|
44
|
+
export default function App() {
|
|
45
|
+
return (
|
|
46
|
+
<Accordion mode="multiple" defaultValue={["item1"]}>
|
|
47
|
+
<AccordionItem value="item1" header={<Text>Section 1</Text>}>
|
|
48
|
+
<Text>Content for section 1</Text>
|
|
49
|
+
</AccordionItem>
|
|
50
|
+
|
|
51
|
+
<AccordionItem value="item2" header={<Text>Section 2</Text>}>
|
|
52
|
+
<Text>Content for section 2</Text>
|
|
53
|
+
</AccordionItem>
|
|
54
|
+
</Accordion>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 📚 API Reference
|
|
62
|
+
|
|
63
|
+
### Accordion Props
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Default | Description |
|
|
66
|
+
| -------------------- | ----------------------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------ |
|
|
67
|
+
| `children` | `ReactNode` | **Required** | `AccordionItem` components |
|
|
68
|
+
| `mode` | `'single' \| 'multiple'` | `'single'` | Controls whether one or many items can be expanded at a time |
|
|
69
|
+
| `value` | `string[]` | `undefined` | Controlled list of expanded item values |
|
|
70
|
+
| `defaultValue` | `string[]` | `[]` | Initially expanded items (uncontrolled mode) |
|
|
71
|
+
| `onChange` | `(values: string[]) => void` | `undefined` | Fires when the expanded state changes |
|
|
72
|
+
| `readOnly` | `boolean` | `false` | Disables all user interactions |
|
|
73
|
+
| `animation` | `AnimationConfig` | `{ type: 'timing', duration: 300 }` | Animation configuration |
|
|
74
|
+
| `renderIcon` | `(props: { expanded: boolean, disabled?: boolean }) => ReactNode` | `undefined` | Custom icon renderer |
|
|
75
|
+
| `iconPosition` | `'left' \| 'right'` | `'right'` | Position of the expand/collapse icon |
|
|
76
|
+
| `showSeparators` | `boolean` | `false` | Render separators between items |
|
|
77
|
+
| `separatorComponent` | `ReactNode` | `undefined` | Custom separator component |
|
|
78
|
+
| `separatorStyle` | `ViewStyle` | `undefined` | Style applied to the default separator |
|
|
79
|
+
| `lazyRender` | `boolean` | `false` | Only render item content when first expanded |
|
|
80
|
+
| `darkMode` | `boolean` | `false` | Enable the built-in dark theme |
|
|
81
|
+
| `theme` | `Partial<AccordionTheme>` | `undefined` | Custom theme object |
|
|
82
|
+
| `onOpen` | `(value: string, data?: any) => void` | `undefined` | Called when an item opens |
|
|
83
|
+
| `onClose` | `(value: string, data?: any) => void` | `undefined` | Called when an item closes |
|
|
84
|
+
| `onToggle` | `(value: string, expanded: boolean, data?: any) => void` | `undefined` | Called when an item toggles |
|
|
85
|
+
| `onAnimationStart` | `(value: string, expanded: boolean) => void` | `undefined` | Called when an animation begins |
|
|
86
|
+
| `onAnimationEnd` | `(value: string, expanded: boolean) => void` | `undefined` | Called when an animation completes |
|
|
87
|
+
| `onStateChange` | `(expandedValues: string[]) => void` | `undefined` | Called whenever expanded state changes |
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### AccordionItem Props
|
|
92
|
+
|
|
93
|
+
| Prop | Type | Default | Description |
|
|
94
|
+
| -------------- | ------------------------------------------------------------------------------ | ------------ | ------------------------------------------------ |
|
|
95
|
+
| `value` | `string` | **Required** | Unique identifier for this item |
|
|
96
|
+
| `header` | `ReactNode \| (props: { expanded: boolean, disabled?: boolean }) => ReactNode` | **Required** | Header content or render function |
|
|
97
|
+
| `children` | `ReactNode \| (props: { expanded: boolean }) => ReactNode` | **Required** | Expanded content or render function |
|
|
98
|
+
| `disabled` | `boolean` | `false` | Prevents this item from being toggled |
|
|
99
|
+
| `style` | `ViewStyle` | `undefined` | Style for the item container |
|
|
100
|
+
| `headerStyle` | `ViewStyle` | `undefined` | Style for the header wrapper |
|
|
101
|
+
| `contentStyle` | `ViewStyle` | `undefined` | Style for the content wrapper |
|
|
102
|
+
| `data` | `any` | `undefined` | Arbitrary data passed through to event callbacks |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### Accordion Ref Methods
|
|
107
|
+
|
|
108
|
+
Attach a ref to `<Accordion>` for programmatic control:
|
|
109
|
+
|
|
110
|
+
```jsx
|
|
111
|
+
const accordionRef = useRef(null);
|
|
112
|
+
|
|
113
|
+
// Open a specific item
|
|
114
|
+
accordionRef.current?.open("itemId");
|
|
115
|
+
|
|
116
|
+
// Close a specific item
|
|
117
|
+
accordionRef.current?.close("itemId");
|
|
118
|
+
|
|
119
|
+
// Toggle a specific item
|
|
120
|
+
accordionRef.current?.toggle("itemId");
|
|
121
|
+
|
|
122
|
+
// Expand all items
|
|
123
|
+
accordionRef.current?.expandAll();
|
|
124
|
+
|
|
125
|
+
// Collapse all items
|
|
126
|
+
accordionRef.current?.collapseAll();
|
|
127
|
+
|
|
128
|
+
// Toggle all items
|
|
129
|
+
accordionRef.current?.toggleAll();
|
|
130
|
+
|
|
131
|
+
// Returns an array of currently expanded item values
|
|
132
|
+
accordionRef.current?.getExpandedItems();
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### Animation Configuration
|
|
138
|
+
|
|
139
|
+
#### Timing Animation
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
{
|
|
143
|
+
type: 'timing',
|
|
144
|
+
duration: 300, // Duration in milliseconds
|
|
145
|
+
easing: (value) => value // Optional custom easing function
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Spring Animation
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
{
|
|
153
|
+
type: 'spring',
|
|
154
|
+
damping: 10, // Default: 10
|
|
155
|
+
mass: 1, // Default: 1
|
|
156
|
+
stiffness: 100, // Default: 100
|
|
157
|
+
overshootClamping: false,
|
|
158
|
+
restSpeedThreshold: 0.01,
|
|
159
|
+
restDisplacementThreshold: 0.01,
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
### Theme Configuration
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
const customTheme = {
|
|
169
|
+
colors: {
|
|
170
|
+
background: "#FFFFFF",
|
|
171
|
+
surface: "#F5F5F5",
|
|
172
|
+
primary: "#2196F3",
|
|
173
|
+
text: "#000000",
|
|
174
|
+
textSecondary: "#666666",
|
|
175
|
+
border: "#E0E0E0",
|
|
176
|
+
disabled: "#BDBDBD",
|
|
177
|
+
icon: "#666666",
|
|
178
|
+
},
|
|
179
|
+
spacing: {
|
|
180
|
+
xs: 4,
|
|
181
|
+
sm: 8,
|
|
182
|
+
md: 16,
|
|
183
|
+
lg: 24,
|
|
184
|
+
xl: 32,
|
|
185
|
+
},
|
|
186
|
+
typography: {
|
|
187
|
+
header: {
|
|
188
|
+
fontSize: 16,
|
|
189
|
+
fontWeight: "500",
|
|
190
|
+
},
|
|
191
|
+
content: {
|
|
192
|
+
fontSize: 14,
|
|
193
|
+
lineHeight: 20,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
borderRadius: {
|
|
197
|
+
sm: 4,
|
|
198
|
+
md: 8,
|
|
199
|
+
lg: 12,
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## 💡 Examples
|
|
207
|
+
|
|
208
|
+
### Basic Usage
|
|
209
|
+
|
|
210
|
+
```jsx
|
|
211
|
+
import { Accordion, AccordionItem } from "react-native-pro-accordion";
|
|
212
|
+
|
|
213
|
+
<Accordion mode="single">
|
|
214
|
+
<AccordionItem value="item1" header={<Text>Title 1</Text>}>
|
|
215
|
+
<Text>Content 1</Text>
|
|
216
|
+
</AccordionItem>
|
|
217
|
+
<AccordionItem value="item2" header={<Text>Title 2</Text>}>
|
|
218
|
+
<Text>Content 2</Text>
|
|
219
|
+
</AccordionItem>
|
|
220
|
+
</Accordion>;
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Custom Header & Content
|
|
226
|
+
|
|
227
|
+
Use render functions to access the `expanded` state inside your header or content:
|
|
228
|
+
|
|
229
|
+
```jsx
|
|
230
|
+
<AccordionItem
|
|
231
|
+
value="custom"
|
|
232
|
+
header={({ expanded }) => (
|
|
233
|
+
<View style={{ flexDirection: "row", justifyContent: "space-between" }}>
|
|
234
|
+
<Text style={{ fontWeight: expanded ? "bold" : "normal" }}>
|
|
235
|
+
Custom Header
|
|
236
|
+
</Text>
|
|
237
|
+
<Text>{expanded ? "▼" : "▶"}</Text>
|
|
238
|
+
</View>
|
|
239
|
+
)}
|
|
240
|
+
>
|
|
241
|
+
{({ expanded }) => <Text>Content is {expanded ? "visible" : "hidden"}</Text>}
|
|
242
|
+
</AccordionItem>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### Controlled Mode
|
|
248
|
+
|
|
249
|
+
Manage expanded state from outside the component:
|
|
250
|
+
|
|
251
|
+
```jsx
|
|
252
|
+
const [expandedItems, setExpandedItems] = useState(["item1"]);
|
|
253
|
+
|
|
254
|
+
<Accordion value={expandedItems} onChange={setExpandedItems} mode="multiple">
|
|
255
|
+
<AccordionItem value="item1" header={<Text>Item 1</Text>}>
|
|
256
|
+
<Text>Content 1</Text>
|
|
257
|
+
</AccordionItem>
|
|
258
|
+
<AccordionItem value="item2" header={<Text>Item 2</Text>}>
|
|
259
|
+
<Text>Content 2</Text>
|
|
260
|
+
</AccordionItem>
|
|
261
|
+
</Accordion>;
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
### Programmatic Control via Ref
|
|
267
|
+
|
|
268
|
+
```jsx
|
|
269
|
+
const accordionRef = useRef(null);
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<>
|
|
273
|
+
<Button
|
|
274
|
+
title="Expand All"
|
|
275
|
+
onPress={() => accordionRef.current?.expandAll()}
|
|
276
|
+
/>
|
|
277
|
+
<Button
|
|
278
|
+
title="Collapse All"
|
|
279
|
+
onPress={() => accordionRef.current?.collapseAll()}
|
|
280
|
+
/>
|
|
281
|
+
|
|
282
|
+
<Accordion ref={accordionRef} mode="multiple">
|
|
283
|
+
{/* Items here */}
|
|
284
|
+
</Accordion>
|
|
285
|
+
</>
|
|
286
|
+
);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### Event Callbacks
|
|
292
|
+
|
|
293
|
+
```jsx
|
|
294
|
+
<Accordion
|
|
295
|
+
onOpen={(value, data) => console.log("Opened:", value, data)}
|
|
296
|
+
onClose={(value, data) => console.log("Closed:", value, data)}
|
|
297
|
+
onToggle={(value, expanded, data) => console.log("Toggled:", value, expanded)}
|
|
298
|
+
>
|
|
299
|
+
<AccordionItem value="item1" header={<Text>Item 1</Text>} data={{ id: 1 }}>
|
|
300
|
+
<Text>Content 1</Text>
|
|
301
|
+
</AccordionItem>
|
|
302
|
+
</Accordion>
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
### Nested Accordions
|
|
308
|
+
|
|
309
|
+
```jsx
|
|
310
|
+
<AccordionItem value="parent" header={<Text>Parent</Text>}>
|
|
311
|
+
<Accordion mode="single">
|
|
312
|
+
<AccordionItem value="child1" header={<Text>Child 1</Text>}>
|
|
313
|
+
<Text>Child content 1</Text>
|
|
314
|
+
</AccordionItem>
|
|
315
|
+
<AccordionItem value="child2" header={<Text>Child 2</Text>}>
|
|
316
|
+
<Text>Child content 2</Text>
|
|
317
|
+
</AccordionItem>
|
|
318
|
+
</Accordion>
|
|
319
|
+
</AccordionItem>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
### Custom Styling
|
|
325
|
+
|
|
326
|
+
```jsx
|
|
327
|
+
<AccordionItem
|
|
328
|
+
value="styled"
|
|
329
|
+
header={<Text>Styled Item</Text>}
|
|
330
|
+
style={styles.customItem}
|
|
331
|
+
headerStyle={styles.customHeader}
|
|
332
|
+
contentStyle={styles.customContent}
|
|
333
|
+
>
|
|
334
|
+
<Text>Custom styled content</Text>
|
|
335
|
+
</AccordionItem>;
|
|
336
|
+
|
|
337
|
+
const styles = StyleSheet.create({
|
|
338
|
+
customItem: {
|
|
339
|
+
marginVertical: 8,
|
|
340
|
+
borderRadius: 12,
|
|
341
|
+
},
|
|
342
|
+
customHeader: {
|
|
343
|
+
backgroundColor: "#667eea",
|
|
344
|
+
padding: 16,
|
|
345
|
+
},
|
|
346
|
+
customContent: {
|
|
347
|
+
backgroundColor: "#f0f0ff",
|
|
348
|
+
padding: 20,
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
### Custom Animations
|
|
356
|
+
|
|
357
|
+
```jsx
|
|
358
|
+
// Spring animation
|
|
359
|
+
<Accordion animation={{ type: 'spring', damping: 8, stiffness: 120 }}>
|
|
360
|
+
|
|
361
|
+
// Timing animation with custom duration
|
|
362
|
+
<Accordion animation={{ type: 'timing', duration: 500 }}>
|
|
363
|
+
|
|
364
|
+
// Custom easing (quadratic)
|
|
365
|
+
<Accordion animation={{
|
|
366
|
+
type: 'timing',
|
|
367
|
+
duration: 400,
|
|
368
|
+
easing: (value) => Math.pow(value, 2)
|
|
369
|
+
}}>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
### Lazy Rendering
|
|
375
|
+
|
|
376
|
+
Improves performance for items with heavy content by deferring rendering until the item is first opened:
|
|
377
|
+
|
|
378
|
+
```jsx
|
|
379
|
+
<Accordion lazyRender>
|
|
380
|
+
<AccordionItem value="lazy" header={<Text>Lazy Loaded</Text>}>
|
|
381
|
+
<HeavyComponent /> {/* Only renders when expanded */}
|
|
382
|
+
</AccordionItem>
|
|
383
|
+
</Accordion>
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
### Read-only Mode
|
|
389
|
+
|
|
390
|
+
```jsx
|
|
391
|
+
<Accordion readOnly>
|
|
392
|
+
<AccordionItem value="ro" header={<Text>Read-only Item</Text>}>
|
|
393
|
+
<Text>Cannot be toggled by the user.</Text>
|
|
394
|
+
</AccordionItem>
|
|
395
|
+
</Accordion>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
### Disabled Items
|
|
401
|
+
|
|
402
|
+
```jsx
|
|
403
|
+
<AccordionItem value="disabled" header={<Text>Disabled Item</Text>} disabled>
|
|
404
|
+
<Text>This content will never show.</Text>
|
|
405
|
+
</AccordionItem>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## 🌗 Theme System
|
|
411
|
+
|
|
412
|
+
### Using ThemeProvider
|
|
413
|
+
|
|
414
|
+
Wrap your component tree with `ThemeProvider` for global theming:
|
|
415
|
+
|
|
416
|
+
```jsx
|
|
417
|
+
import {
|
|
418
|
+
ThemeProvider,
|
|
419
|
+
defaultLightTheme,
|
|
420
|
+
defaultDarkTheme,
|
|
421
|
+
} from "react-native-pro-accordion";
|
|
422
|
+
|
|
423
|
+
<ThemeProvider darkMode={isDarkMode} theme={customTheme}>
|
|
424
|
+
<Accordion>{/* Your accordion items */}</Accordion>
|
|
425
|
+
</ThemeProvider>;
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Inline Custom Theme
|
|
429
|
+
|
|
430
|
+
Apply a theme directly to a single `Accordion` instance:
|
|
431
|
+
|
|
432
|
+
```jsx
|
|
433
|
+
const myTheme = {
|
|
434
|
+
colors: {
|
|
435
|
+
primary: "#FF6B6B",
|
|
436
|
+
background: "#FFFFFF",
|
|
437
|
+
surface: "#F8F9FA",
|
|
438
|
+
text: "#2C3E50",
|
|
439
|
+
border: "#E1E8ED",
|
|
440
|
+
},
|
|
441
|
+
borderRadius: {
|
|
442
|
+
sm: 8,
|
|
443
|
+
md: 12,
|
|
444
|
+
lg: 16,
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
<Accordion theme={myTheme} darkMode={false}>
|
|
449
|
+
{/* Items */}
|
|
450
|
+
</Accordion>;
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
## ♿ Accessibility
|
|
456
|
+
|
|
457
|
+
This component is built with accessibility as a first-class concern:
|
|
458
|
+
|
|
459
|
+
- **Screen readers** — Compatible with VoiceOver (iOS) and TalkBack (Android)
|
|
460
|
+
- **Keyboard navigation** — Full support on web targets
|
|
461
|
+
- **ARIA roles & labels** — Correct semantic markup
|
|
462
|
+
- **Focus management** — Logical focus order maintained on expand/collapse
|
|
463
|
+
|
|
464
|
+
```jsx
|
|
465
|
+
<Accordion accessibilityLabel="Main navigation accordion">
|
|
466
|
+
<AccordionItem value="accessible" header={<Text>Accessible Item</Text>}>
|
|
467
|
+
<Text>Fully accessible content</Text>
|
|
468
|
+
</AccordionItem>
|
|
469
|
+
</Accordion>
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## 📄 License
|
|
475
|
+
|
|
476
|
+
MIT © react-native-pro-accordion contributors
|
package/index.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Accordion = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _AccordionContext = require("../core/AccordionContext");
|
|
10
|
+
var _AccordionRef = require("../core/AccordionRef");
|
|
11
|
+
var _defaultTheme = require("../theme/defaultTheme");
|
|
12
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
14
|
+
const Accordion = exports.Accordion = /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
|
|
15
|
+
const {
|
|
16
|
+
children,
|
|
17
|
+
value: controlledValue,
|
|
18
|
+
defaultValue = [],
|
|
19
|
+
onChange,
|
|
20
|
+
mode = "single",
|
|
21
|
+
readOnly = false,
|
|
22
|
+
animation = {
|
|
23
|
+
type: "timing",
|
|
24
|
+
duration: 300
|
|
25
|
+
},
|
|
26
|
+
renderIcon,
|
|
27
|
+
iconPosition = "right",
|
|
28
|
+
showSeparators = false,
|
|
29
|
+
separatorComponent,
|
|
30
|
+
separatorStyle,
|
|
31
|
+
stickyHeaders = false,
|
|
32
|
+
lazyRender = false,
|
|
33
|
+
theme: customTheme,
|
|
34
|
+
darkMode = false,
|
|
35
|
+
accessibilityLabel,
|
|
36
|
+
testID,
|
|
37
|
+
onOpen,
|
|
38
|
+
onClose,
|
|
39
|
+
onToggle,
|
|
40
|
+
onAnimationStart,
|
|
41
|
+
onAnimationEnd,
|
|
42
|
+
onStateChange
|
|
43
|
+
} = props;
|
|
44
|
+
|
|
45
|
+
// State management
|
|
46
|
+
const isControlled = controlledValue !== undefined;
|
|
47
|
+
const [internalExpandedValues, setInternalExpandedValues] = (0, _react.useState)(defaultValue);
|
|
48
|
+
const expandedValues = isControlled ? controlledValue : internalExpandedValues;
|
|
49
|
+
const expandedValuesRef = (0, _react.useRef)(expandedValues);
|
|
50
|
+
expandedValuesRef.current = expandedValues;
|
|
51
|
+
const setExpandedValues = (0, _react.useCallback)(newValues => {
|
|
52
|
+
if (!isControlled) {
|
|
53
|
+
setInternalExpandedValues(newValues);
|
|
54
|
+
}
|
|
55
|
+
onChange?.(newValues);
|
|
56
|
+
onStateChange?.(newValues);
|
|
57
|
+
}, [isControlled, onChange, onStateChange]);
|
|
58
|
+
const handleToggleItem = (0, _react.useCallback)(value => {
|
|
59
|
+
const isCurrentlyExpanded = expandedValues.includes(value);
|
|
60
|
+
let newValues;
|
|
61
|
+
if (isCurrentlyExpanded) {
|
|
62
|
+
newValues = expandedValues.filter(v => v !== value);
|
|
63
|
+
onClose?.(value);
|
|
64
|
+
onToggle?.(value, false);
|
|
65
|
+
} else {
|
|
66
|
+
if (mode === "single") {
|
|
67
|
+
newValues = [value];
|
|
68
|
+
} else {
|
|
69
|
+
newValues = [...expandedValues, value];
|
|
70
|
+
}
|
|
71
|
+
onOpen?.(value);
|
|
72
|
+
onToggle?.(value, true);
|
|
73
|
+
}
|
|
74
|
+
setExpandedValues(newValues);
|
|
75
|
+
}, [expandedValues, mode, setExpandedValues, onOpen, onClose, onToggle]);
|
|
76
|
+
|
|
77
|
+
// Expose ref methods
|
|
78
|
+
(0, _react.useImperativeHandle)(ref, () => new _AccordionRef.AccordionRefImpl(expandedValuesRef, setExpandedValues, mode, readOnly), [mode, readOnly, setExpandedValues]);
|
|
79
|
+
|
|
80
|
+
// Theme merging
|
|
81
|
+
const baseTheme = darkMode ? _defaultTheme.defaultDarkTheme : _defaultTheme.defaultLightTheme;
|
|
82
|
+
const theme = customTheme ? {
|
|
83
|
+
...baseTheme,
|
|
84
|
+
...customTheme,
|
|
85
|
+
colors: {
|
|
86
|
+
...baseTheme.colors,
|
|
87
|
+
...customTheme.colors
|
|
88
|
+
}
|
|
89
|
+
} : baseTheme;
|
|
90
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_AccordionContext.AccordionProvider, {
|
|
91
|
+
mode: mode,
|
|
92
|
+
readOnly: readOnly,
|
|
93
|
+
animationConfig: animation,
|
|
94
|
+
renderIcon: renderIcon,
|
|
95
|
+
iconPosition: iconPosition,
|
|
96
|
+
showSeparators: showSeparators,
|
|
97
|
+
lazyRender: lazyRender,
|
|
98
|
+
theme: theme,
|
|
99
|
+
darkMode: darkMode,
|
|
100
|
+
expandedValues: expandedValues,
|
|
101
|
+
onToggleItem: handleToggleItem,
|
|
102
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
103
|
+
style: styles.container,
|
|
104
|
+
accessible: !!accessibilityLabel,
|
|
105
|
+
accessibilityLabel: accessibilityLabel,
|
|
106
|
+
testID: testID,
|
|
107
|
+
children: _react.default.Children.map(children, (child, index) => {
|
|
108
|
+
const isLast = index === _react.default.Children.count(children) - 1;
|
|
109
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_react.default.Fragment, {
|
|
110
|
+
children: [child, showSeparators && !isLast && (separatorComponent || /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
111
|
+
style: [styles.defaultSeparator, separatorStyle, {
|
|
112
|
+
backgroundColor: theme.colors.border
|
|
113
|
+
}]
|
|
114
|
+
}))]
|
|
115
|
+
}, index);
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
const styles = _reactNative.StyleSheet.create({
|
|
121
|
+
container: {
|
|
122
|
+
width: "100%"
|
|
123
|
+
},
|
|
124
|
+
defaultSeparator: {
|
|
125
|
+
height: 1,
|
|
126
|
+
width: "100%"
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
Accordion.displayName = "Accordion";
|
|
130
|
+
//# sourceMappingURL=Accordion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_AccordionContext","_AccordionRef","_defaultTheme","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","Accordion","exports","forwardRef","props","ref","children","value","controlledValue","defaultValue","onChange","mode","readOnly","animation","type","duration","renderIcon","iconPosition","showSeparators","separatorComponent","separatorStyle","stickyHeaders","lazyRender","theme","customTheme","darkMode","accessibilityLabel","testID","onOpen","onClose","onToggle","onAnimationStart","onAnimationEnd","onStateChange","isControlled","undefined","internalExpandedValues","setInternalExpandedValues","useState","expandedValues","expandedValuesRef","useRef","current","setExpandedValues","useCallback","newValues","handleToggleItem","isCurrentlyExpanded","includes","filter","v","useImperativeHandle","AccordionRefImpl","baseTheme","defaultDarkTheme","defaultLightTheme","colors","jsx","AccordionProvider","animationConfig","onToggleItem","View","style","styles","container","accessible","React","Children","map","child","index","isLast","count","jsxs","Fragment","defaultSeparator","backgroundColor","border","StyleSheet","create","width","height","displayName"],"sourceRoot":"..\\..\\..\\src","sources":["components/Accordion.js"],"mappings":"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","ignoreList":[]}
|