# MotorInc Global Components

A comprehensive React Native component library with built-in theme support for consistent UI across different projects.

## Features

- 🎨 **Complete Theme System** - Light/dark mode with 100+ predefined colors
- 📱 **React Native Components** - Pre-built, customizable UI components
- 🔄 **Auto Theme Detection** - Automatically follows system theme preferences
- 💾 **Theme Persistence** - Remembers user theme preferences
- 🎯 **TypeScript Support** - Full TypeScript definitions included
- 📦 **Easy Integration** - Simple setup for any React Native project

## Installation

```bash
npm install motorinc-global-components
# or
yarn add motorinc-global-components
```

## Peer Dependencies

Make sure you have these peer dependencies installed:

```bash
npm install react-native-svg @react-native-async-storage/async-storage
```

## Quick Start

### 1. Wrap your app with ThemeContext

```tsx
import React from 'react';
import {ThemeContext} from 'motorinc-global-components';
import YourApp from './YourApp';

export default function App() {
  return (
    <ThemeContext>
      <YourApp />
    </ThemeContext>
  );
}
```

### 2. Use components in your app

```tsx
import React from 'react';
import {View} from 'react-native';
import {
  PlayyText,
  IconComponent,
  NavigationHeader,
  icons,
  SPACING_16,
  SPACING_24,
} from 'motorinc-global-components';

export default function YourApp() {
  return (
    <View>
      <NavigationHeader
        title="My App"
        backIcon
        isSearch
        titlePosition="center"
      />

      <PlayyText>This text automatically uses theme colors!</PlayyText>

      <PlayyText color="#FF0000">This text is always red</PlayyText>

      <IconComponent name={icons.search} size={24} />
    </View>
  );
}
```

## Components

### Header Compound Component (NEW in v2.0.0)

A flexible compound component system for creating headers with various configurations. The Header component follows the compound component pattern, allowing you to compose exactly the header layout you need.

#### Basic Usage

```tsx
import {Header} from 'motorinc-global-components';

// Simple header with title
<Header statusBarValue={44}>
  <Header.Row>
    <Header.Left backIcon onBackPress={() => navigation.goBack()} />
    <Header.Center title="Settings" />
    <Header.Right />
  </Header.Row>
</Header>

// Header with search
<Header statusBarValue={44}>
  <Header.Row>
    <Header.Left />
    <Header.Center title="Messages" />
    <Header.Right icons={[
      { name: 'search', onPress: () => setShowSearch(true) }
    ]} />
  </Header.Row>
  <Header.Search placeholder="Search messages..." onChangeText={handleSearch} />
</Header>
```

#### Advanced Examples

```tsx
// Contact header with avatar and online status
<Header statusBarValue={44}>
  <Header.Row>
    <Header.Left
      backIcon
      onBackPress={() => navigation.goBack()}
      isContact
      contactSource={{uri: 'avatar.jpg'}}
      contactTitle="John Doe"
      contactSubTitle="Online"
      isOnline
    />
    <Header.Right
      icons={[
        { name: 'call', onPress: handleCall },
        { name: 'videocall', onPress: handleVideoCall }
      ]}
    />
  </Header.Row>
</Header>

// Header with large title
<Header statusBarValue={44}>
  <Header.Row>
    <Header.Left showLeading leadingSource={avatarSource} />
    <Header.Right
      isButton
      buttonTitle="Edit"
      onButtonPress={handleEdit}
    />
  </Header.Row>
  <Header.Title title="Good Morning!" />
</Header>

// Header with prompt message
<Header
  statusBarValue={44}
  showPrompt="This is a sample prompt message"
>
  <Header.Row>
    <Header.Left backIcon onBackPress={handleBack} label="Back" />
    <Header.Center title="Dashboard" subtitle="Welcome back!" showSubtitle />
    <Header.Right icons={[{name: 'notification', onPress: handleNotifications}]} />
  </Header.Row>
</Header>
```

#### Header Component Props

**Main Header**

```tsx
interface HeaderProps {
  children: ReactNode;
  statusBarValue?: number; // Status bar height
  style?: StyleProp<ViewStyle>;
  showPrompt?: string; // Optional prompt message at top
}
```

**Header.Row**

```tsx
interface HeaderRowProps {
  children: ReactNode; // Should contain Header.Left, Header.Center, Header.Right
}
```

**Header.Left**

