npm package: @social.dev/rn-sdk
Description: React Native SDK for Social.dev with reusable UI components
Author: social.dev Team
Latest version: 0.0.1-alpha.68

# @social.dev/rn-sdk

React Native SDK and UI Kit for Social.dev - A comprehensive toolkit for building social media applications with React Native and Expo.

## Overview

The `@social.dev/rn-sdk` package provides:

- 🎨 **Pre-built UI Components** - Complete set of customizable social media components
- 🔄 **Component Override System** - Replace any component with your own implementation
- 🎯 **Navigation Setup** - Pre-configured navigation with React Navigation
- 🔐 **Authentication** - Built-in auth flows with OIDC support
- 💬 **Chat System** - Real-time messaging components
- 📱 **Mobile-First** - Optimized for React Native with Expo support
- 🎭 **Theming** - Comprehensive theming system with dark mode support

## Installation

```bash
# Using pnpm (recommended)
pnpm add @social.dev/rn-sdk @social.dev/js-sdk

# Using npm
npm install @social.dev/rn-sdk @social.dev/js-sdk

# Using yarn
yarn add @social.dev/rn-sdk @social.dev/js-sdk
```

### Peer Dependencies

Make sure you have the following peer dependencies installed:

```bash
# Required Expo modules
npx expo install expo-audio expo-auth-session expo-crypto expo-linking expo-secure-store expo-web-browser

# Required React Navigation
pnpm add @react-navigation/native @react-navigation/native-stack @react-navigation/bottom-tabs @react-navigation/drawer

# Required for React Navigation
npx expo install react-native-screens react-native-safe-area-context

# Required for gestures and animations
npx expo install react-native-gesture-handler react-native-reanimated

# Required for bottom sheets
pnpm add @gorhom/bottom-sheet
```

## Quick Start

### Basic Setup

```tsx
import React from 'react';
import { SocialDevProvider, SocialDevApp } from '@social.dev/rn-sdk';
import { Platform } from 'react-native';

export default function App() {
  return (
    <SocialDevProvider
      apiBaseUrl={
        Platform.OS === 'web' ? '/api' : 'https://your-server.social.dev/api/'
      }
    >
      <SocialDevApp />
    </SocialDevProvider>
  );
}
```

### Advanced Setup with Component Overrides

```tsx
import React from 'react';
import {
  SocialDevProvider,
  SocialDevApp,
  ComponentLibrary,
  DefaultComponents,
} from '@social.dev/rn-sdk';
import { defaultRouterConfig } from '@social.dev/rn-sdk/navigation/AppNavigator';
import { Platform, Text, View } from 'react-native';

// Custom components
import CustomAvatar from './components/CustomAvatar';
import CustomHomeScreen from './screens/CustomHomeScreen';

export default function App() {
  // Custom navigation configuration
  const navConfig = {
    screens: {
      ...defaultRouterConfig?.screens,
      Home: { path: 'home', alias: ['homepage'] },
      Profile: { path: 'profile/:id' },
    },
  };

  // Override specific components
  const components: Partial<ComponentLibrary> = {
    // Override a single component
    Avatar: CustomAvatar,

    // Override nested components
    Post: {
      Post: CustomPost,
      PostToolbar: CustomPostToolbar,
    },

    // Override screens
    Screens: {
      ...DefaultComponents.Screens,
      HomeScreen: CustomHomeScreen,
      NotificationScreen: () => (
        <View>
          <Text>Custom Notification Screen</Text>
        </View>
      ),
    },
  };

  return (
    <SocialDevProvider
      apiBaseUrl={
        Platform.OS === 'web' ? '/api' : 'https://demo.social.dev/api/'
      }
      components={components}
      sdkConfig={{
        feed: {
          chatMode: true, // Enable chat mode for feeds
        },
      }}
    >
      <SocialDevApp navigationConfig={navConfig} />
    </SocialDevProvider>
  );
}
```

## Component Override System

The SDK uses a powerful component override system that allows you to replace any component with your own implementation while maintaining the rest of the SDK functionality.

### Available Component Categories

