@hoddy-ui/core 1.1.0 → 1.1.2

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 CHANGED
@@ -1,331 +1,1113 @@
1
1
  # @hoddy-ui/core
2
2
 
3
- Hoddy UI is a versatile UI component and theming library for React Native and Expo. It follows the Hoddy UI design guidelines, which are a tweak of Material Design. The library provides a collection of reusable components and a customizable theming system to simplify and accelerate the development of mobile applications.
3
+ **The complete UI component library for React Native and Expo applications**
4
4
 
5
- ## Installation
5
+ A comprehensive, production-ready UI component library that follows Material Design principles with a modern twist. Built with TypeScript and optimized for React Native and Expo applications.
6
6
 
7
- To install Hoddy UI, use npm or yarn:
7
+ ## Features
8
8
 
9
- **npm:**
9
+ - 🎨 **20+ Production-Ready Components** - From basic buttons to complex forms
10
+ - 🌗 **Dark Mode Support** - Automatic theme switching with system preference detection
11
+ - 🔧 **TypeScript First** - Full type safety and IntelliSense support
12
+ - ⚡ **Performance Optimized** - Minimal bundle size with tree shaking
13
+ - 🎯 **Accessibility Ready** - WCAG compliant components
14
+ - 🔌 **Highly Customizable** - Extensive theming and configuration options
15
+ - 📱 **Cross Platform** - Works seamlessly on iOS and Android
10
16
 
11
- ```sh
17
+ ## 📦 Installation
18
+
19
+ ```bash
12
20
  npm install @hoddy-ui/core
21
+ # or
22
+ yarn add @hoddy-ui/core
13
23
  ```
14
24
 
15
- **yarn:**
25
+ ### Peer Dependencies
16
26
 
17
- ```sh
18
- yarn add @hoddy-ui/core
27
+ Install the required peer dependencies:
28
+
29
+ ```bash
30
+ npm install @expo/vector-icons @react-native-async-storage/async-storage @react-navigation/native expo-navigation-bar expo-system-ui react-native-safe-area-context react-native-size-matters
19
31
  ```
20
32
 
21
- Hoddy UI has the following peer dependencies, make sure to install them as well:
33
+ Or with yarn:
22
34
 
23
- ```json
24
- "@expo/vector-icons": "^13.0.0",
25
- "@react-native-async-storage/async-storage": "^1.18.1",
26
- "@react-navigation/native": "^6.1.6",
27
- "expo-navigation-bar": "^2.1.1",
28
- "expo-system-ui": "^2.2.1",
29
- "react": "^18.2.0",
30
- "react-native": "^0.71.8",
31
- "react-native-safe-area-context": "^4.5.3",
32
- "react-native-size-matters": "^0.4.0"
35
+ ```bash
36
+ yarn add @expo/vector-icons @react-native-async-storage/async-storage @react-navigation/native expo-navigation-bar expo-system-ui react-native-safe-area-context react-native-size-matters
33
37
  ```
34
38
 
35
- ## Enabling dark mode
39
+ ## 🚀 Quick Start
36
40
 
37
- To take advantage of the dark mode feature, add the UIProvider component to the root of your app
41
+ ### Basic Setup
38
42
 
39
- ```javascript
40
- import { UIThemeProvider } from "hoddy-ui/core";
43
+ 1. **Initialize the library** (optional but recommended):
41
44
 