```tsx
interface HeaderLeftProps {
  children?: ReactNode; // Custom content (overrides other props)
  backIcon?: boolean; // Show back arrow
  backIconColor?: string;
  backIconWidth?: number;
  backIconHeight?: number;
  label?: string; // Text next to back icon
  labelColor?: string;
  onBackPress?: () => void;
  showLeading?: boolean; // Show leading avatar/image
  leadingSource?: ImageURISource;
  leadingContainerStyle?: StyleProp<ViewStyle>;
  onLeadingPress?: () => void;
  isContact?: boolean; // Show as contact header
  contactSource?: ImageURISource;
  contactName?: string;
  contactTitle?: string;
  contactSubTitle?: string;
  isOnline?: boolean; // Show online indicator
}
```

**Header.Center**

```tsx
interface HeaderCenterProps {
  children?: ReactNode; // Custom content (overrides other props)
  title?: string;
  titleColor?: string;
  subtitle?: string;
  showSubtitle?: boolean;
}
```

**Header.Right**

```tsx
interface HeaderRightProps {
  children?: ReactNode; // Custom content (overrides other props)
  icons?: Array<{
    name: string;
    onPress?: () => void;
    color?: string;
    size?: number;
  }>;
  isButton?: boolean; // Show as text button
  buttonTitle?: string;
  buttonTextColor?: string;
  buttonStyle?: StyleProp<ViewStyle>;
  onButtonPress?: () => void;
}
```

**Header.Title**

```tsx
interface HeaderTitleProps {
  title: string; // Large title text
}
```

**Header.Search**

```tsx
interface HeaderSearchProps {
  placeholder?: string; // Default: "Search"
  onChangeText?: (text: string) => void;
}
```

#### Migration from NavigationHeader

The compound component provides better composition than NavigationHeader:

```tsx
// Old NavigationHeader
<NavigationHeader
  statusBarvalue={44}
  backIcon
  title="Settings"
  handleBack={() => navigation.goBack()}
  iconsList={[{ name: 'search', onPress: handleSearch }]}
/>

// New Header compound component
<Header statusBarValue={44}>
  <Header.Row>
    <Header.Left backIcon onBackPress={() => navigation.goBack()} />
    <Header.Center title="Settings" />
    <Header.Right icons={[{ name: 'search', onPress: handleSearch }]} />
  </Header.Row>
</Header>
```

#### Features

- **Compound Component Pattern**: Mix and match sections as needed
- **Full TypeScript Support**: Complete type definitions for all props
- **Theme Integration**: Automatic theme color support
- **Status Bar Management**: Cross-platform status bar handling
- **Icon Integration**: Seamless IconComponent usage
- **Contact Display**: Avatar, name, subtitle, online status
- **Interactive Elements**: Touch handlers for buttons and icons
- **Search Functionality**: Built-in search input with styling
- **Flexible Composition**: Create any header layout combination

### PlayyText

Enhanced Text component with automatic theme support.

```tsx
// Automatic theme colors (default behavior)
<PlayyText>Uses colors.text_primary automatically</PlayyText>

// Custom color (overrides theme)
<PlayyText color="#FF0000">Always red text</PlayyText>

// Manual light/dark colors
<PlayyText lightColor="#000" darkColor="#FFF">
  Custom colors for each theme
</PlayyText>

// With styling
<PlayyText style={{ fontSize: 18, fontWeight: 'bold' }}>
  Styled text
</PlayyText>
```

### IconComponent

SVG icon component with theme-aware styling.

```tsx
<IconComponent
  name={icons.search} // Icon name from icons enum
  size={24} // Icon size
  fill="#007AFF" // Custom fill color
/>;

// Available icons
icons.search;
icons.back;
icons.microphone;
```

### Spacing

Consistent spacing constants for your layouts.

```tsx
import {
  SPACING_8,
  SPACING_16,
  SPACING_24,
  SPACING_32,
} from 'motorinc-global-components';

<View
  style={{
    padding: SPACING_16,
    margin: SPACING_8,
    gap: SPACING_12,
  }}>
  <PlayyText>Consistently spaced content</PlayyText>
</View>;

// Available spacing constants:
SPACING_2,
  SPACING_4,
  SPACING_6,
  SPACING_8,
  SPACING_10,
  SPACING_12,
  SPACING_14,
  SPACING_16,
  SPACING_18,
  SPACING_20,
  SPACING_24,
  SPACING_26,
  SPACING_30,
  SPACING_32,
  SPACING_34,
  SPACING_36,
  SPACING_40,
  SPACING_44,
  SPACING_46,
  SPACING_48,
  SPACING_52,
  SPACING_54,
  SPACING_56,
  SPACING_64,
  SPACING_72,
  SPACING_84;
```