```typescript
interface ComponentLibrary {
  // Core UI Components
  Avatar: React.ComponentType;
  Button: React.ComponentType;
  Core: {
    Button: React.ComponentType;
    Icon: React.ComponentType;
    Pressable: React.ComponentType;
    TextInput: React.ComponentType;
  };

  // Authentication Components
  Auth: {
    AuthForm: React.ComponentType;
    OidcProvidersList: React.ComponentType;
  };

  // Chat Components
  Chat: {
    ChatConversationList: React.ComponentType;
    ChatConversationPanel: React.ComponentType;
    ChatCreate: React.ComponentType;
    ChatMessage: React.ComponentType;
  };

  // Community Components
  Community: {
    CommunityFeed: React.ComponentType;
    CommunityJoinButton: React.ComponentType;
    CommunityMembersList: React.ComponentType;
  };

  // Post Creation Components
  CreatePost: {
    CreatePost: React.ComponentType;
    CreatePostInline: React.ComponentType;
    CreatePostButton: React.ComponentType;
    ReplyToPostButton: React.ComponentType;
    CreatePostFab: React.ComponentType;
  };

  // Feed Components
  Feed: {
    Feed: React.ComponentType;
  };

  // Post Components
  Post: {
    Post: React.ComponentType;
    PostToolbar: React.ComponentType;
  };

  // User Components
  User: {
    UserListItem: React.ComponentType;
  };

  // Screen Components
  Screens: {
    AuthScreen: React.ComponentType;
    ChatScreen: React.ComponentType;
    ChatCreateScreen: React.ComponentType;
    CommunityCreateScreen: React.ComponentType;
    CommunityListScreen: React.ComponentType;
    CommunityProfileScreen: React.ComponentType;
    HomeScreen: React.ComponentType;
    NotificationScreen: React.ComponentType;
    PostViewScreen: React.ComponentType;
    ProfileScreen: React.ComponentType;
  };

  // Audio Components
  AudioPlayer: {
    AudioPlayer: React.ComponentType;
  };

  AudioVisualizer: {
    AudioVisualizer: React.ComponentType;
  };

  // Voice Recording
  VoiceRecorder: {
    VoiceRecorder: React.ComponentType;
    VoiceRecorderModal: React.ComponentType;
  };

  // Layout
  Layout: React.ComponentType;
}
```

### Override Examples

#### Example 1: Custom Avatar Component

```tsx
// components/CustomAvatar.tsx
import React from 'react';
import { View, Image, Text, StyleSheet } from 'react-native';

export default function CustomAvatar({ user, size = 40, onPress }) {
  return (
    <View style={[styles.container, { width: size, height: size }]}>
      {user?.avatar ? (
        <Image source={{ uri: user.avatar }} style={styles.image} />
      ) : (
        <Text style={styles.initial}>
          {user?.name?.[0]?.toUpperCase() || '?'}
        </Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    borderRadius: 999,
    backgroundColor: '#007AFF',
    alignItems: 'center',
    justifyContent: 'center',
  },
  image: {
    width: '100%',
    height: '100%',
    borderRadius: 999,
  },
  initial: {
    color: 'white',
    fontWeight: 'bold',
  },
});
```

#### Example 2: Custom Post Component

```tsx
// components/CustomPost.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { useComponentLibrary } from '@social.dev/rn-sdk';

export default function CustomPost({ post }) {
  const components = useComponentLibrary();
  const Avatar = components.Avatar;
  const PostToolbar = components.Post.PostToolbar;

  return (
    <View style={styles.container}>
      <View style={styles.header}>
        <Avatar user={post.author} size={32} />
        <Text style={styles.authorName}>{post.author.name}</Text>
      </View>
      <Text style={styles.content}>{post.content}</Text>
      <PostToolbar post={post} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 16,
    backgroundColor: 'white',
    marginBottom: 8,
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 12,
  },
  authorName: {
    marginLeft: 8,
    fontWeight: '600',
  },
  content: {
    fontSize: 14,
    marginBottom: 12,
  },
});
```

#### Example 3: Partial Screen Override

```tsx
// App.tsx
const components: Partial<ComponentLibrary> = {
  Screens: {
    // Keep all default screens
    ...DefaultComponents.Screens,
    // Override only the HomeScreen
    HomeScreen: () => {
      const { user } = useConfig();
      return (
        <View style={{ flex: 1, padding: 20 }}>
          <Text>Welcome {user?.name || 'Guest'}!</Text>
          <Feed />
        </View>
      );
    },
  },
};
```

## Hooks

### useApi

Access the API client for making authenticated requests:

```tsx
import { useApi } from '@social.dev/rn-sdk';

function MyComponent() {
  const api = useApi();

  const { data, error, isLoading } = api.useQuery(
    'get',
    '/posts',
    { params: { limit: 10 } }
  );

  const createPost = api.useMutation('post', '/posts');

  const handleSubmit = async (content: string) => {
    await createPost.mutateAsync({
      body: { content }
    });
  };

  return (
    // Your component JSX
  );
}
```

### useConfig

Access server configuration and user authentication state:

