# react-storage-drafts

**react-storage-drafts** is a lightweight, flexible React context provider for managing, storing, and syncing local drafts (e.g. offline forms, notes, cached edits) with optional syncing strategies like intervals, connection changes, or manual triggers.

---

## 🚀 Features

- Store drafts locally in memory
- Add, update, and remove drafts
- Sync unsynced drafts with external storage
- Configurable sync triggers: `onChange`, `interval`, `connection`, or `manual`
- Optional integration with online/offline detection (via `navigator.onLine` or React Native `NetInfo`)

---

## 📦 Installation

```bash
npm install react-storage-drafts
```

or

```bash
yarn add react-storage-drafts
```

---

## 🔧 Usage

### 1. Wrap your app with the `Provider`

```tsx
import { Provider } from 'react-storage-drafts';

<Provider
  referenceKey="id"
  syncTrigger="connection" // or 'onChange' | 'interval' | 'manual'
  syncInterval={60} // optional, in seconds
  onSync={async (drafts) => {
    // Sync changed drafts to external storage (e.g. API)
    // Drafts will have a status property: 'changed' | 'removed'
    await api.saveDrafts(drafts);
  }}
  onLoadStoredData={async () => {
    return await api.loadDrafts();
  }}
>
  <YourApp />
</Provider>
```

---

### 2. Access drafts with useDrafts hook

```tsx
import { useDrafts } from 'react-storage-drafts';

const { drafts, count, addDraft, updateDraft, removeDraft, clearDrafts } = useDrafts();

// Example:
addDraft({ id: 'draft-1', title: 'New Draft' });
```

---

## 🧠 API Reference

### `<Provider />`

| Prop               | Type                            | Required | Description |
|--------------------|----------------------------------|----------|-------------|
| `referenceKey`     | `string`                         | ❌       | Key used to identify and manage each draft. If not provided, `_duid` autogenerated property will be used. |
| `syncTrigger`      | `'onChange' \| 'interval' \| 'connection' \| 'manual'` | ✅ | Determines when to trigger syncing. |
| `syncInterval`     | `number`                         | ❌       | Sync interval (in seconds) if `syncTrigger` is `'interval'`. Defaults to `120`. |
| `onSync`           | `(drafts: any[]) => void \| Promise<void>` | ✅ | Callback to sync unsynced drafts to external storage. Unsyced drafts will have `changed` (new/modified) or `removed` status |
| `onLoadStoredData` | `() => Promise<any[]>`           | ❌       | Callback to load initial data into the context. |

---

### useDrafts Hook

Use `useDrafts()` to access these values:

```ts
{
  drafts: any[];
  count: number;
  addDraft: (draft: any) => void;
  updateDraft: (key: string | number, changes: any) => void;
  removeDraft: (key: string | number) => void;
  clearDrafts: () => void;
  handleSync: () => void; // Manually trigger sync (if set 'manual' syncTrigger in provider)
}
```

### useDraft Hook

Use `useDraft({ draftId: '' })` to manage a single draft:
`draftId` is the key of the draft you want to manage. Setting `draftId` to `first` or `last` will return the first or last draft in the list, respectively.

```ts
{
  draft: any;
  update: (changes: any) => void;
  remove: () => void;
}
```

---

## 🧪 Sync Triggers

- `onChange`: Syncs immediately after adding/updating/removing a draft.
- `interval`: Syncs every `syncInterval` seconds.
- `connection`: Syncs automatically when the app goes online.
- `manual`: You can call the exposed `syncData` manually (exposing this is coming soon).

---

## 🌐 Online Detection

When using `syncTrigger="connection"`, the provider uses the `useOnline` hook to detect if the app is online.

> Web: uses `navigator.onLine` and `online/offline` events
>
> React Native: uses `@react-native-community/netinfo`

---

## 📁 File Structure

```bash
src/
├── Provider.tsx         # The main context provider
├── Context.ts           # React Context object
├── useOnline.ts         # Hook for online status
├── useDrafts.ts         # Hook for drafts management
├── types.ts             # Type declarations
```

---

## 📝 License

MIT © [BossBele](https://github.com/BossBele)

---

## 💬 Contributing / Issues

PRs and issues are welcome! Open an issue on the [GitHub repo](https://github.com/BossBele/react-drafts/issues).

---

## 🛠️ TODOs

- [x] Expose manual sync method
- [ ] Add persistent storage with localStorage/AsyncStorage
- [ ] Bundle as ESM + CJS for wider compatibility
