> ## Documentation Index
> Fetch the complete documentation index at: https://stratasync.blode.md/llms.txt
> Use this file to discover all available pages before exploring further.

# Collaborative editing hooks

Integrate Yjs CRDT documents with React components. Requires the `yjs` peer dependency and a configured Yjs transport.

## Prerequisites

1. `yjs` peer dependency installed
2. Yjs transport configured via `yjsTransport`
3. Sync client accessible via `SyncProvider`

```ts
import { createSyncClient } from "@stratasync/client";

const client = createSyncClient({
  // ... storage, transport, reactivity
  yjsTransport: createYjsTransport({
    wsEndpoint: "wss://api.example.com/yjs",
  }),
});
```

If `client.yjs` is `undefined` (no Yjs transport configured), `useYjsDocument` sets an error state and `useYjsPresence` operations become no-ops.

## useYjsDocument

Manages a Yjs document lifecycle: connection, content tracking, and session awareness.

```tsx
import { useYjsDocument } from "@stratasync/react";

function DescriptionEditor({ taskId }: { taskId: string }) {
  const {
    doc,
    isConnected,
    isSessionActive,
    participants,
    content,
    connect,
    disconnect,
    focus,
    blur,
    connectionState,
    error,
  } = useYjsDocument(
    { entityType: "Task", entityId: taskId, fieldName: "description" },
    { autoConnect: true }
  );

  if (!doc) {
    return <div>Loading editor...</div>;
  }

  return (
    <div>
      {isSessionActive && (
        <div>
          Collaborating with: {participants.map((p) => p.userId).join(", ")}
        </div>
      )}
      <RichTextEditor doc={doc} onFocus={focus} onBlur={blur} />
      {error && <div>{error.message}</div>}
    </div>
  );
}
```

**Signature:** `useYjsDocument(docKey: DocumentKey, options?: UseYjsDocumentOptions): UseYjsDocumentResult`

### DocumentKey

Identifies a collaborative field on a model.

```ts
interface DocumentKey {
  entityType: string; // Model name, such as "Task"
  entityId: string; // Model ID, such as "task-123"
  fieldName: string; // Field name, such as "description"
}
```

### UseYjsDocumentOptions

| Option           | Type      | Default | Description                                      |
| ---------------- | --------- | ------- | ------------------------------------------------ |
| `initialContent` | `string`  | -       | Initial content if the document is empty.        |
| `autoConnect`    | `boolean` | `false` | Automatically connect when the component mounts. |
| `editing`        | `boolean` | -       | Start in editing mode (signals presence).        |
| `skip`           | `boolean` | `false` | Skip connecting entirely.                        |

### UseYjsDocumentResult

| Field             | Type                   | Description                                                      |
| ----------------- | ---------------------- | ---------------------------------------------------------------- |
| `doc`             | `YDoc \| null`         | The Yjs document instance. `null` before connection.             |
| `connectionState` | `YjsConnectionState`   | `"disconnected"`, `"connecting"`, `"syncing"`, or `"connected"`. |
| `isConnected`     | `boolean`              | `true` when `connectionState === "connected"`.                   |
| `isSessionActive` | `boolean`              | `true` when other participants are present.                      |
| `participants`    | `SessionParticipant[]` | List of current session participants.                            |
| `content`         | `string`               | Current text content of the document.                            |
| `connect`         | `() => void`           | Connect to the document.                                         |
| `disconnect`      | `() => void`           | Disconnect from the document.                                    |
| `focus`           | `() => void`           | Signal that you started editing.                                 |
| `blur`            | `() => void`           | Signal that you stopped editing.                                 |
| `error`           | `Error \| null`        | Any error that occurred.                                         |

### SessionParticipant

```ts
interface SessionParticipant {
  userId: string;
  isEditing: boolean;
}
```

### YjsConnectionState

```ts
type YjsConnectionState =
  | "disconnected"
  | "connecting"
  | "syncing"
  | "connected";
```

## useYjsPresence

Presence signaling with focus tracking and visibility detection.

```tsx
import { useYjsPresence } from "@stratasync/react";

function TaskEditor({ taskId }: { taskId: string }) {
  const { getRef, isViewing, isEditing, focus, blur } = useYjsPresence(
    { entityType: "Task", entityId: taskId, fieldName: "description" },
    { trackFocus: true, trackVisibility: true }
  );

  return (
    <div ref={getRef()}>
      <p>Viewing: {isViewing ? "Yes" : "No"}</p>
      <p>Editing: {isEditing ? "Yes" : "No"}</p>
      <textarea onFocus={focus} onBlur={blur} />
    </div>
  );
}
```

**Signature:** `useYjsPresence(docKey: DocumentKey, options?: UseYjsPresenceOptions): UseYjsPresenceResult`

### UseYjsPresenceOptions

| Option            | Type      | Default | Description                                              |
| ----------------- | --------- | ------- | -------------------------------------------------------- |
| `trackFocus`      | `boolean` | `false` | Track focus via `focusin`/`focusout` on the ref element. |
| `trackVisibility` | `boolean` | `false` | Track visibility via `IntersectionObserver`.             |
| `skip`            | `boolean` | `false` | Skip presence tracking.                                  |

### UseYjsPresenceResult

| Field          | Type                                                        | Description                          |
| -------------- | ----------------------------------------------------------- | ------------------------------------ |
| `startViewing` | `() => void`                                                | Start viewing the document.          |
| `stopViewing`  | `() => void`                                                | Stop viewing the document.           |
| `focus`        | `() => void`                                                | Signal editing focus.                |
| `blur`         | `() => void`                                                | Signal editing blur.                 |
| `isViewing`    | `boolean`                                                   | Whether you're viewing the document. |
| `isEditing`    | `boolean`                                                   | Whether you're editing the document. |
| `getRef`       | `<T extends HTMLElement>() => (element: T \| null) => void` | Ref callback for auto-tracking.      |

### Auto-tracking with getRef

Attaches event listeners and an `IntersectionObserver` to the element.

```tsx
function AutoTrackedEditor({ taskId }: { taskId: string }) {
  const { getRef } = useYjsPresence(
    { entityType: "Task", entityId: taskId, fieldName: "description" },
    { trackFocus: true, trackVisibility: true }
  );

  return (
    <div ref={getRef()}>
      <textarea />
    </div>
  );
}
```

`trackVisibility`: viewing starts when visible (intersection ratio > 0.1) and stops when leaving the viewport. `trackFocus`: editing starts on `focusin` and stops on `focusout`.