### NavigationHeader

Complete navigation header with customizable layout.

```tsx
<NavigationHeader
  title="Page Title"
  backIcon={true}
  isSearch={true}
  titlePosition="center" // left | center | right
  showPrompt="Optional prompt message"
  statusBarvalue={100}
/>
```

## Theme System

### Using Theme Colors

The library provides 100+ predefined colors for both light and dark themes:

```tsx
import {useTheme} from 'motorinc-global-components';

function MyComponent() {
  const {colors, colorScheme, toggleTheme} = useTheme();

  return (
    <View style={{backgroundColor: colors.bg_primary}}>
      <Text style={{color: colors.text_primary}}>
        Current theme: {colorScheme}
      </Text>
      <TouchableOpacity onPress={toggleTheme}>
        <Text>Toggle Theme</Text>
      </TouchableOpacity>
    </View>
  );
}
```

### Available Theme Colors

- **Text colors**: `text_primary`, `text_secondary`, `text_tertiary`
- **Background colors**: `bg_primary`, `bg_secondary`, `bg_tertiary`
- **Button colors**: `button_primary`, `button_hover`, `button_pressed`
- **Status colors**: `status_success`, `status_error`, `status_warning`
- **Fill colors**: `fill_primary`, `fill_secondary`, `fill_tertiary`
- **Border colors**: `border_light`, `border_medium`, `border_strong`
- And 80+ more colors...

### Theme Management

```tsx
const {colorScheme, toggleTheme, setSelectedTheme} = useTheme();

// Toggle between light and dark
toggleTheme();

// Set specific theme
setSelectedTheme('light'); // Force light mode
setSelectedTheme('dark'); // Force dark mode
setSelectedTheme('system'); // Follow system (default)
```

## Metro Configuration

Add this to your `metro.config.js` for SVG support:

```js
const {getDefaultConfig} = require('@react-native/metro-config');

module.exports = (() => {
  const config = getDefaultConfig(__dirname);

  const {transformer, resolver} = config;

  config.transformer = {
    ...transformer,
    babelTransformerPath: require.resolve('react-native-svg-transformer'),
  };
  config.resolver = {
    ...resolver,
    assetExts: resolver.assetExts.filter(ext => ext !== 'svg'),
    sourceExts: [...resolver.sourceExts, 'svg'],
  };

  return config;
})();
```

## TypeScript Support

The library includes full TypeScript definitions. Import types as needed:

```tsx
import type {
  ColorsScheme,
  PlayyTextProps,
  IconProps,
  NavigationHeaderProps,
} from 'motorinc-global-components';
```

## ListView Component

The ListView component provides a flexible list item with optional swipe actions, similar to iOS native lists.

### Basic Usage

```tsx
import {ListView} from 'motorinc-global-components';

<ListView
  title="Basic List Item"
  subtitle="This is a subtitle"
  showRight={true}
  isRightArrow={true}
  handlePressListView={() => console.log('Pressed')}
/>;
```

### ListView with Swipe Actions

```tsx
import {ListView, SwipeAction} from 'motorinc-global-components';

const leftSwipeActions: SwipeAction[] = [
  {
    comp: (
      <View style={{alignItems: 'center'}}>
        <Icon name="edit" size={20} color="#FFFFFF" />
        <Text style={{color: '#FFFFFF', fontSize: 12}}>Edit</Text>
      </View>
    ),
    color: '#34C759',
    width: 80,
    onPress: () => console.log('Edit pressed'),
  },
];

const rightSwipeActions: SwipeAction[] = [
  {
    comp: (
      <View style={{alignItems: 'center'}}>
        <Icon name="delete" size={20} color="#FFFFFF" />
        <Text style={{color: '#FFFFFF', fontSize: 12}}>Delete</Text>
      </View>
    ),
    color: '#FF3B30',
    width: 80,
    onPress: () => console.log('Delete pressed'),
  },
];

<ListView
  title="Swipeable List Item"
  subtitle="Swipe left or right for actions"
  enableSwipe={true}
  swipeActions={{
    left: leftSwipeActions,
    right: rightSwipeActions,
  }}
  handlePressListView={() => console.log('Item pressed')}
/>;
```

### ListView Props