```tsx
import { useConfig } from '@social.dev/rn-sdk';

function MyComponent() {
  const { server, user, isLoggedIn, sdk, refetch } = useConfig();

  if (!isLoggedIn) {
    return <LoginPrompt />;
  }

  return (
    <View>
      <Text>Welcome {user.name}!</Text>
      <Text>Server: {server.title}</Text>
      <Button onPress={refetch} title="Refresh Config" />
    </View>
  );
}
```

### useComponentLibrary

Access the component library to use SDK components in your custom components:

```tsx
import { useComponentLibrary } from '@social.dev/rn-sdk';

function CustomFeed() {
  const components = useComponentLibrary();
  const { Feed, Post, Avatar } = components;

  return (
    <View>
      <Feed
        renderItem={({ item }) => (
          <View>
            <Avatar user={item.author} />
            <Post post={item} />
          </View>
        )}
      />
    </View>
  );
}
```

### useOpenChat

Navigate to or create a chat conversation:

```tsx
import { useOpenChat } from '@social.dev/rn-sdk';

function UserProfile({ userId }) {
  const { openChat, mutation } = useOpenChat({ userId });

  return (
    <Button onPress={openChat} title="Message" loading={mutation.isLoading} />
  );
}
```

### useTheme

Access the theme system:

```tsx
import { useTheme } from '@social.dev/rn-sdk';

function ThemedComponent() {
  const { colors, fonts, spacing } = useTheme();

  return (
    <View
      style={{
        backgroundColor: colors.background,
        padding: spacing.md,
      }}
    >
      <Text
        style={{
          color: colors.text,
          fontSize: fonts.sizes.body,
        }}
      >
        Themed content
      </Text>
    </View>
  );
}
```

## SDK Configuration

Configure the SDK behavior through the `sdkConfig` prop:

```tsx
<SocialDevProvider
  sdkConfig={{
    feed: {
      chatMode: true, // Reverse feed direction for chat-like experience
    },
  }}
>
  {/* Your app */}
</SocialDevProvider>
```

## Push Notifications

Setup push notifications with Expo:

```tsx
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';

async function registerForPushNotificationsAsync() {
  if (!Device.isDevice) return;

  const { status } = await Notifications.requestPermissionsAsync();
  if (status !== 'granted') return;

  const token = await Notifications.getExpoPushTokenAsync();
  return token.data;
}

export default function App() {
  const [pushToken, setPushToken] = useState<string>();

  useEffect(() => {
    registerForPushNotificationsAsync().then((token) => setPushToken(token));
  }, []);

  return (
    <SocialDevProvider
      pushNotificationToken={pushToken}
      // ... other props
    >
      <SocialDevApp />
    </SocialDevProvider>
  );
}
```

## Navigation Configuration

Customize the navigation structure:

```tsx
import { defaultRouterConfig } from '@social.dev/rn-sdk/navigation/AppNavigator';

const navConfig = {
  screens: {
    ...defaultRouterConfig?.screens,
    // Custom routes
    Home: { path: 'home', alias: ['homepage'] },
    Profile: { path: 'profile/:id' },
    Settings: { path: 'settings' },
  },
  // Deep linking configuration
  config: {
    initialRouteName: 'Home',
  },
};

<SocialDevApp navigationConfig={navConfig} />;
```

## Testing

The SDK includes comprehensive test utilities and mocks:

```bash
# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Generate coverage report
pnpm test --coverage
```

### Writing Tests for Components Using the SDK

```tsx
import { render } from '@testing-library/react-native';
import { SocialDevProvider } from '@social.dev/rn-sdk';

function renderWithProviders(component, options = {}) {
  return render(
    <SocialDevProvider apiBaseUrl="/api" {...options}>
      {component}
    </SocialDevProvider>
  );
}

test('my component renders', () => {
  const { getByText } = renderWithProviders(<MyComponent />);
  expect(getByText('Hello')).toBeTruthy();
});
```

## Development

```bash
# Install dependencies
pnpm install

# Build the package
pnpm build

# Watch for changes during development
pnpm dev

# Run tests
pnpm test

# Type checking
pnpm typecheck

# Linting
pnpm lint
```

## TypeScript Support

The SDK is written in TypeScript and provides full type definitions. Import types as needed:

```tsx
import type {
  ComponentLibrary,
  SdkConfig,
  User,
  Post,
  ApiComponents,
  ApiPaths,
} from '@social.dev/rn-sdk';
```

## Examples

Check out the [apps/mobile](../../apps/mobile) directory for a complete implementation example using the SDK.

## Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

## License

MIT

## Support

- [Documentation](https://docs.social.dev)
- [GitHub Issues](https://github.com/socialdotdev/social.dev/issues)
- [Discord Community](https://discord.gg/socialdev)