UNPKG

@naarni/design-system

Version:

Naarni React Native Design System for EV Fleet Apps

942 lines (810 loc) 20.6 kB
# @naarni/design-system A comprehensive React Native design system for EV Fleet applications, built with TypeScript and modern React Native patterns. ## 🚀 Features - **TypeScript First**: Full TypeScript support with proper type definitions - **Modern Components**: Built with React Native best practices - **Customizable**: Easy to customize and extend - **Performance Optimized**: Memoized components and optimized rendering - **Accessibility**: Built-in accessibility support - **Theme Support**: Flexible theming system - **Chart Components**: Built-in LineChart and BarChart with Skia - **Form Components**: InputBox with validation and grouping support ## 📦 Installation ```bash npm install @naarni/design-system # or yarn add @naarni/design-system ``` ## 🔧 Peer Dependencies This package requires the following peer dependencies: ```json { "react": ">=18.0.0", "react-native": ">=0.70.0", "react-native-vector-icons": ">=10.0.0", "react-native-safe-area-context": ">=4.0.0", "react-native-maps": ">=1.7.0" } ``` **Note:** For Google Maps functionality, you'll need to: 1. Set up Google Maps API keys in your Android and iOS projects 2. Configure the necessary permissions for location services ## 🎨 Components ### Button A versatile button component with multiple variants, sizes, and states. ```tsx import { Button } from '@naarni/design-system'; // Basic usage <Button variant="primary" onPress={() => console.log('Pressed!')}> Click Me </Button> // With different variants <Button variant="secondary">Secondary</Button> <Button variant="outline">Outline</Button> <Button variant="text">Text Button</Button> <Button variant="ghost">Ghost</Button> // Different sizes <Button variant="primary" size="small">Small</Button> <Button variant="primary" size="medium">Medium</Button> <Button variant="primary" size="large">Large</Button> // States <Button variant="primary" loading>Loading...</Button> <Button variant="primary" disabled>Disabled</Button> <Button variant="primary" loading loadingText="Processing..."> Loading with Text </Button> // With icons <Button variant="primary" icon={<Icon name="arrow-right" size={16} />} iconPosition="right" > Next </Button> // Full width <Button variant="primary" fullWidth>Full Width Button</Button> ``` **Button Props:** ```tsx interface ButtonProps { variant?: 'primary' | 'secondary' | 'outline' | 'text' | 'ghost'; size?: 'small' | 'medium' | 'large'; loading?: boolean; disabled?: boolean; fullWidth?: boolean; style?: ViewStyle; textStyle?: TextStyle; icon?: React.ReactNode; iconPosition?: 'left' | 'right'; onPress?: () => void; onLongPress?: () => void; activeOpacity?: number; children: React.ReactNode; loadingText?: string; accessibilityLabel?: string; accessibilityHint?: string; testID?: string; } ``` ### Text A flexible text component with predefined typography variants. ```tsx import { Text } from '@naarni/design-system'; // Basic usage <Text>Hello World</Text> // Typography variants <Text variant="h1">Heading 1</Text> <Text variant="h2">Heading 2</Text> <Text variant="h3">Heading 3</Text> <Text variant="h4">Heading 4</Text> <Text variant="h5">Heading 5</Text> <Text variant="h6">Heading 6</Text> <Text variant="body1">Body text</Text> <Text variant="body2">Smaller body text</Text> <Text variant="subtitle1">Subtitle 1</Text> <Text variant="subtitle2">Subtitle 2</Text> <Text variant="button">Button text</Text> <Text variant="caption">Caption text</Text> <Text variant="overline">Overline text</Text> <Text variant="code">Code text</Text> // Custom styling <Text variant="h1" color="#007AFF" align="center" weight="bold"> Custom Styled Text </Text> // Text truncation <Text variant="body1" numberOfLines={2} ellipsizeMode="tail"> This is a very long text that will be truncated after two lines... </Text> ``` **Text Props:** ```tsx interface TextProps { variant?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'body1' | 'body2' | 'subtitle1' | 'subtitle2' | 'button' | 'caption' | 'overline' | 'code'; color?: string; align?: 'auto' | 'left' | 'right' | 'center' | 'justify'; weight?: 'thin' | 'extralight' | 'light' | 'regular' | 'medium' | 'semibold' | 'bold' | 'extrabold' | 'black'; style?: TextStyle; children: ReactNode; numberOfLines?: number; ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip'; testID?: string; } ``` ### Card A container component with optional title, subtitle, and animations. ```tsx import { Card } from '@naarni/design-system'; // Basic card <Card title="Card Title" subtitle="Card Subtitle"> <Text variant="body1">Card content goes here</Text> </Card> // Card with image <Card title="Vehicle Info" subtitle="Tesla Model 3" image={require('./assets/tesla.jpg')} > <Text variant="body1">Electric vehicle details...</Text> </Card> // Animated cards <Card title="Animated Card" animated animationType="shine" loop={true} > <Text variant="body1">This card has a shine animation</Text> </Card> // Custom styling <Card title="Custom Card" backgroundColor="#f0f0f0" elevation={8} style={{ marginVertical: 16 }} > <Text variant="body1">Custom styled card</Text> </Card> ``` **Card Props:** ```tsx interface CardProps { title?: string; subtitle?: string; image?: ImageSourcePropType; elevation?: number; style?: ViewStyle; children?: ReactNode; backgroundColor?: string; key?: string | number; animated?: boolean; animationType?: 'none' | 'shine' | 'sine-shine' | 'stars' | 'drops'; loop?: boolean; } ``` ### Alert A notification component for displaying messages to users. ```tsx import { Alert } from '@naarni/design-system'; // Basic alert <Alert type="success" title="Success!" message="Operation completed successfully" /> // Different alert types <Alert type="info" title="Information" message="Here's some info" /> <Alert type="warning" title="Warning" message="Please be careful" /> <Alert type="error" title="Error" message="Something went wrong" /> // Dismissible alert <Alert type="info" title="Dismissible" message="You can close this alert" dismissible onDismiss={() => console.log('Alert dismissed')} /> // Alert with actions <Alert type="warning" title="Confirm Action" message="Are you sure you want to proceed?" actions={[ { label: 'Cancel', onPress: () => console.log('Cancelled'), variant: 'outline' }, { label: 'Confirm', onPress: () => console.log('Confirmed'), variant: 'primary' } ]} /> ``` **Alert Props:** ```tsx interface AlertProps { variant?: 'info' | 'success' | 'warning' | 'error'; title?: string; message: string; dismissible?: boolean; persistent?: boolean; onDismiss?: () => void; icon?: ReactNode; style?: ViewStyle; actions?: AlertAction[]; } interface AlertAction { label: string; onPress: () => void; variant?: 'primary' | 'secondary' | 'outline' | 'text' | 'ghost'; } ``` ### InputBox A form input component with validation and icon support. ```tsx import { InputBox, InputBoxGroup } from '@naarni/design-system'; // Basic input <InputBox placeholder="Enter your email" type="email" label="Email Address" /> // Input with validation <InputBox placeholder="Enter password" type="password" label="Password" error="Password must be at least 8 characters" leftIcon="lock" /> // Input with icons <InputBox placeholder="Search..." leftIcon="search" rightIcon="clear" onRightIconPress={() => console.log('Clear pressed')} /> // Different variants and sizes <InputBox variant="filled" size="large" placeholder="Large filled input" /> // Input group <InputBoxGroup direction="horizontal" spacing={16}> <InputBox placeholder="First Name" /> <InputBox placeholder="Last Name" /> </InputBoxGroup> <InputBoxGroup direction="vertical" spacing={12}> <InputBox placeholder="Email" type="email" /> <InputBox placeholder="Password" type="password" /> <InputBox placeholder="Confirm Password" type="password" /> </InputBoxGroup> ``` **InputBox Props:** ```tsx interface InputBoxProps extends Omit<TextInputProps, 'style'> { placeholder?: string; error?: string; type?: 'text' | 'email' | 'password' | 'phone' | 'number' | 'url'; leftIcon?: string; rightIcon?: string; onRightIconPress?: () => void; disabled?: boolean; label?: string; helperText?: string; variant?: 'outlined' | 'filled'; size?: 'small' | 'medium' | 'large'; fullWidth?: boolean; style?: any; containerStyle?: any; } interface InputBoxGroupProps { children: React.ReactNode; direction?: 'horizontal' | 'vertical'; spacing?: number; style?: any; } ``` ### Icon A wrapper around react-native-vector-icons for consistent icon usage. ```tsx import { Icon } from '@naarni/design-system'; // Basic icon <Icon name="home" size={24} color="#007AFF" /> // Different sizes <Icon name="star" size={16} /> <Icon name="star" size={24} /> <Icon name="star" size={32} /> // With custom colors <Icon name="heart" size={24} color="#FF3B30" /> <Icon name="check" size={24} color="#34C759" /> ``` **Icon Props:** ```tsx interface IconProps { name: string; size?: number; color?: string; style?: any; } ``` ### Charts Chart components built with React Native Skia for smooth animations. #### LineChart ```tsx import { LineChart } from '@naarni/design-system'; // Basic line chart <LineChart data={[10, 20, 15, 30, 25, 40, 35]} width={300} height={200} /> // With customization <LineChart data={[10, 20, 15, 30, 25, 40, 35]} width={300} height={200} color="#007AFF" showGrid={true} showXAxis={true} showYAxis={true} showTooltip={true} tooltipFormatter={(value, index) => `Point ${index}: ${value}`} /> ``` #### BarChart ```tsx import { BarChart } from '@naarni/design-system'; // Basic bar chart <BarChart data={[10, 20, 15, 30, 25, 40, 35]} width={300} height={200} /> // With customization <BarChart data={[10, 20, 15, 30, 25, 40, 35]} width={300} height={200} color="#34C759" showGrid={true} showXAxis={true} showYAxis={true} showTooltip={true} tooltipFormatter={(value, index) => `Bar ${index}: ${value}`} /> ``` **Chart Props:** ```tsx interface LineChartProps { data: number[]; width: number; height: number; showXAxis?: boolean; showYAxis?: boolean; isLabelOnXaxis?: boolean; isLabelOnYaxis?: boolean; color?: string; showGrid?: boolean; showTooltip?: boolean; tooltipFormatter?: (value: number, index: number) => string; } interface BarChartProps { data: number[]; width: number; height: number; showXAxis?: boolean; showYAxis?: boolean; isLabelOnXaxis?: boolean; isLabelOnYaxis?: boolean; color?: string; showGrid?: boolean; showTooltip?: boolean; tooltipFormatter?: (value: number, index: number) => string; } ``` ### BottomSheet A modal component that slides up from the bottom. ```tsx import { BottomSheet } from '@naarni/design-system'; // Basic bottom sheet <BottomSheet visible={isVisible} onClose={() => setIsVisible(false)} title="Bottom Sheet" > <Text variant="body1">Bottom sheet content goes here</Text> </BottomSheet> // With confirmation <BottomSheet visible={isVisible} onClose={() => setIsVisible(false)} onConfirm={() => { console.log('Confirmed'); setIsVisible(false); }} title="Confirm Action" confirmText="Confirm" cancelText="Cancel" > <Text variant="body1">Are you sure you want to proceed?</Text> </BottomSheet> // Custom snap points <BottomSheet visible={isVisible} onClose={() => setIsVisible(false)} snapPoints={[300, 500]} initialSnapPoint={300} showDragIndicator={true} > <Text variant="body1">Custom height bottom sheet</Text> </BottomSheet> ``` **BottomSheet Props:** ```tsx interface BottomSheetProps { visible: boolean; title?: string; children: ReactNode; onClose: () => void; onConfirm?: () => void; showDragIndicator?: boolean; initialSnapPoint?: number; snapPoints?: number[]; style?: ViewStyle; contentStyle?: ViewStyle; enablePanDownToClose?: boolean; confirmText?: string; cancelText?: string; } ``` ### Map A comprehensive map component for vehicle tracking using Google Maps. ```tsx import { Map, EnhancedMap, Vehicle } from '@naarni/design-system'; // Basic map with vehicles const vehicles: Vehicle[] = [ { id: '1', name: 'Tesla Model 3', latitude: 37.78825, longitude: -122.4324, speed: 65, battery: 85, status: 'active' } ]; <Map vehicles={vehicles} mapStyle="dark" onVehiclePress={(vehicle) => console.log(vehicle)} /> // Enhanced map with controls and vehicle info <EnhancedMap vehicles={vehicles} mapStyle="blackAndWhite" showControls={true} showVehicleInfo={true} onVehicleSelect={(vehicle) => setSelectedVehicle(vehicle)} /> // Custom map styling <Map vehicles={vehicles} customMapStyle={[ { elementType: 'geometry', stylers: [{ color: '#212121' }] }, { elementType: 'labels.text.fill', stylers: [{ color: '#757575' }] } ]} /> ``` **Map Props:** ```tsx interface MapProps { vehicles?: Vehicle[]; initialRegion?: Region; style?: ViewStyle; mapStyle?: 'default' | 'dark' | 'light' | 'blackAndWhite'; customMapStyle?: MapStyleConfig[]; showVehicleInfo?: boolean; autoFitToVehicles?: boolean; onVehiclePress?: (vehicle: Vehicle) => void; onMapPress?: (event: any) => void; onRegionChange?: (region: Region) => void; zoomEnabled?: boolean; scrollEnabled?: boolean; rotateEnabled?: boolean; pitchEnabled?: boolean; showsUserLocation?: boolean; showsMyLocationButton?: boolean; showsCompass?: boolean; showsScale?: boolean; loadingEnabled?: boolean; loadingIndicatorColor?: string; loadingBackgroundColor?: string; testID?: string; } ``` interface Vehicle { id?: string; name?: string; description?: string; latitude: number; longitude: number; heading?: number; color?: string; speed?: number; battery?: number; status?: 'active' | 'inactive' | 'charging' | 'maintenance'; lastUpdate?: Date; } ``` **EnhancedMap Props:** ```tsx interface EnhancedMapProps extends MapProps { showControls?: boolean; showVehicleInfo?: boolean; selectedVehicle?: Vehicle | null; onVehicleSelect?: (vehicle: Vehicle | null) => void; } ``` ## 🎯 Complete Usage Examples ### Basic App Setup ```tsx import React from 'react'; import { View, StyleSheet } from 'react-native'; import { Button, Text, Card, Alert, InputBox, InputBoxGroup } from '@naarni/design-system'; const App = () => { const [showAlert, setShowAlert] = React.useState(false); const [email, setEmail] = React.useState(''); const [password, setPassword] = React.useState(''); return ( <View style={styles.container}> <Text variant="h1" style={styles.title}> Welcome to Naarni </Text> <Card title="Login Form" style={styles.card}> <InputBoxGroup direction="vertical" spacing={16}> <InputBox placeholder="Enter your email" type="email" label="Email Address" value={email} onChangeText={setEmail} /> <InputBox placeholder="Enter your password" type="password" label="Password" value={password} onChangeText={setPassword} /> </InputBoxGroup> <Button variant="primary" fullWidth style={styles.button} onPress={() => setShowAlert(true)} > Login </Button> </Card> {showAlert && ( <Alert type="success" title="Success!" message="Login successful" dismissible onDismiss={() => setShowAlert(false)} /> )} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 16, backgroundColor: '#f5f5f5', }, title: { textAlign: 'center', marginVertical: 32, }, card: { marginVertical: 16, }, button: { marginTop: 24, }, }); export default App; ``` ### Dashboard Example ```tsx import React from 'react'; import { View, ScrollView, StyleSheet } from 'react-native'; import { Text, Card, Button, LineChart, BarChart, Icon, Map, Vehicle } from '@naarni/design-system'; const Dashboard = () => { const chartData = [10, 20, 15, 30, 25, 40, 35]; const vehicles: Vehicle[] = [ { id: '1', name: 'Tesla Model 3', latitude: 37.78825, longitude: -122.4324, speed: 65, battery: 85, status: 'active' }, { id: '2', name: 'Nissan Leaf', latitude: 37.78925, longitude: -122.4314, speed: 45, battery: 72, status: 'active' } ]; return ( <ScrollView style={styles.container}> <Text variant="h1" style={styles.title}> Fleet Dashboard </Text> {/* Stats Cards */} <View style={styles.statsRow}> <Card style={styles.statCard}> <Text variant="h3" color="#007AFF">24</Text> <Text variant="body2" color="#666">Active Vehicles</Text> </Card> <Card style={styles.statCard}> <Text variant="h3" color="#34C759">98%</Text> <Text variant="body2" color="#666">Uptime</Text> </Card> </View> {/* Vehicle Map */} <Card title="Live Vehicle Locations" style={styles.mapCard}> <Map vehicles={vehicles} mapStyle="dark" style={styles.map} onVehiclePress={(vehicle) => console.log('Vehicle pressed:', vehicle)} /> </Card> {/* Charts */} <Card title="Weekly Performance" style={styles.chartCard}> <LineChart data={chartData} width={300} height={200} color="#007AFF" showGrid={true} showTooltip={true} /> </Card> <Card title="Monthly Usage" style={styles.chartCard}> <BarChart data={chartData} width={300} height={200} color="#34C759" showGrid={true} showTooltip={true} /> </Card> {/* Actions */} <View style={styles.actions}> <Button variant="primary" icon={<Icon name="plus" size={16} />}> Add Vehicle </Button> <Button variant="outline" icon={<Icon name="settings" size={16} />}> Settings </Button> </View> </ScrollView> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 16, backgroundColor: '#f5f5f5', }, title: { marginBottom: 24, }, statsRow: { flexDirection: 'row', gap: 16, marginBottom: 24, }, statCard: { flex: 1, alignItems: 'center', padding: 16, }, mapCard: { height: 300, marginBottom: 24, }, map: { flex: 1, borderRadius: 8, }, chartCard: { marginBottom: 24, }, actions: { gap: 12, marginBottom: 24, }, }); export default Dashboard; ``` ## 🔧 Development ### Building ```bash npm run build ``` ### Testing Package ```bash npm run pack npm run test:pack ``` ### Publishing ```bash # Patch version (1.0.0 -> 1.0.1) npm run publish:patch # Minor version (1.0.0 -> 1.1.0) npm run publish:minor # Major version (1.0.0 -> 2.0.0) npm run publish:major ``` ## 📚 Typography System The design system includes a comprehensive typography system with predefined text styles: - **Headings**: `h1`, `h2`, `h3`, `h4`, `h5`, `h6` - **Body Text**: `body1`, `body2` - **Subtitles**: `subtitle1`, `subtitle2` - **Special**: `button`, `caption`, `overline`, `code` Each variant has optimized font sizes, weights, and spacing for different use cases. ## 🎨 Theme Support The design system supports theming through the typography system and individual component styling. You can customize colors, spacing, and other design tokens by extending the theme files. ## 🤝 Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests if applicable 5. Submit a pull request ## 📄 License MIT License - see LICENSE file for details ## 🆘 Support For support and questions: - Create an issue on GitHub - Check the examples in the `src/Examples` directory - Review the component interfaces for detailed prop information