42
- function App() {
45
+ ```tsx
46
+ import { initialize } from "@hoddy-ui/core";
47
+
48
+ initialize({
49
+ // Custom font family
50
+ fontFamily: "Inter-Regular",
51
+
52
+ // Google Maps API key for Locator component
53
+ googleMapApiKey: "your-google-maps-api-key",
54
+
55
+ // Edge-to-edge display (affects Android navigation bar styling)
56
+ edgeToEdge: false,
57
+
58
+ // Custom colors
59
+ colors: {
60
+ primary: {
61
+ main: "#6366f1",
62
+ light: "#818cf8",
63
+ dark: "#4f46e5",
64
+ },
65
+ },
66
+ });
67
+ ```
68
+
69
+ 2. **Wrap your app with the theme provider**:
70
+
71
+ ```tsx
72
+ import React from "react";
73
+ import { UIThemeProvider } from "@hoddy-ui/core";
74
+ import App from "./App";
75
+
76
+ export default function Root() {
43
77
  return (
44
78
  <UIThemeProvider>
45
- <Component />
79
+ <App />
46
80
  </UIThemeProvider>
47
81
  );
48
82
  }
49
83
  ```
50
84
 
51
- ## Usage
52
-
53
- Here's a quick example of how to use Hoddy UI in your React Native or Expo project:
85
+ 3. **Start using components**:
54
86
 
55
- ```javascript
87
+ ```tsx
56
88
  import React from "react";
57
89
  import { View } from "react-native";
58
- import { Button, Typography } from "@hoddy-ui/core";
90
+ import {
91
+ Typography,
92
+ Button,
93
+ TextField,
94
+ Animator,
95
+ useColors,
96
+ useFadeAnimation,
97
+ } from "@hoddy-ui/core";
98
+
99
+ export default function HomeScreen() {
100
+ const colors = useColors();
59
101
 
60
- const HomeScreen = () => {
61
102
  return (
62
- <View>
63
- <Typography>Welcome to Hoddy UI!</Typography>
64
- <Button title="Click me" onPress={() => console.log("Button pressed!")} />
103
+ <View style={{ padding: 20, backgroundColor: colors.white[1] }}>
104
+ <Animator type="fade" duration={1000}>
105
+ <Typography variant="h4" color="primary" gutterBottom={20}>
106
+ Welcome to Hoddy UI!
107
+ </Typography>
108
+ </Animator>
109
+
110
+ <Animator type="slide" direction="up" delay={200}>
111
+ <TextField
112
+ label="Email Address"
113
+ variant="outlined"
114
+ keyboardType="email-address"
115
+ gutterBottom={16}
116
+ />
117
+ </Animator>
118
+
119
+ <Animator type="grow" delay={400}>
120
+ <Button
121
+ title="Get Started"
122
+ variant="contained"
123
+ color="primary"
124
+ onPress={() => console.log("Button pressed!")}
125
+ />
126
+ </Animator>
65
127
  </View>
66
128
  );
67
- };
129
+ }
130
+ ```
131
+
132
+ ## ⚙️ Configuration
133
+
134
+ ### Global Configuration
135
+
136
+ Use the `initialize` function to configure the library globally:
137
+
138
+ ```tsx
139
+ import { initialize } from "@hoddy-ui/core";
68
140
 
69
- export default HomeScreen;
141
+ initialize({
142
+ // Font family for all typography components
143
+ fontFamily?: string;
144
+
145
+ // Google Maps API key for Locator component
146
+ googleMapApiKey?: string;
147
+
148
+ // Edge-to-edge display (skips Android navigation bar styling)
149
+ edgeToEdge?: boolean;
150
+
151
+ // Custom color overrides
152
+ colors?: {
153
+ primary?: { main: string; light?: string; dark?: string };
154
+ secondary?: { main: string; light?: string; dark?: string };
155
+ // ... and more
156
+ };
157
+ });
70
158
  ```
71
159
 
72
- ## Components
160
+ ### Theme Configuration
73
161
 
74
- Hoddy UI provides the following components for building your UI:
162
+ The theme system automatically detects system preferences and can be controlled programmatically:
75
163
 
76
- - [AdaptiveStatusBar](#adaptivestatusbar)
77
- - [Avatar](#avatar)
78
- - [AlertX](#alertx)
79
- - [Button](#button)
80
- - [FlashMessage](#flashmessage)
81
- - [FormWrapper](#formwrapper)
82
- - [Grid](#grid)
83
- - [GridItem](#griditem)
84
- - [IconButton](#iconbutton)
85
- - [LinkButton](#linkbutton)
86
- - [List](#list)
87
- - [ListItem](#listitem)
88
- - [ListItemText](#listitemtext)
89
- - [Locator](#locator)
90
- - [Popup](#popup)
91
- - [SafeAreaView](#safeareaview)
92
- - [Spinner](#spinner)
93
- - [TextField](#textfield)
94
- - [TextField2](#textfield2)
95
- - [Typography](#typography)
164
+ ```tsx
165
+ import { useTheme } from "@hoddy-ui/core";
96
166
 
97
- ## Component API Reference
167
+ function ThemeToggle() {
168
+ const { themeState, themeDispatch } = useTheme();
98
169
 
99
- ### AdaptiveStatusBar
170
+ const toggleTheme = () => {
171
+ themeDispatch({
172
+ type: themeState.mode === "dark" ? "light" : "dark",
173
+ });
174
+ };
100
175
 
101
- A component that adapts the status bar color based on the theme.
176
+ return (
177
+ <Button
178
+ title={`Switch to ${themeState.mode === "dark" ? "Light" : "Dark"} Mode`}
179
+ onPress={toggleTheme}
180
+ />
181
+ );
182
+ }
183
+ ```
102
184
 
103
- **Props:**
185
+ ## 🎨 Theming System
104
186
 
105
- | Prop | Type | Default | Description |
106
- | --------------- | ------ | --------------- | ----------------------------------------------------------------------------------------- |
107
- | barStyle | string | "light-content" | The style of the status bar. Possible values: "default", "light-content", "dark-content". |
108
- | backgroundColor | string | Theme-dependent | The background color of the status bar. |
187
+ ### Using Hooks
109
188
 
110
- Example usage:
189
+ Access theme colors and state throughout your app:
111
190
 
112
- ```jsx
113
- import { AdaptiveStatusBar } from "@hoddy-ui/core";
191
+ ```tsx
192
+ import { useColors, useTheme } from "@hoddy-ui/core";
193
+
194
+ function MyComponent() {
195
+ const colors = useColors();
196
+ const theme = useTheme();
114
197
 
115
- const App = () => {
116
198
  return (
117
- <>
118
- <AdaptiveStatusBar />
119
- {/* Rest of the app */}
120
- </>
199
+ <View
200
+ style={{
201
+ backgroundColor: colors.white[1],
202
+ borderColor: colors.primary.main,
203
+ }}
204
+ >
205
+ <Typography color={theme === "dark" ? "white" : "dark"}>
206
+ Current theme: {theme}
207
+ </Typography>
208
+ </View>
121
209
  );
210
+ }
211
+ ```
212
+
213
+ ### Color Palette
214
+
215
+ The library includes a comprehensive color system:
216
+
217
+ ```tsx
218
+ const colors = {
219
+ // Primary colors
220
+ primary: { main: "#007AFF", light: "#5AC8FA", dark: "#0051D5" },
221
+ secondary: { main: "#FF3B30", light: "#FF6B6B", dark: "#D70015" },
222
+
223
+ // Neutral colors
224
+ white: ["#FFFFFF", "#F8F9FA", "#E9ECEF"],
225
+ black: ["#000000", "#212529", "#495057"],
226
+
227
+ // Semantic colors
228
+ success: { main: "#28A745", light: "#34CE57", dark: "#1E7E34" },
229
+ error: { main: "#DC3545", light: "#E74C3C", dark: "#C82333" },
230
+ warning: { main: "#FFC107", light: "#FFD54F", dark: "#FF8F00" },
231
+
232
+ // Utility colors
233
+ textPrimary: { main: "#212529" },
234
+ textSecondary: { main: "#6C757D" },
235
+ divider: { main: "#DEE2E6" },
122
236
  };
123
237
  ```
124
238
 
125
- ### Avatar
239
+ ## 🧩 Components
126
240
 
127
- A component for displaying user avatars.
241
+ ### Layout & Structure
128
242
 
129
- **Props:**
243
+ - **`SafeAreaView`** - Safe area wrapper for different devices
244
+ - **`Grid`** & **`GridItem`** - Flexible grid layout system
245
+ - **`FormWrapper`** - Form container with validation support
130
246
 
131
- | Prop | Type | Default | Description |
132
- | ------- | ------- | ------- | ------------------------------------- |
133
- | image | number | - | The source of the avatar image. |
134
- | size | number | 40 | The size of the avatar in pixels. |
135
- | rounded | boolean | false | Whether the avatar should be rounded. |
247
+ ### Navigation & Status
136
248
 
137
- ### AlertX
249
+ - **`AdaptiveStatusBar`** - Theme-aware status bar
250
+ - Navigation utilities via hooks
138
251
 
139
- A customizable alert component.
252
+ ### Typography
140
253
 
141
- **Props:**
254
+ - **`Typography`** - Comprehensive text component with variants (h1-h6, body1-body2, caption)
142
255
 
143
- | Prop | Type | Default | Description |
144
- | ------- | ------ | --------- | --------------------------------------------------------------------------------- |
145
- | title | string | - | The title of the alert. |
146
- | message | string | - | The message/content of the alert. |
147
- | type | string | "default" | The type of the alert. Possible values: "default", "success", "error", "warning". |
256
+ ### Form Components
148
257
 
149
- ### Button
258
+ - **`TextField`** - Material Design text input with variants
259
+ - **`TextField2`** - Alternative text field design
260
+ - **`Locator`** - Location picker with Google Maps integration
150
261
 
151
- A customizable button component.
262
+ ### Interactive Elements
152
263
 
153
- **Props:**
264
+ - **`Button`** - Primary action buttons with variants
265
+ - **`IconButton`** - Icon-only buttons
266
+ - **`LinkButton`** - Text-based link buttons
154
267
 
155
- | Prop | Type | Default | Description |
156
- | ------- | -------- | ------- | ------------------------------------------ |
157
- | title | string | - | The text to display on the button. |
158
- | onPress | function | - | The function to be called on button press. |
268
+ ### Feedback & Communication
159
269
 
160
- ### FlashMessage
270
+ - **`FlashMessage`** - Toast notifications and alerts
271
+ - **`AlertX`** - Customizable alert dialogs
272
+ - **`Spinner`** - Loading indicators
161
273
 
162
- A component for displaying flash messages.
274
+ ### Data Display
163
275
 
164
- **Props:**
276
+ - **`Avatar`** - User profile images and placeholders
277
+ - **`List`**, **`ListItem`**, **`ListItemText`** - List components
165
278
 
166
- | Prop | Type | Default | Description |
167
- | -------- | ------- | --------- | ----------------------------------------------------------------------------------------- |
168
- | message | string | - | The message/content of the flash message. |
169
- | type | string | "default" | The type of the flash message. Possible values: "default", "success", "error", "warning". |
170
- | duration | number | 3000 | The duration in milliseconds that the flash message should be displayed. |
171
- | autoHide | boolean | true | Whether the flash message should auto-hide after the specified duration. |
279
+ ### Overlays & Modals
172
280
 
173
- ### FormWrapper
281
+ - **`Popup`** - Modal dialogs and bottom sheets
174
282
 
175
- A wrapper component for form fields.
283
+ ### Animation
176
284
 
177
- **Props:**
285
+ - **`Animator`** - Layout animations and transitions
178
286
 
179
- | Prop | Type | Default | Description |
180
- | -------- | ---- | ------- | ----------------------------------------- |
181
- | children | node | - | The form fields/components to be wrapped. |
287
+ ## 📖 Component API Reference
182
288
 
183
- ### Grid
289
+ ### Typography
184
290
 
185
- A flexible grid component for arranging child elements.
291
+ A versatile text component supporting multiple variants and styling options.
186
292
 
187
293
  **Props:**
188
294
 
189
- | Prop | Type | Default | Description |
190
- | ---------- | ------ | ------- | ---------------------------------------------- |
191
- | children | node | - | The child elements to be rendered in the grid. |
192
- | numColumns | number | 2 | The number of columns in the grid. |
193
- | spacing | number | 10 | The spacing between grid items in pixels. |
295
+ | Prop | Type | Default | Description |
296
+ | -------------- | --------------------------------------------------------------------------------- | --------- | ----------------------------- |
297
+ | `variant` | `"h1" \| "h2" \| "h3" \| "h4" \| "h5" \| "h6" \| "body1" \| "body2" \| "caption"` | `"body1"` | Text style variant |
298
+ | `color` | `string` | `"dark"` | Text color from theme palette |
299
+ | `align` | `"left" \| "center" \| "right"` | `"left"` | Text alignment |
300
+ | `gutterBottom` | `number` | `0` | Bottom margin in pixels |
301
+ | `fontWeight` | `number` | `400` | Font weight |
302
+ | `textCase` | `"uppercase" \| "lowercase" \| "capitalize"` | `null` | Text transformation |
303
+
304
+ **Example:**
305
+
306
+ ```tsx
307
+ <Typography variant="h4" color="primary" gutterBottom={20}>
308
+ Welcome to Hoddy UI
309
+ </Typography>
310
+ ```
194
311
 
195
- ### GridItem
312
+ ### Button
196
313
 
197
- A component representing an item in the Grid component.
314
+ A comprehensive button component with multiple variants and states.
198
315
 
199
316
  **Props:**
200
317
 
201
- | Prop | Type | Default | Description |
202
- | -------- | ---- | ------- | ----------------------------- |
203
- | children | node | - | The content of the grid item. |
318
+ | Prop | Type | Default | Description |
319
+ | ---------- | ------------------------------------- | ------------- | -------------------------- |
320
+ | `title` | `string` | - | Button text |
321
+ | `variant` | `"contained" \| "outlined" \| "text"` | `"contained"` | Button variant |
322
+ | `color` | `string` | `"primary"` | Button color from theme |
323
+ | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Button size |
324
+ | `disabled` | `boolean` | `false` | Disabled state |
325
+ | `loading` | `boolean` | `false` | Loading state with spinner |
326
+ | `onPress` | `() => void` | - | Press handler |
327
+ | `start` | `ReactNode` | - | Leading icon/element |
328
+ | `end` | `ReactNode` | - | Trailing icon/element |
329
+
330
+ **Example:**
331
+
332
+ ```tsx
333
+ <Button
334
+ title="Submit"
335
+ variant="contained"
336
+ color="primary"
337
+ loading={isLoading}
338
+ onPress={handleSubmit}
339
+ />
340
+ ```
204
341
 
205
342
  ### IconButton
206
343
 
207
- A button component with an icon.
344
+ A button component that displays only an icon.
208
345
 
209
346
  **Props:**
210
347
 
211
- | Prop | Type | Default | Description |
212
- | ------- | -------- | ------- | ------------------------------------------ |
213
- | icon | string | - | The name of the icon to display. |
214
- | onPress | function | - | The function to be called on button press. |
348
+ | Prop | Type | Default | Description |
349
+ | ----------------- | --------------------- | ------------ | ------------------------- |
350
+ | `icon` | `string` | - | Icon name |
351
+ | `iconType` | `"material" \| "ion"` | `"material"` | Icon library to use |
352
+ | `size` | `number` | `24` | Icon size in pixels |
353
+ | `color` | `string` | `"dark"` | Icon color from theme |
354
+ | `bg` | `boolean` | `false` | Show background circle |
355
+ | `elevation` | `number` | `0` | Shadow elevation |
356
+ | `disabled` | `boolean` | `false` | Disabled state |
357
+ | `onPress` | `() => void` | - | Press handler |
358
+ | `style` | `ViewStyle` | `{}` | Icon style overrides |
359
+ | `containerStyles` | `ViewStyle` | `{}` | Container style overrides |
360
+
361
+ **Example:**
362
+
363
+ ```tsx
364
+ <IconButton
365
+ icon="star"
366
+ iconType="ion"
367
+ size={28}
368
+ color="primary"
369
+ bg={true}
370
+ elevation={2}
371
+ onPress={() => console.log("Starred!")}
372
+ />
373
+ ```
215
374
 
216
375
  ### LinkButton
217
376
 
218
- A button component that navigates to a specified URL.
377
+ A text-based button component for navigation or secondary actions.
219
378
 
220
379
  **Props:**
221
380
 
222
- | Prop | Type | Default | Description |
223
- | ----- | ------ | ------- | --------------------------------------- |
224
- | title | string | - | The text to display on the button. |
225
- | url | string | - | The URL to navigate to on button press. |
381
+ | Prop | Type | Default | Description |
382
+ | ------------ | ------------ | -------- | --------------------- |
383
+ | `title` | `string` | - | Button text |
384
+ | `color` | `string` | `"blue"` | Text color from theme |
385
+ | `fontSize` | `number` | `12` | Font size |
386
+ | `fontWeight` | `string` | `"400"` | Font weight |
387
+ | `disabled` | `boolean` | `false` | Disabled state |
388
+ | `onPress` | `() => void` | - | Press handler |
389
+ | `style` | `TextStyle` | `{}` | Text style overrides |
390
+
391
+ **Example:**
392
+
393
+ ```tsx
394
+ <LinkButton
395
+ title="Forgot Password?"
396
+ color="primary"
397
+ fontSize={14}
398
+ onPress={() => navigation.navigate("ForgotPassword")}
399
+ />
400
+ ```
226
401
 
227
- ### List
402
+ ### TextField
228
403
 
229
- A component for rendering lists.
404
+ A Material Design text input component with comprehensive features.
230
405
 
231
406
  **Props:**
232
407
 
233
- | Prop | Type | Default | Description |
234
- | -------- | ---- | ------- | ------------------------------ |
235
- | children | node | - | The list items to be rendered. |
408
+ | Prop | Type | Default | Description |
409
+ | -------------- | -------------------------------------- | ------------ | --------------------- |
410
+ | `label` | `string` | - | Input label |
411
+ | `variant` | `"outlined" \| "filled" \| "standard"` | `"outlined"` | Input variant |
412
+ | `value` | `string` | - | Input value |
413
+ | `onChangeText` | `(text: string) => void` | - | Change handler |
414
+ | `placeholder` | `string` | - | Placeholder text |
415
+ | `error` | `boolean` | `false` | Error state |
416
+ | `helperText` | `string` | - | Helper/error text |
417
+ | `disabled` | `boolean` | `false` | Disabled state |
418
+ | `multiline` | `boolean` | `false` | Multiline input |
419
+ | `start` | `ReactNode` | - | Leading icon/element |
420
+ | `end` | `ReactNode` | - | Trailing icon/element |
421
+
422
+ **Example:**
423
+
424
+ ```tsx
425
+ <TextField
426
+ label="Email Address"
427
+ variant="outlined"
428
+ value={email}
429
+ onChangeText={setEmail}
430
+ keyboardType="email-address"
431
+ error={!!emailError}
432
+ helperText={emailError}
433
+ />
434
+ ```
236
435
 
237
- ### ListItem
436
+ ### Locator
238
437
 
239
- A component representing an item in the List component.
438
+ A location picker component with Google Maps integration.
240
439
 
241
440
  **Props:**
242
441
 
243
- | Prop | Type | Default | Description |
244
- | -------- | ---- | ------- | ----------------------------- |
245
- | children | node | - | The content of the list item. |
442
+ | Prop | Type | Default | Description |
443
+ | -------------------- | ---------------------------------- | ------------- | -------------------------- |
444
+ | `onLocationSelected` | `(location: LocationType) => void` | - | Location selection handler |
445
+ | `label` | `string` | - | Input label |
446
+ | `variant` | `"contained" \| "outlined"` | `"contained"` | Input variant |
447
+ | `location` | `LocationType` | - | Current location |
448
+ | `country` | `string` | `"ng"` | Country code for search |
449
+ | `error` | `boolean` | `false` | Error state |
450
+
451
+ **Example:**
452
+
453
+ ```tsx
454
+ <Locator
455
+ label="Select Location"
456
+ onLocationSelected={(location) => setSelectedLocation(location)}
457
+ country="us"
458
+ />
459
+ ```
246
460
 
247
- ### ListItemText
461
+ ### SafeAreaView
248
462
 
249
- A component representing the text content of a ListItem.
463
+ A safe area wrapper component that handles device-specific safe areas.
250
464
 
251
465
  **Props:**
252
466
 
253
- | Prop | Type | Default | Description |
254
- | -------- | ---- | ------- | ------------------------ |
255
- | children | node | - | The text to be rendered. |
467
+ | Prop | Type | Default | Description |
468
+ | ---------- | ----------- | ------- | ------------------------- |
469
+ | `children` | `ReactNode` | - | Child components |
470
+ | `style` | `ViewStyle` | `{}` | Container style overrides |
256
471
 
257
- ### Locator
472
+ **Example:**
258
473
 
259
- A component for displaying a location marker on a map.
474
+ ```tsx
475
+ <SafeAreaView style={{ backgroundColor: "white" }}>
476
+ <YourContent />
477
+ </SafeAreaView>
478
+ ```
479
+
480
+ ### AdaptiveStatusBar
481
+
482
+ A status bar component that automatically adapts to the current theme.
260
483
 
261
484
  **Props:**
262
485
 
263
- | Prop | Type | Default | Description |
264
- | --------- | ------ | ------- | ------------------------------ |
265
- | latitude | number | - | The latitude of the location. |
266
- | longitude | number | - | The longitude of the location. |
486
+ | Prop | Type | Default | Description |
487
+ | ------------- | --------- | ------- | ------------------------------------- |
488
+ | `translucent` | `boolean` | `false` | Whether the status bar is translucent |
267
489
 
268
- ### Popup
490
+ **Example:**
269
491
 
270
- A customizable popup component.
492
+ ```tsx
493
+ <AdaptiveStatusBar translucent={true} />
494
+ ```
495
+
496
+ ### AlertX
497
+
498
+ A customizable alert component for displaying important messages.
271
499
 
272
500
  **Props:**
273
501
 
274
- | Prop | Type | Default | Description |
275
- | ------- | -------- | ------- | --------------------------------------------------- |
276
- | title | string | - | The title of the popup. |
277
- | onClose | function | - | The function to be called when the popup is closed. |
502
+ | Prop | Type | Default | Description |
503
+ | -------------- | --------------------------------------------- | ------------- | ------------------------- |
504
+ | `type` | `"info" \| "warning" \| "success" \| "error"` | `"info"` | Alert type |
505
+ | `variant` | `"contained" \| "outlined"` | `"contained"` | Alert variant |
506
+ | `title` | `string` | - | Alert title |
507
+ | `body` | `string` | - | Alert message |
508
+ | `gutterBottom` | `number` | `0` | Bottom margin in pixels |
509
+ | `style` | `ViewStyle` | `{}` | Container style overrides |
510
+
511
+ **Example:**
512
+
513
+ ```tsx
514
+ <AlertX
515
+ type="success"
516
+ title="Success!"
517
+ body="Your profile has been updated successfully."
518
+ gutterBottom={20}
519
+ />
520
+ ```
278
521
 
279
- ### SafeAreaView
522
+ ### Avatar
280
523
 
281
- A component that renders content within the safe area boundaries of the device.
524
+ A component for displaying user avatars with support for images, labels, or default icons.
282
525
 
283
526
  **Props:**
284
527
 
285
- | Prop | Type | Default | Description |
286
- | -------- | ---- | ------- | --------------------------- |
287
- | children | node | - | The content to be rendered. |
528
+ | Prop | Type | Default | Description |
529
+ | --------- | --------------------------- | ------------- | --------------------------- |
530
+ | `source` | `ImageSourcePropType` | - | Image source |
531
+ | `label` | `string` | - | Text label (first letter) |
532
+ | `size` | `number` | `48` | Avatar size in pixels |
533
+ | `color` | `string` | `"dark"` | Background color from theme |
534
+ | `variant` | `"contained" \| "outlined"` | `"contained"` | Avatar variant |
535
+ | `style` | `ViewStyle` | `{}` | Container style overrides |
536
+
537
+ **Example:**
538
+
539
+ ```tsx
540
+ <Avatar
541
+ source={{ uri: 'https://example.com/avatar.jpg' }}
542
+ size={64}
543
+ />
544
+
545
+ <Avatar
546
+ label="John Doe"
547
+ color="primary"
548
+ size={48}
549
+ />
550
+ ```
288
551
 
289
- ### Spinner
552
+ ### Grid & GridItem
553
+
554
+ Flexible grid layout components for organizing content.
555
+
556
+ **Grid Props:**
557
+
558
+ | Prop | Type | Default | Description |
559
+ | ---------- | ----------- | ------- | ------------------------- |
560
+ | `children` | `ReactNode` | - | GridItem components |
561
+ | `spacing` | `number` | `1` | Spacing between items |
562
+ | `style` | `ViewStyle` | `{}` | Container style overrides |
563
+
564
+ **GridItem Props:**
565
+
566
+ | Prop | Type | Default | Description |
567
+ | ------------ | ---------------------------------------- | ------- | ------------------------- |
568
+ | `children` | `ReactNode` | - | Item content |
569
+ | `col` | `number` | `2` | Number of columns to span |
570
+ | `alignItems` | `"center" \| "flex-start" \| "flex-end"` | - | Item alignment |
571
+ | `spacing` | `number` | `1` | Item spacing |
572
+ | `style` | `ViewStyle` | `{}` | Item style overrides |
573
+
574
+ **Example:**
575
+
576
+ ```tsx
577
+ <Grid spacing={2}>
578
+ <GridItem col={2}>
579
+ <Typography>Full width item</Typography>
580
+ </GridItem>
581
+ <GridItem col={4} alignItems="center">
582
+ <Typography>Quarter width item</Typography>
583
+ </GridItem>
584
+ <GridItem col={4}>
585
+ <Typography>Another quarter width</Typography>
586
+ </GridItem>
587
+ </Grid>
588
+ ```
290
589
 
291
- A component for displaying a loading spinner.
590
+ ### FormWrapper
591
+
592
+ A wrapper component that provides keyboard handling and scrolling for forms.
292
593
 
293
594
  **Props:**
294
595
 
295
- | Prop | Type | Default | Description |
296
- | ----- | ------ | --------------- | ----------------------------------------------------------- |
297
- | size | string | "small" | The size of the spinner. Possible values: "small", "large". |
298
- | color | string | Theme-dependent | The color of the spinner. |
596
+ | Prop | Type | Default | Description |
597
+ | ------------------------ | ------------------------------- | ------------------ | --------------------------- |
598
+ | `children` | `ReactNode` | - | Form content |
599
+ | `mode` | `"scroll" \| "static"` | `"scroll"` | Wrapper mode |
600
+ | `behavior` | `KeyboardAvoidingView` behavior | Platform-dependent | Keyboard avoidance behavior |
601
+ | `keyboardVerticalOffset` | `number` | `10` | Keyboard offset |
602
+ | `contentContainerStyle` | `ViewStyle` | `{}` | ScrollView content style |
603
+ | `style` | `ViewStyle` | `{}` | Container style |
604
+ | `onScroll` | `(event) => void` | - | Scroll event handler |
605
+
606
+ **Example:**
607
+
608
+ ```tsx
609
+ <FormWrapper mode="scroll" keyboardVerticalOffset={20}>
610
+ <TextField label="Name" />
611
+ <TextField label="Email" />
612
+ <Button title="Submit" />
613
+ </FormWrapper>
614
+ ```
299
615
 
300
- ### TextField
616
+ ### List, ListItem & ListItemText
617
+
618
+ Components for displaying structured lists of data.
619
+
620
+ **List Props:**
621
+
622
+ | Prop | Type | Default | Description |
623
+ | ---------- | ----------- | ------- | ------------------------- |
624
+ | `children` | `ReactNode` | - | ListItem components |
625
+ | `style` | `ViewStyle` | `{}` | Container style overrides |
626
+
627
+ **ListItem Props:**
628
+
629
+ | Prop | Type | Default | Description |
630
+ | ---------- | ------------ | ------- | ------------------------- |
631
+ | `children` | `ReactNode` | - | Item content |
632
+ | `link` | `boolean` | `false` | Show arrow indicator |
633
+ | `divider` | `boolean` | `false` | Show bottom border |
634
+ | `onPress` | `() => void` | - | Press handler |
635
+ | `index` | `number` | `1` | Item index for animations |
636
+ | `style` | `ViewStyle` | `{}` | Item style overrides |
637
+
638
+ **ListItemText Props:**
639
+
640
+ | Prop | Type | Default | Description |
641
+ | ---------------- | ----------------- | ------- | ------------------------- |
642
+ | `primary` | `string` | - | Primary text |
643
+ | `secondary` | `string` | - | Secondary text |
644
+ | `divider` | `boolean` | `false` | Show bottom border |
645
+ | `primaryProps` | `TypographyProps` | `{}` | Primary text props |
646
+ | `secondaryProps` | `TypographyProps` | `{}` | Secondary text props |
647
+ | `style` | `ViewStyle` | `{}` | Container style overrides |
648
+
649
+ **Example:**
650
+
651
+ ```tsx
652
+ <List>
653
+ <ListItem link onPress={() => navigate("Profile")}>
654
+ <ListItemText primary="Profile Settings" secondary="Manage your account" />
655
+ </ListItem>
656
+ <ListItem divider>
657
+ <ListItemText primary="Notifications" />
658
+ </ListItem>
659
+ </List>
660
+ ```
661
+
662
+ ### Popup
301
663
 
302
- A component for text input.
664
+ A modal component for overlays, dialogs, and bottom sheets.
303
665
 
304
666
  **Props:**
305
667
 
306
- | Prop | Type | Default | Description |
307
- | ----------- | ------ | ------- | ----------------------------------- |
308
- | label | string | - | The label for the text input. |
309
- | placeholder | string | - | The placeholder text for the input. |
668
+ | Prop | Type | Default | Description |
669
+ | ------------------------ | ------------------- | ------- | ------------------------- |
670
+ | `open` | `boolean` | - | Whether popup is visible |
671
+ | `onClose` | `() => void` | - | Close handler |
672
+ | `title` | `string` | - | Popup title |
673
+ | `children` | `ReactNode` | - | Popup content |
674
+ | `sheet` | `boolean \| number` | `false` | Bottom sheet mode/height |
675
+ | `bare` | `boolean` | `false` | Hide header and padding |
676
+ | `keyboardVerticalOffset` | `number` | - | Keyboard avoidance offset |
677
+ | `style` | `ViewStyle` | `{}` | Container style overrides |
678
+
679
+ **Example:**
680
+
681
+ ```tsx
682
+ <Popup
683
+ open={isOpen}
684
+ onClose={() => setIsOpen(false)}
685
+ title="Confirm Action"
686
+ sheet={400}
687
+ >
688
+ <Typography>Are you sure you want to delete this item?</Typography>
689
+ <Button title="Delete" color="error" />
690
+ <Button title="Cancel" variant="outlined" />
691
+ </Popup>
692
+ ```
310
693
 
311
- ### TextField2
694
+ ### Spinner
312
695
 
313
- Another component for text input.
696
+ A loading indicator component with customizable appearance.
314
697
 
315
698
  **Props:**
316
699
 
317
- | Prop | Type | Default | Description |
318
- | ----------- | ------ | ------- | ----------------------------------- |
319
- | label | string | - | The label for the text input. |
320
- | placeholder | string | - | The placeholder text for the input. |
700
+ | Prop | Type | Default | Description |
701
+ | ------------ | -------------------- | ----------- | ------------------------- |
702
+ | `size` | `"small" \| "large"` | `"large"` | Spinner size |
703
+ | `color` | `string` | `"primary"` | Spinner color from theme |
704
+ | `label` | `string` | - | Loading text |
705
+ | `fullscreen` | `boolean` | `false` | Cover entire screen |
706
+ | `style` | `ViewStyle` | `{}` | Container style overrides |
321
707
 
322
- ### Typography
708
+ **Example:**
709
+
710
+ ```tsx
711
+ <Spinner size="large" color="primary" label="Loading..." fullscreen={true} />
712
+ ```
713
+
714
+ ### Animator
715
+
716
+ A unified component that provides a single interface for all animation types with generic props.
717
+
718
+ **Features:**
719
+
720
+ - **Single Component**: One component handles all animation types
721
+ - **Generic Props**: Consistent prop naming across all animations (e.g., `closeAfter` instead of animation-specific names)
722
+ - **Modular Hooks**: Animation logic is separated into individual custom hooks
723
+ - **Type Safety**: Full TypeScript support with proper typing
724
+ - **Performance**: Only the specified animation runs, others are not loaded
725
+
726
+ **Generic Props:**
727
+
728
+ All animation types support these generic props:
729
+
730
+ | Prop | Type | Default | Description |
731
+ | ------------ | --------------------------------------------------------------------------- | ------- | ------------------------------------------------------------- |
732
+ | `type` | `"fade" \| "grow" \| "slide" \| "blink" \| "float" \| "roll" \| "thrownup"` | - | Animation type |
733
+ | `duration` | `number` | `500` | Animation duration in milliseconds |
734
+ | `delay` | `number` | `0` | Delay before animation starts |
735
+ | `closeAfter` | `number \| null` | `null` | Time after which the exit animation starts (null for no exit) |
736
+ | `style` | `ViewStyle` | `{}` | Additional styles for the animated view |
737
+
738
+ **Animation-Specific Props:**
739
+
740
+ **Slide Animation:**
741
+
742
+ - `direction`: `"up" \| "down" \| "left" \| "right"`
743
+ - `initialValue`: Custom initial position value
744
+
745
+ **Grow Animation:**
746
+
747
+ - `initialScale`: Starting scale (default: 0)
748
+
749
+ **Blink Animation:**
750
+
751
+ - `blinkDuration`: Duration of one blink cycle
752
+ - `minOpacity`: Minimum opacity value
753
+ - `maxOpacity`: Maximum opacity value
754
+
755
+ **Float Animation:**
756
+
757
+ - `closeDuration`: Duration of exit animation
758
+ - `floatDistance`: Distance to float up/down
759
+ - `floatDuration`: Duration of one float cycle
760
+
761
+ **Roll Animation:**
762
+
763
+ - `initialTranslateY`: Initial vertical position
764
+ - `initialRotate`: Initial rotation value
765
+
766
+ **Examples:**
767
+
768
+ ```tsx
769
+ // Fade animation
770
+ <Animator type="fade" duration={1000} closeAfter={3000}>
771
+ <Text>This will fade in and out</Text>
772
+ </Animator>
773
+
774
+ // Slide animation
775
+ <Animator type="slide" direction="up" duration={800} closeAfter={2000}>
776
+ <View>This will slide up from bottom</View>
777
+ </Animator>
778
+
779
+ // Grow animation
780
+ <Animator type="grow" initialScale={0.5} duration={600}>
781
+ <Button>This will grow from 50% scale</Button>
782
+ </Animator>
783
+
784
+ // Blink animation (continuous)
785
+ <Animator type="blink" blinkDuration={1000} minOpacity={0.3}>
786
+ <Icon>This will blink continuously</Icon>
787
+ </Animator>
323
788
 
324
- A component for displaying text with different styles.
789
+ // Float animation
790
+ <Animator type="float" floatDistance={20} floatDuration={2000} closeAfter={5000}>
791
+ <View>This will float up and down</View>
792
+ </Animator>
793
+
794
+ // Roll animation
795
+ <Animator type="roll" initialRotate="45deg" duration={800}>
796
+ <Image>This will roll and rotate</Image>
797
+ </Animator>
798
+
799
+ // Thrown up animation
800
+ <Animator type="thrownup" delay={500} closeAfter={4000}>
801
+ <Notification>This will spring up from bottom</Notification>
802
+ </Animator>
803
+ ```
804
+
805
+ **Available Animation Types:**
806
+
807
+ 1. **fade**: Simple fade in/out
808
+ 2. **grow**: Scale-based growth animation
809
+ 3. **slide**: Directional slide animations
810
+ 4. **blink**: Continuous opacity blinking
811
+ 5. **float**: Floating up/down motion with fade
812
+ 6. **roll**: Combined rotation and translation
813
+ 7. **thrownup**: Spring-based upward animation
814
+
815
+ **Using Animation Hooks Directly:**
816
+
817
+ You can also use the animation hooks directly for custom implementations:
818
+
819
+ ```tsx
820
+ import { useFadeAnimation, useSlideAnimation } from "@hoddy-ui/core";
821
+
822
+ const MyComponent = () => {
823
+ const { animatedStyle } = useFadeAnimation({
824
+ duration: 800,
825
+ closeAfter: 2000,
826
+ });
827
+
828
+ return (
829
+ <Animated.View style={animatedStyle}>
830
+ <Text>Custom animated content</Text>
831
+ </Animated.View>
832
+ );
833
+ };
834
+ ```
835
+
836
+ **Migration from Old Components:**
837
+
838
+ Replace old individual animation components:
839
+
840
+ ```tsx
841
+ // Old way
842
+ <AnimatedFade fadeOutAfter={2000}>
843
+ <Text>Content</Text>
844
+ </AnimatedFade>
845
+
846
+ // New way
847
+ <Animator type="fade" closeAfter={2000}>
848
+ <Text>Content</Text>
849
+ </Animator>
850
+ ```
851
+
852
+ ### FlashMessage
853
+
854
+ Display toast notifications and alerts.
325
855
 
326
856
  **Props:**
327
857
 
328
- | Prop | Type | Default | Description |
329
- | -------- | ------ | ------- | ---------------------------------------------------------------------------------------------------- |
330
- | variant | string | "body" | The style variant of the text. Possible values: "heading", "title", "subheading", "body", "caption". |
331
- | children | node | - | The text content to be rendered. |
858
+ | Prop | Type | Default | Description |
859
+ | ---------- | --------------------------------------------- | -------- | ---------------------- |
860
+ | `message` | `string` | - | Message text |
861
+ | `type` | `"success" \| "error" \| "warning" \| "info"` | `"info"` | Message type |
862
+ | `duration` | `number` | `3000` | Display duration in ms |
863
+ | `position` | `"top" \| "bottom"` | `"top"` | Message position |
864
+
865
+ **Usage:**
866
+
867
+ ```tsx
868
+ import { showMessage } from "@hoddy-ui/core";
869
+
870
+ // Show a success message
871
+ showMessage({
872
+ message: "Profile updated successfully!",
873
+ type: "success",
874
+ });
875
+ ```
876
+
877
+ ## 🔧 Hooks
878
+
879
+ ### useColors
880
+
881
+ Access the current theme's color palette:
882
+
883
+ ```tsx
884
+ import { useColors } from "@hoddy-ui/core";
885
+
886
+ function MyComponent() {
887
+ const colors = useColors();
888
+
889
+ return (
890
+ <View style={{ backgroundColor: colors.primary.main }}>
891
+ {/* Component content */}
892
+ </View>
893
+ );
894
+ }
895
+ ```
896
+
897
+ ### useTheme
898
+
899
+ Access and control the current theme:
900
+
901
+ ```tsx
902
+ import { useTheme } from "@hoddy-ui/core";
903
+
904
+ function ThemeAwareComponent() {
905
+ const { themeState, themeDispatch } = useTheme();
906
+
907
+ const toggleTheme = () => {
908
+ themeDispatch({
909
+ type: themeState.mode === "dark" ? "light" : "dark",
910
+ });
911
+ };
912
+
913
+ return <Button title="Toggle Theme" onPress={toggleTheme} />;
914
+ }
915
+ ```
916
+
917
+ ### useNavScreenOptions
918
+
919
+ Get theme-aware navigation screen options:
920
+
921
+ ```tsx
922
+ import { useNavScreenOptions } from "@hoddy-ui/core";
923
+
924
+ function MyScreen() {
925
+ const screenOptions = useNavScreenOptions("stack");
926
+
927
+ // Use with React Navigation
928
+ return (
929
+ <Stack.Screen name="Home" component={HomeScreen} options={screenOptions} />
930
+ );
931
+ }
932
+ ```
933
+
934
+ ### Animation Hooks
935
+
936
+ Access animation logic directly for custom implementations:
937
+
938
+ #### useFadeAnimation
939
+
940
+ ```tsx
941
+ import { useFadeAnimation } from "@hoddy-ui/core";
942
+
943
+ function FadeComponent() {
944
+ const { animatedStyle } = useFadeAnimation({
945
+ duration: 800,
946
+ closeAfter: 2000,
947
+ });
948
+
949
+ return (
950
+ <Animated.View style={animatedStyle}>
951
+ <Text>This will fade in and out</Text>
952
+ </Animated.View>
953
+ );
954
+ }
955
+ ```
956
+
957
+ #### useSlideAnimation
958
+
959
+ ```tsx
960
+ import { useSlideAnimation } from "@hoddy-ui/core";
961
+
962
+ function SlideComponent() {
963
+ const { animatedStyle } = useSlideAnimation({
964
+ direction: "up",
965
+ duration: 600,
966
+ initialValue: 100,
967
+ });
968
+
969
+ return (
970
+ <Animated.View style={animatedStyle}>
971
+ <Text>This will slide up</Text>
972
+ </Animated.View>
973
+ );
974
+ }
975
+ ```
976
+
977
+ #### useGrowAnimation
978
+
979
+ ```tsx
980
+ import { useGrowAnimation } from "@hoddy-ui/core";
981
+
982
+ function GrowComponent() {
983
+ const { animatedStyle } = useGrowAnimation({
984
+ duration: 500,
985
+ initialScale: 0.5,
986
+ });
987
+
988
+ return (
989
+ <Animated.View style={animatedStyle}>
990
+ <Text>This will grow from 50% scale</Text>
991
+ </Animated.View>
992
+ );
993
+ }
994
+ ```
995
+
996
+ #### Other Animation Hooks
997
+
998
+ - `useBlinkAnimation` - For continuous blinking effects
999
+ - `useFloatAnimation` - For floating up/down motion
1000
+ - `useRollAnimation` - For rotation and translation effects
1001
+ - `useThrownUpAnimation` - For spring-based upward animations
1002
+
1003
+ All animation hooks accept similar configuration objects with properties like `duration`, `delay`, and animation-specific options.
1004
+
1005
+ ## 🎯 Advanced Usage
1006
+
1007
+ ### Custom Theme Provider
1008
+
1009
+ Create your own theme provider with custom configurations:
1010
+
1011
+ ```tsx
1012
+ import { UIThemeProvider, initialize } from "@hoddy-ui/core";
1013
+
1014
+ // Initialize with custom configuration
1015
+ initialize({
1016
+ fontFamily: "CustomFont-Regular",
1017
+ colors: {
1018
+ primary: { main: "#FF6B6B" },
1019
+ secondary: { main: "#4ECDC4" },
1020
+ },
1021
+ });
1022
+
1023
+ function App() {
1024
+ return (
1025
+ <UIThemeProvider>
1026
+ <YourAppContent />
1027
+ </UIThemeProvider>
1028
+ );
1029
+ }
1030
+ ```
1031
+
1032
+ ### Form Validation Example
1033
+
1034
+ ```tsx
1035
+ import React, { useState } from "react";
1036
+ import { View } from "react-native";
1037
+ import { TextField, Button, FormWrapper } from "@hoddy-ui/core";
1038
+
1039
+ function LoginForm() {
1040
+ const [email, setEmail] = useState("");
1041
+ const [password, setPassword] = useState("");
1042
+ const [errors, setErrors] = useState({});
1043
+
1044
+ const validate = () => {
1045
+ const newErrors = {};
1046
+ if (!email) newErrors.email = "Email is required";
1047
+ if (!password) newErrors.password = "Password is required";
1048
+ setErrors(newErrors);
1049
+ return Object.keys(newErrors).length === 0;
1050
+ };
1051
+
1052
+ const handleSubmit = () => {
1053
+ if (validate()) {
1054
+ // Handle form submission
1055
+ }
1056
+ };
1057
+
1058
+ return (
1059
+ <FormWrapper>
1060
+ <TextField
1061
+ label="Email"
1062
+ value={email}
1063
+ onChangeText={setEmail}
1064
+ error={!!errors.email}
1065
+ helperText={errors.email}
1066
+ keyboardType="email-address"
1067
+ />
1068
+
1069
+ <TextField
1070
+ label="Password"
1071
+ value={password}
1072
+ onChangeText={setPassword}
1073
+ error={!!errors.password}
1074
+ helperText={errors.password}
1075
+ secureTextEntry
1076
+ />
1077
+
1078
+ <Button
1079
+ title="Login"
1080
+ onPress={handleSubmit}
1081
+ variant="contained"
1082
+ color="primary"
1083
+ />
1084
+ </FormWrapper>
1085
+ );
1086
+ }
1087
+ ```
1088
+
1089
+ ## 📱 Platform Compatibility
1090
+
1091
+ - **React Native**: ≥ 0.71.8
1092
+ - **Expo**: SDK 48+
1093
+ - **iOS**: 11.0+
1094
+ - **Android**: API 21+ (Android 5.0)
1095
+ - **TypeScript**: ≥ 5.0.4
1096
+
1097
+ ## 🤝 Contributing
1098
+
1099
+ We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
1100
+
1101
+ ## 📄 License
1102
+
1103
+ MIT © [Hoddy Inc](https://github.com/kinghoddy)
1104
+
1105
+ ## 🔗 Links
1106
+
1107
+ - [GitHub Repository](https://github.com/kinghoddy/hoddy-ui)
1108
+ - [npm Package](https://www.npmjs.com/package/@hoddy-ui/core)
1109
+ - [Issues & Support](https://github.com/kinghoddy/hoddy-ui/issues)
1110
+
1111
+ ---
1112
+
1113
+ **Need help?** [Open an issue](https://github.com/kinghoddy/hoddy-ui/issues) or check out our [examples](../../test/hoddyui).