| Prop             | Type                                          | Description                    |
| ---------------- | --------------------------------------------- | ------------------------------ |
| `title`          | string                                        | Main title text                |
| `subtitle`       | string                                        | Optional subtitle text         |
| `enableSwipe`    | boolean                                       | Enable swipe gestures          |
| `swipeActions`   | {left?: SwipeAction[], right?: SwipeAction[]} | Grouped swipe actions          |
| `onEdit`         | () => void                                    | Legacy: Edit action callback   |
| `onDelete`       | () => void                                    | Legacy: Delete action callback |
| `showImage`      | boolean                                       | Show leading image             |
| `imageSource`    | ImageSource                                   | Image source for leading image |
| `showToggle`     | boolean                                       | Show toggle switch             |
| `toggleValue`    | boolean                                       | Toggle switch value            |
| `onToggleChange` | (value: boolean) => void                      | Toggle change callback         |

### SwipeAction Interface

```tsx
interface SwipeAction {
  comp: React.ReactNode; // Custom component to display
  color?: string; // Background color
  width?: number; // Action width (default: 80)
  onPress?: () => void; // Action callback
}
```

## Swipeable Component

Standalone swipeable wrapper for any content with WhatsApp-style smooth animations.

```tsx
import {SwipeableComponent} from 'motorinc-global-components';

<SwipeableComponent
  leftActions={leftActions}
  rightActions={rightActions}
  leftSwipeEnabled={true}
  rightSwipeEnabled={true}>
  <YourCustomContent />
</SwipeableComponent>;
```

### Features

- **Smooth Animations**: Scale, opacity, and translation animations
- **WhatsApp-style Behavior**: Elastic resistance and natural swipe limits
- **Multiple Actions**: Support for multiple actions on each side
- **Auto-close**: Actions automatically close after selection
- **Gesture Handler**: Built on react-native-gesture-handler for performance

## SwipeableListItem Component (NEW in v3.6.0)

A modern, feature-rich chat/list interface component with built-in swipe actions, perfect for messaging apps, chat lists, and swipeable item lists. Inspired by iOS WhatsApp and iMessage designs.

### Features

- ✅ **Avatar Support** - Image avatars with placeholder fallback
- ✅ **Rich Message Preview** - Name, message text, timestamp, and icons
- ✅ **Status Indicators** - Pinned badges, mention badges (@), unread count
- ✅ **Typing Indicator** - Shows "User is typing..." state
- ✅ **Deleted Messages** - Special styling for deleted message state
- ✅ **Swipe Actions** - Customizable left/right swipe gestures
- ✅ **Fully Themed** - Auto dark/light mode support
- ✅ **Performance Optimized** - Ready for large lists with FlatList

### Basic Usage

```tsx
import {SwipeableListItem} from 'motorinc-global-components';

<SwipeableListItem
  chatProps={{
    name: 'John Doe',
    message: 'Hey, how are you?',
    timestamp: '2:30 PM',
    avatar: require('./avatar.jpg'),
    onPress: () => console.log('Chat pressed'),
  }}
/>;
```

### Advanced Usage with Swipe Actions

```tsx
import {SwipeableListItem, GLYPHS} from 'motorinc-global-components';

<SwipeableListItem
  chatProps={{
    name: 'John Doe',
    message: 'Hey, how are you?',
    timestamp: '2:30 PM',
    avatar: require('./avatar.jpg'),

    // Status indicators
    isPinned: true,
    pinnedIcon: <Text>{GLYPHS['pin-fill'].char}</Text>,
    isMentioned: true,
    unreadCount: 3,

    // Message states
    isTyping: false,
    isDeleted: false,
    messageIcon: <Text>{GLYPHS['checkmark-message-fill'].char}</Text>,

    // Swipe actions
    readStatus: 'unread',
    showPinAction: true,
    onToggleReadStatus: () => console.log('Toggle read status'),
    onTogglePin: () => console.log('Toggle pin'),
    onMute: () => console.log('Mute chat'),
    onArchive: () => console.log('Archive chat'),
    onMore: () => console.log('More options'),

    // Custom colors (optional)
    leftActionColors: {
      read: '#007AFF',
      pin: '#8E8E93',
    },
    rightActionColors: {
      mute: '#FF3B30',
      archive: '#FF9500',
      more: '#8E8E93',
    },

    onPress: () => console.log('Chat pressed'),
  }}
/>;
```

### Usage with FlatList

