npm package: @staccats/sdk-react
Description: React components and hooks for integrating Staccats notifications into your React application.
Latest version: 0.1.0

# @staccats/sdk-react

React components and hooks for integrating Staccats notifications into your React application.

## Installation

```bash
npm install @staccats/sdk-react @staccats/sdk-js react react-dom
```

or with yarn:

```bash
yarn add @staccats/sdk-react @staccats/sdk-js react react-dom
```

or with bun:

```bash
bun add @staccats/sdk-react @staccats/sdk-js react react-dom
```

## Quick Start

### 1. Import Styles

First, import the CSS file in your app entry point:

```tsx
import '@staccats/sdk-react/style.css';
```

### 2. Add Notification Components

```tsx
import React from 'react';
import {
	NotificationBell,
	NotificationDropdown,
	NotificationToastContainer,
} from '@staccats/sdk-react';
import '@staccats/sdk-react/style.css';

function App() {
	const currentUserId = 'user_123';
	const apiKey = 'pk_your_public_key';

	const handleNotificationClick = (notification) => {
		console.log('Notification clicked:', notification);
		// Handle navigation, etc.
	};

	return (
		<div>
			{/* Notification Bell */}
			<NotificationBell userId={currentUserId} apiKey={apiKey} onClick={() => {}} />

			{/* Notification Dropdown */}
			<NotificationDropdown
				userId={currentUserId}
				apiKey={apiKey}
				onNotificationClick={handleNotificationClick}
			/>

			{/* Toast Container (for showing new notifications) */}
			<NotificationToastContainer userId={currentUserId} apiKey={apiKey} />
		</div>
	);
}
```

## Components

### NotificationBell

A simple bell icon with unread badge.

```tsx
<NotificationBell
	userId={userId}
	apiKey={apiKey}
	apiUrl={apiUrl}
	className="custom-class"
	theme="auto"
	onClick={handleClick}
	icon={<CustomIcon />}
/>
```

**Props:**
- `userId` (string, required) - The user ID
- `apiKey` (string, required) - Your Staccats API key (public key for client-side)
- `apiUrl` (string, optional) - API URL (defaults to `https://api.staccats.com`)
- `className` (string, optional) - Additional CSS classes
- `theme` ('light' | 'dark' | 'auto', optional) - Theme mode (defaults to 'auto')
- `onClick` (function, optional) - Click handler
- `icon` (ReactNode, optional) - Custom icon component

---

### NotificationDropdown

A dropdown menu showing all notifications.

```tsx
<NotificationDropdown
	userId={userId}
	apiKey={apiKey}
	apiUrl={apiUrl}
	position="bottom-right"
	theme="auto"
	onNotificationClick={handleClick}
	renderTrigger={(props) => <CustomTrigger {...props} />}
	renderEmpty={() => <div>No notifications</div>}
	icon={<CustomIcon />}
/>
```

**Props:**
- `userId` (string, required) - The user ID
- `apiKey` (string, required) - Your Staccats API key
- `apiUrl` (string, optional) - API URL
- `position` (string, optional) - Dropdown position: `'bottom-right'` | `'bottom-left'` | `'top-right'` | `'top-left'` (default: `'bottom-right'`)
- `className` (string, optional) - Additional CSS classes
- `theme` ('light' | 'dark' | 'auto', optional) - Theme mode (defaults to 'auto')
- `onNotificationClick` (function, optional) - Handler when notification is clicked
- `renderTrigger` (function, optional) - Custom trigger render function
- `renderEmpty` (function, optional) - Custom empty state render function
- `icon` (ReactNode, optional) - Custom icon component

---

### NotificationToastContainer

Automatically shows toast notifications for new notifications.

```tsx
<NotificationToastContainer
	userId={userId}
	apiKey={apiKey}
	apiUrl={apiUrl}
	position="top-right"
	duration={5000}
	theme="auto"
	stack={false}
/>
```

**Props:**
- `userId` (string, required) - The user ID
- `apiKey` (string, required) - Your Staccats API key
- `apiUrl` (string, optional) - API URL
- `position` (string, optional) - Toast position (default: `'top-right'`)
- `duration` (number, optional) - Auto-dismiss duration in ms (default: `5000`, set to `0` to disable)
- `theme` ('light' | 'dark' | 'auto', optional) - Theme mode (defaults to 'auto')
- `stack` (boolean, optional) - Stack toasts vertically instead of overlapping (default: `false`)

---

### NotificationToast

Individual toast notification (usually used via `NotificationToastContainer`).

```tsx
<NotificationToast
	notification={notification}
	position="top-right"
	duration={5000}
	theme="auto"
	stack={false}
	index={0}
	onDismiss={handleDismiss}
/>
```

## Hook

### useNotifications

Use the hook directly for custom implementations:

```tsx
import { useNotifications } from '@staccats/sdk-react';

function CustomNotifications() {
	const { notifications, unreadCount, loading, markAsRead, markAllAsRead, refresh, onNewNotification } =
		useNotifications('user_123', {
			apiKey: 'pk_your_public_key',
			apiUrl: 'https://api.staccats.com', // optional
		});

	useEffect(() => {
		const unsubscribe = onNewNotification((notification) => {
			console.log('New notification:', notification);
		});

		return unsubscribe;
	}, [onNewNotification]);

	return (
		<div>
			{notifications.map((notification) => (
				<div key={notification.id}>
					<h4>{notification.title}</h4>
					<p>{notification.message}</p>
					<button onClick={() => markAsRead(notification.id)}>Mark as read</button>
				</div>
			))}
		</div>
	);
}
```

**Returns:**
- `notifications` (Notification[]) - List of notifications
- `unreadCount` (number) - Number of unread notifications
- `loading` (boolean) - Loading state
- `markAsRead(notificationId: string)` - Mark a notification as read
- `markAllAsRead()` - Mark all notifications as read
- `refresh()` - Reload notifications from API
- `onNewNotification(callback)` - Register callback for new notifications (returns unsubscribe function)

## Shared State

All components using the same `userId` share the same notification state. This means:

- When you mark a notification as read in the dropdown, the bell badge updates automatically
- When a new notification arrives via WebSocket, all components update simultaneously
- No duplicate API calls - state is shared across components

## WebSocket Connection

Components automatically connect via WebSocket for real-time updates. The connection is:

- **Shared** - One WebSocket connection per userId
- **Auto-reconnecting** - Reconnects automatically on disconnect
- **Efficient** - Only one connection regardless of how many components you use

## Theming & Customization

### Theme Modes

Components support three theme modes:

- `'light'` - Always use light theme
- `'dark'` - Always use dark theme
- `'auto'` - Follows system preference (default)

### CSS Variables

Components use CSS variables for complete customization. Override them in your CSS:

```css
:root {
	/* Colors */
	--staccats-bg-primary: #ffffff;
	--staccats-text-primary: #111827;
	--staccats-color-primary: #3b82f6;
	--staccats-badge-bg: #ef4444;

	/* Spacing */
	--staccats-padding-lg: 16px;
	--staccats-gap-md: 12px;

	/* Border Radius */
	--staccats-radius-md: 8px;

	/* Typography */
	--staccats-font-size-base: 14px;
	--staccats-font-weight-semibold: 600;
}
```

### Scoped Theming

Use the `data-staccats-theme` attribute to scope theme overrides:

```tsx
<div data-staccats-theme="dark">
	<NotificationBell userId={userId} apiKey={apiKey} />
</div>
```

## Examples

### Basic Setup

```tsx
import { NotificationDropdown, NotificationToastContainer } from '@staccats/sdk-react';
import '@staccats/sdk-react/style.css';

function App() {
	const userId = 'user_123';
	const apiKey = process.env.REACT_APP_STACCATS_API_KEY;

	return (
		<div>
			<NotificationDropdown userId={userId} apiKey={apiKey} />
			<NotificationToastContainer userId={userId} apiKey={apiKey} />
		</div>
	);
}
```

### Custom Styling

```tsx
<NotificationBell
	userId={userId}
	apiKey={apiKey}
	className="my-custom-bell"
	icon={<CustomIcon />}
/>
```

```css
.my-custom-bell {
	border-radius: 50%;
	background: #f3f4f6;
	padding: 12px;
}
```

### Using Hook Directly

```tsx
import { useState } from 'react';
import { useNotifications } from '@staccats/sdk-react';

function CustomNotifications() {
	const [isOpen, setIsOpen] = useState(false);
	const { notifications, unreadCount, markAsRead } = useNotifications('user_123', {
		apiKey: 'pk_your_key',
	});

	return (
		<div>
			<button onClick={() => setIsOpen(!isOpen)}>
				Notifications {unreadCount > 0 && <span>{unreadCount}</span>}
			</button>
			{isOpen && (
				<div>
					{notifications.map((notification) => (
						<div key={notification.id}>
							<h4>{notification.title}</h4>
							<p>{notification.message}</p>
							<button onClick={() => markAsRead(notification.id)}>Mark as read</button>
						</div>
					))}
				</div>
			)}
		</div>
	);
}
```

### Toast Stacking

```tsx
<NotificationToastContainer
	userId={userId}
	apiKey={apiKey}
	position="top-right"
	stack={true}
/>
```

## TypeScript Support

Full TypeScript support is included. All types are exported:

```typescript
import type {
	Notification,
	NotificationBellProps,
	NotificationDropdownProps,
	NotificationToastProps,
	NotificationToastContainerProps,
	ThemeMode,
} from '@staccats/sdk-react';
```

## License

MIT