```tsx
import React from 'react';
import {FlatList} from 'react-native';
import {SwipeableListItem} from 'motorinc-global-components';

const chatData = [
  {
    id: '1',
    name: 'Alice Johnson',
    message: 'See you tomorrow!',
    timestamp: '2:30 PM',
    unreadCount: 2,
  },
  {
    id: '2',
    name: 'Bob Smith',
    message: 'Thanks for the update',
    timestamp: '1:15 PM',
    isPinned: true,
  },
  // ... more chats
];

function ChatListScreen() {
  return (
    <FlatList
      data={chatData}
      keyExtractor={item => item.id}
      renderItem={({item}) => (
        <SwipeableListItem
          chatProps={{
            name: item.name,
            message: item.message,
            timestamp: item.timestamp,
            avatar: item.avatar,
            isPinned: item.isPinned,
            unreadCount: item.unreadCount,
            readStatus: item.unreadCount > 0 ? 'unread' : 'read',
            showPinAction: true,
            onToggleReadStatus: () => handleToggleRead(item.id),
            onTogglePin: () => handleTogglePin(item.id),
            onMute: () => handleMute(item.id),
            onArchive: () => handleArchive(item.id),
            onPress: () => navigation.navigate('Chat', {id: item.id}),
          }}
        />
      )}
    />
  );
}
```

### Props Interface

```tsx
interface ChatItemProps {
  // Required props
  name: string; // Contact/chat name
  timestamp: string; // Time/date display

  // Content props
  message?: string; // Message preview text
  avatar?: ImageSourcePropType; // Avatar image

  // Status indicators
  isPinned?: boolean; // Show pinned badge
  pinnedIcon?: React.ReactNode; // Custom pin icon
  isMentioned?: boolean; // Show @ badge
  unreadCount?: number; // Unread message count

  // Message states
  isTyping?: boolean; // Show "User is typing..."
  isDeleted?: boolean; // Show deleted message state
  messageIcon?: React.ReactNode; // Icon in message preview

  // Swipe actions
  readStatus?: 'read' | 'unread'; // Enable read/unread toggle
  showPinAction?: boolean; // Enable pin action

  // Callbacks
  onToggleReadStatus?: () => void; // Read/unread toggle
  onTogglePin?: () => void; // Pin toggle
  onPress?: () => void; // Item press
  onMute?: () => void; // Mute action
  onArchive?: () => void; // Archive action
  onMore?: () => void; // More options

  // Custom colors (optional)
  leftActionColors?: {
    read?: string;
    pin?: string;
  };
  rightActionColors?: {
    mute?: string;
    archive?: string;
    more?: string;
  };
}
```

### Swipe Actions

**Left Swipe Actions:**

- **Read/Unread** (blue) - Toggle read status
- **Pin** (gray) - Pin/unpin chat

**Right Swipe Actions:**

- **Mute** (red) - Mute notifications
- **Archive** (orange) - Archive chat
- **More** (gray) - Additional options

### Styling & Theming

The component automatically adapts to your theme:

```tsx
// Light mode
background: colors.background_primary(white);
text: colors.labels_primary(black);

// Dark mode
background: colors.background_primary(black);
text: colors.labels_primary(white);
```

All colors are theme-aware and will automatically update when theme changes.

## Examples

### Complete App Example

```tsx
import React from 'react';
import {View, ScrollView, TouchableOpacity} from 'react-native';
import {
  ThemeContext,
  useTheme,
  PlayyText,
  IconComponent,
  NavigationHeader,
  icons,
  SPACING_10,
  SPACING_16,
  SPACING_20,
} from 'motorinc-global-components';

function AppContent() {
  const {colors, colorScheme, toggleTheme} = useTheme();

  return (
    <View style={{flex: 1, backgroundColor: colors.bg_primary}}>
      <NavigationHeader
        title="My App"
        backIcon
        isSearch
        titlePosition="center"
      />

      <ScrollView style={{padding: SPACING_20}}>
        <PlayyText
          style={{fontSize: 24, fontWeight: 'bold', marginBottom: SPACING_10}}>
          Welcome to Motor Inc Components
        </PlayyText>

        <PlayyText style={{marginBottom: SPACING_20}}>
          Current theme: {colorScheme}
        </PlayyText>

        <TouchableOpacity
          onPress={toggleTheme}
          style={{
            backgroundColor: colors.button_primary,
            padding: SPACING_16,
            borderRadius: 8,
            alignItems: 'center',
            marginBottom: SPACING_20,
          }}>
          <PlayyText style={{color: colors.white}}>Toggle Theme</PlayyText>
        </TouchableOpacity>

        <View style={{flexDirection: 'row', justifyContent: 'space-around'}}>
          <IconComponent name={icons.search} size={30} />
          <IconComponent name={icons.back} size={30} />
          <IconComponent name={icons.microphone} size={30} />
        </View>
      </ScrollView>
    </View>
  );
}

export default function App() {
  return (
    <ThemeContext>
      <AppContent />
    </ThemeContext>
  );
}
```

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
