ai-design-system 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,29 +1,40 @@
1
1
  /**
2
- * AIDocEditor Stories
2
+ * AIDocEditor Feature Stories
3
3
  *
4
- * Demonstrates the AIDocEditor feature with various scenarios
4
+ * Required story patterns for AIDocEditor feature:
5
+ * - Default: Static single-document mode (backward compatible)
6
+ * - Empty: Empty state for multi-tab mode
7
+ * - WithStateManagement: Interactive multi-tab with mock hook
5
8
  */
6
9
 
7
10
  import type { Meta, StoryObj } from '@storybook/react'
8
11
  import { AIDocEditor } from './AIDocEditor'
9
12
  import { useAIDocEditorMock } from './useAIDocEditor.mock'
10
- import { sampleContent, currentUser, sampleAnnotations } from './AIDocEditor.mocks'
11
-
12
- const meta: Meta<typeof AIDocEditor> = {
13
+ import {
14
+ sampleContent,
15
+ currentUser,
16
+ sampleAnnotations,
17
+ sampleMultiTabDocuments,
18
+ } from './AIDocEditor.mocks'
19
+
20
+ const meta = {
13
21
  title: 'Features/AIDocEditor',
14
22
  component: AIDocEditor,
15
23
  parameters: {
16
24
  layout: 'fullscreen',
17
25
  },
18
26
  tags: ['autodocs'],
19
- }
27
+ } satisfies Meta<typeof AIDocEditor>
20
28
 
21
29
  export default meta
22
- type Story = StoryObj<typeof AIDocEditor>
30
+ type Story = StoryObj<typeof meta>
23
31
 
24
32
  /**
25
- * Default story with static props
26
- * Shows the editor with existing annotations
33
+ * Default - Static single-document mode (REQUIRED)
34
+ *
35
+ * Shows the editor in the original single-document usage pattern with
36
+ * existing annotations. Demonstrates backward compatibility with existing
37
+ * consumers who have not yet migrated to multi-tab mode.
27
38
  */
28
39
  export const Default: Story = {
29
40
  args: {
@@ -37,104 +48,44 @@ export const Default: Story = {
37
48
  }
38
49
 
39
50
  /**
40
- * Story with empty document
51
+ * Empty - Multi-tab empty state (REQUIRED edge case)
52
+ *
53
+ * Shows the empty state when no documents are open in multi-tab mode.
54
+ * Demonstrates edge case behavior and placeholder messaging.
41
55
  */
42
- export const EmptyDocument: Story = {
56
+ export const Empty: Story = {
43
57
  args: {
44
- content: {
45
- type: 'doc',
46
- content: [
47
- {
48
- type: 'paragraph',
49
- content: [],
50
- },
51
- ],
52
- },
53
- annotations: [],
58
+ documents: [],
54
59
  currentUser,
55
60
  mode: 'review',
56
61
  },
57
62
  }
58
63
 
59
64
  /**
60
- * Story in readonly mode (no interactions)
61
- */
62
- export const ReadonlyMode: Story = {
63
- args: {
64
- content: sampleContent,
65
- annotations: sampleAnnotations,
66
- currentUser,
67
- mode: 'readonly',
68
- },
69
- }
70
-
71
- /**
72
- * Interactive story with state management using mock hook
73
- * Demonstrates adding comments and replies with simulated async operations
74
- * Uses markdown format for easy content creation
65
+ * WithStateManagement - Multi-tab interactive mode (REQUIRED)
66
+ *
67
+ * Demonstrates the new multi-tab capability with live state management.
68
+ * Users can switch tabs, close tabs, and manage annotations across
69
+ * multiple documents. Uses mock hook for realistic interaction simulation.
75
70
  */
76
71
  export const WithStateManagement: Story = {
77
72
  render: () => {
78
- const { annotations, addAnnotation, updateAnnotation, loading } = useAIDocEditorMock(sampleAnnotations)
79
-
80
- const markdownContent = `# AI Document Review Demo
81
-
82
- This document demonstrates the **AIDocEditor** feature with full state management.
83
-
84
- ## Interactive Features
85
-
86
- Try these interactions:
87
-
88
- - **Select text** to add a new comment
89
- - **Click highlighted text** to view existing annotations
90
- - **Reply to comments** in the comment thread
91
- - All changes are saved with simulated async operations
92
-
93
- ## Sample Content for Review
94
-
95
- The AI has analyzed this document and provided several suggestions. You can review each suggestion and add your own comments.
96
-
97
- ### Code Example
98
-
99
- \`\`\`javascript
100
- function processData(items) {
101
- return items.map(item => ({
102
- id: item.id,
103
- name: item.name,
104
- processed: true
105
- }));
106
- }
107
- \`\`\`
108
-
109
- ### Key Points
110
-
111
- 1. **Performance**: The current implementation is efficient
112
- 2. **Maintainability**: Code is well-structured and documented
113
- 3. **Testing**: Unit tests cover all critical paths
114
-
115
- > **Note:** This is a live demo with state management. Try selecting text and adding comments!
116
-
117
- ---
118
-
119
- **Status:** Ready for review | **Last updated:** ${new Date().toLocaleDateString()}`
73
+ const mockState = useAIDocEditorMock({
74
+ multiDoc: true,
75
+ initialDocuments: sampleMultiTabDocuments,
76
+ })
120
77
 
121
78
  return (
122
- <div className="h-screen p-8">
123
- <AIDocEditor
124
- content={markdownContent}
125
- format="markdown"
126
- annotations={annotations}
127
- currentUser={currentUser}
128
- mode="review"
129
- onAnnotationAdd={addAnnotation}
130
- onAnnotationUpdate={updateAnnotation}
131
- />
132
- {loading && (
133
- <div className="fixed bottom-4 right-4 bg-primary text-primary-foreground px-4 py-2 rounded-md">
134
- Saving...
135
- </div>
136
- )}
137
- </div>
79
+ <AIDocEditor
80
+ documents={mockState.documents}
81
+ activeDocumentId={mockState.activeDocumentId}
82
+ currentUser={currentUser}
83
+ mode="review"
84
+ onTabSelect={mockState.switchDocument}
85
+ onTabClose={mockState.closeDocument}
86
+ onAnnotationAdd={mockState.addAnnotation}
87
+ onAnnotationUpdate={mockState.updateAnnotation}
88
+ />
138
89
  )
139
90
  },
140
91
  }
@@ -2,9 +2,9 @@
2
2
  * AIDocEditor Feature Component
3
3
  *
4
4
  * Complete document editor with inline comment annotations.
5
- * Feature layer: uses DocumentEditorWithComments section with data management.
5
+ * Supports both single-document and multi-tab modes.
6
6
  *
7
- * @example
7
+ * Single-document mode (backward compatible):
8
8
  * ```tsx
9
9
  * <AIDocEditor
10
10
  * content={document}
@@ -14,18 +14,36 @@
14
14
  * onAnnotationAdd={(annotation) => saveAnnotation(annotation)}
15
15
  * />
16
16
  * ```
17
+ *
18
+ * Multi-tab mode:
19
+ * ```tsx
20
+ * <AIDocEditor
21
+ * documents={[
22
+ * { file: { id: 'doc-1', name: 'File.md', isDirty: false, lastModified: now },
23
+ * content: '...',
24
+ * annotations: [] }
25
+ * ]}
26
+ * activeDocumentId="doc-1"
27
+ * currentUser={user}
28
+ * mode="review"
29
+ * onTabSelect={(id) => switchDocument(id)}
30
+ * onTabClose={(id) => closeDocument(id)}
31
+ * />
32
+ * ```
17
33
  */
18
34
 
19
- import React, { useCallback } from 'react'
35
+ import React, { useCallback, useMemo } from 'react'
20
36
  import { DocumentEditorWithComments } from '@/components/blocks/DocumentEditorWithComments'
37
+ import { DocumentTabBar } from '@/components/composites/DocumentTabBar'
21
38
  import { cn } from '@/lib/utils'
22
39
  import type { JSONContent } from '@tiptap/core'
23
40
  import type { Annotation, User } from '@/types/ai-editor/annotations'
41
+ import type { DocumentWithAnnotations } from '@/types/ai-editor'
24
42
 
25
43
  /**
26
- * Props for AIDocEditor feature component
44
+ * Props for AIDocEditor feature component - Single document mode (backward compatible)
27
45
  */
28
- export interface AIDocEditorProps {
46
+ export interface AIDocEditorSingleProps {
29
47
  /**
30
48
  * Document content - can be either:
31
49
  * - JSONContent: Tiptap's JSON format (default)
@@ -44,6 +62,42 @@ export interface AIDocEditorProps {
44
62
  annotations: Annotation[]
45
63
  /** ID of currently selected annotation */
46
64
  selectedAnnotationId?: string
65
+ /** Multi-document array (not provided in single-doc mode) */
66
+ documents?: never
67
+ /** Active document ID (not provided in single-doc mode) */
68
+ activeDocumentId?: never
69
+ /** Tab selection callback (not provided in single-doc mode) */
70
+ onTabSelect?: never
71
+ /** Tab close callback (not provided in single-doc mode) */
72
+ onTabClose?: never
73
+ }
74
+
75
+ /**
76
+ * Props for AIDocEditor feature component - Multi-tab mode
77
+ */
78
+ export interface AIDocEditorMultiTabProps {
79
+ /** Array of open documents with their content and annotations */
80
+ documents: DocumentWithAnnotations[]
81
+ /** ID of currently active document */
82
+ activeDocumentId?: string
83
+ /** Content prop (not provided in multi-tab mode) */
84
+ content?: never
85
+ /** Format prop (not provided in multi-tab mode) */
86
+ format?: never
87
+ /** Annotations prop (not provided in multi-tab mode) */
88
+ annotations?: never
89
+ /** Selected annotation ID (not provided in multi-tab mode) */
90
+ selectedAnnotationId?: never
91
+ /** Callback when tab is selected */
92
+ onTabSelect?: (documentId: string) => void
93
+ /** Callback when tab close button is clicked */
94
+ onTabClose?: (documentId: string) => void
95
+ }
96
+
97
+ /**
98
+ * Props for AIDocEditor feature component
99
+ */
100
+ export type AIDocEditorProps = (AIDocEditorSingleProps | AIDocEditorMultiTabProps) & {
47
101
  /** Current user information */
48
102
  currentUser: User
49
103
  /** Editor mode: 'review' allows commenting, 'readonly' disables interactions */
@@ -66,30 +120,56 @@ export interface AIDocEditorProps {
66
120
  className?: string
67
121
  }
68
122
 
123
+ /**
124
+ * Determine if props are multi-tab mode
125
+ */
126
+ function isMultiTabMode(props: AIDocEditorProps): props is AIDocEditorMultiTabProps & {
127
+ currentUser: User
128
+ mode: 'review' | 'readonly'
129
+ } {
130
+ return 'documents' in props && props.documents !== undefined
131
+ }
132
+
69
133
  /**
70
134
  * AIDocEditor - Document editor with inline comment annotations
71
135
  *
72
136
  * This feature component provides a complete document review experience with:
137
+ * - Single-document or multi-tab display modes
73
138
  * - Read-only document display with annotation highlights
74
139
  * - Inline comment box for viewing and adding comments
75
140
  * - Support for comments, suggestions, and block additions
76
141
  * - Controlled component pattern (all state managed by parent)
142
+ * - Backward-compatible with single-document consumers
77
143
  *
78
144
  * Note: The refinement panel (right sidebar with Accept All/Reject All) is a
79
145
  * separate component in the parent application, not part of this feature.
80
146
  */
81
147
  export const AIDocEditor = React.memo<AIDocEditorProps>(
82
- ({
83
- content,
84
- format = 'json',
85
- annotations,
86
- selectedAnnotationId,
87
- currentUser,
88
- mode,
89
- onAnnotationAdd,
90
- onAnnotationUpdate,
91
- className,
92
- }) => {
148
+ (props) => {
149
+ const {
150
+ currentUser,
151
+ mode,
152
+ onAnnotationAdd,
153
+ onAnnotationUpdate,
154
+ onAnnotationDelete: _onAnnotationDelete, // Callback for consumers; passed through on demand
155
+ className,
156
+ } = props
157
+
158
+ const isMultiTab = isMultiTabMode(props)
159
+
160
+ /**
161
+ * Get current document for rendering
162
+ */
163
+ const currentDocument = useMemo(() => {
164
+ if (isMultiTab && props.documents) {
165
+ return (
166
+ props.documents.find((doc) => doc.file.id === props.activeDocumentId) ||
167
+ props.documents[0]
168
+ )
169
+ }
170
+ return null
171
+ }, [isMultiTab, props])
172
+
93
173
  /**
94
174
  * Handle annotation add - emit event to parent
95
175
  */
@@ -110,19 +190,67 @@ export const AIDocEditor = React.memo<AIDocEditorProps>(
110
190
  [onAnnotationUpdate]
111
191
  )
112
192
 
193
+ /**
194
+ * Single-document mode
195
+ */
196
+ if (!isMultiTab) {
197
+ return (
198
+ <DocumentEditorWithComments
199
+ content={props.content}
200
+ format={props.format}
201
+ annotations={props.annotations}
202
+ selectedAnnotationId={props.selectedAnnotationId}
203
+ currentUserId={currentUser.id}
204
+ currentUserName={currentUser.name}
205
+ readOnly={mode === 'readonly'}
206
+ onAnnotationAdd={handleAnnotationAdd}
207
+ onAnnotationUpdate={handleAnnotationUpdate}
208
+ className={cn('ai-doc-editor p-6', className)}
209
+ />
210
+ )
211
+ }
212
+
213
+ /**
214
+ * Multi-tab mode
215
+ */
216
+ if (!currentDocument) {
217
+ return (
218
+ <div className={cn('ai-doc-editor flex flex-col h-full', className)}>
219
+ <DocumentTabBar
220
+ tabs={props.documents?.map((doc) => doc.file) || []}
221
+ activeTabId={props.activeDocumentId}
222
+ onTabSelect={props.onTabSelect}
223
+ onTabClose={props.onTabClose}
224
+ />
225
+ <div className="flex-1 flex items-center justify-center p-6 text-muted-foreground">
226
+ No documents open
227
+ </div>
228
+ </div>
229
+ )
230
+ }
231
+
113
232
  return (
114
- <DocumentEditorWithComments
115
- content={content}
116
- format={format}
117
- annotations={annotations}
118
- selectedAnnotationId={selectedAnnotationId}
119
- currentUserId={currentUser.id}
120
- currentUserName={currentUser.name}
121
- readOnly={mode === 'readonly'}
122
- onAnnotationAdd={handleAnnotationAdd}
123
- onAnnotationUpdate={handleAnnotationUpdate}
124
- className={cn('ai-doc-editor p-6', className)}
125
- />
233
+ <div className={cn('ai-doc-editor flex flex-col h-full', className)}>
234
+ <DocumentTabBar
235
+ tabs={props.documents?.map((doc) => doc.file) || []}
236
+ activeTabId={props.activeDocumentId}
237
+ onTabSelect={props.onTabSelect}
238
+ onTabClose={props.onTabClose}
239
+ />
240
+ <div className="flex-1 overflow-auto">
241
+ <DocumentEditorWithComments
242
+ content={currentDocument.content}
243
+ format={currentDocument.file.format}
244
+ annotations={currentDocument.annotations}
245
+ currentUserId={currentUser.id}
246
+ currentUserName={currentUser.name}
247
+ readOnly={mode === 'readonly'}
248
+ onAnnotationAdd={handleAnnotationAdd}
249
+ onAnnotationUpdate={handleAnnotationUpdate}
250
+ className="p-6"
251
+ />
252
+ </div>
253
+ </div>
126
254
  )
127
255
  }
128
256
  )
@@ -2,16 +2,21 @@
2
2
 
3
3
  Document editor with inline comment annotations for AI-powered document review workflows.
4
4
 
5
+ Supports both single-document and multi-tab modes for flexible document management.
6
+
5
7
  ## Architecture
6
8
 
7
- - **Component Layer**: Pure UI component (`AIDocEditor.tsx`)
8
- - **Hook Contract**: Interface definition (`useAIDocEditor.d.ts`)
9
+ - **Component Layer**: Pure UI component (`AIDocEditor.tsx`) with mode detection
10
+ - **Hook Contract**: Interface definitions (`useAIDocEditor.d.ts`) for single and multi-tab modes
11
+ - **Composite Layer**: `DocumentTabBar` composite for tab rendering
9
12
  - **Mock Implementation**: Storybook testing (`useAIDocEditor.mock.ts`)
10
13
  - **Application Layer**: Real implementation (in your app)
11
14
 
12
15
  ## Usage
13
16
 
14
- ### In Your Application (implement hook with real API)
17
+ ### Single-Document Mode (Backward Compatible)
18
+
19
+ #### In Your Application
15
20
 
16
21
  ```tsx
17
22
  // app/hooks/useAIDocEditor.ts
@@ -53,14 +58,89 @@ export function DocEditorContainer({ documentId, content, currentUser }) {
53
58
  }
54
59
  ```
55
60
 
56
- ### In Storybook (use mock hook)
61
+ ### Multi-Tab Mode
62
+
63
+ #### In Your Application
57
64
 
58
65
  ```tsx
66
+ // app/hooks/useMultiTabDocEditor.ts
67
+ import type { UseAIMultiTabDocEditorReturn, DocumentWithAnnotations } from 'ui-lib/components/features/AIDocEditor';
68
+
69
+ export function useAIMultiTabDocEditor(): UseAIMultiTabDocEditorReturn {
70
+ const [documents, setDocuments] = useState<DocumentWithAnnotations[]>([]);
71
+ const [activeDocumentId, setActiveDocumentId] = useState<string>();
72
+ const [loading, setLoading] = useState(false);
73
+
74
+ const switchDocument = (documentId: string) => {
75
+ setActiveDocumentId(documentId);
76
+ };
77
+
78
+ const closeDocument = (documentId: string) => {
79
+ setDocuments(prev => {
80
+ const filtered = prev.filter(doc => doc.file.id !== documentId);
81
+ if (activeDocumentId === documentId && filtered.length > 0) {
82
+ setActiveDocumentId(filtered[0].file.id);
83
+ }
84
+ return filtered;
85
+ });
86
+ };
87
+
88
+ const addAnnotation = async (documentId: string, annotation: Annotation) => {
89
+ setLoading(true);
90
+ await api.createAnnotation(documentId, annotation);
91
+ setDocuments(prev =>
92
+ prev.map(doc =>
93
+ doc.file.id === documentId
94
+ ? { ...doc, annotations: [...doc.annotations, annotation] }
95
+ : doc
96
+ )
97
+ );
98
+ setLoading(false);
99
+ };
100
+
101
+ // ... other methods
102
+
103
+ return {
104
+ documents,
105
+ activeDocumentId,
106
+ switchDocument,
107
+ closeDocument,
108
+ addAnnotation,
109
+ // ... other methods
110
+ };
111
+ }
112
+ ```
113
+
114
+ ```tsx
115
+ // app/components/MultiDocEditorContainer.tsx
59
116
  import { AIDocEditor } from 'ui-lib/components/features/AIDocEditor';
60
- import { useMockAIDocEditor } from 'ui-lib/components/features/AIDocEditor';
117
+ import { useAIMultiTabDocEditor } from '../hooks/useMultiTabDocEditor';
118
+
119
+ export function MultiDocEditorContainer({ currentUser }) {
120
+ const { documents, activeDocumentId, switchDocument, closeDocument } = useAIMultiTabDocEditor();
121
+
122
+ return (
123
+ <AIDocEditor
124
+ documents={documents}
125
+ activeDocumentId={activeDocumentId}
126
+ currentUser={currentUser}
127
+ mode="review"
128
+ onTabSelect={switchDocument}
129
+ onTabClose={closeDocument}
130
+ />
131
+ );
132
+ }
133
+ ```
134
+
135
+ ### In Storybook (use mock hook)
136
+
137
+ #### Single-Document Mode
138
+
139
+ ```tsx
140
+ import { AIDocEditor, useAIDocEditorMock, sampleAnnotations } from 'ui-lib/components/features/AIDocEditor';
61
141
 
62
142
  export const Default = () => {
63
- const { annotations, addAnnotation, updateAnnotation } = useMockAIDocEditor();
143
+ const { annotations, addAnnotation, updateAnnotation } = useAIDocEditorMock(sampleAnnotations);
64
144
 
65
145
  return (
66
146
  <AIDocEditor
@@ -75,9 +155,36 @@ export const Default = () => {
75
155
  };
76
156
  ```
77
157
 
78
- ## Hook Contract
158
+ #### Multi-Tab Mode
159
+
160
+ ```tsx
161
+ import {
162
+ AIDocEditor,
163
+ useAIMultiTabDocEditorMock,
164
+ sampleMultiTabDocuments
165
+ } from 'ui-lib/components/features/AIDocEditor';
166
+
167
+ export const MultiTab = () => {
168
+ const [documents, activeDocumentId, , , switchDocument, closeDocument] = Object.values(
169
+ useAIMultiTabDocEditorMock(sampleMultiTabDocuments)
170
+ );
171
+
172
+ return (
173
+ <AIDocEditor
174
+ documents={documents}
175
+ activeDocumentId={activeDocumentId}
176
+ currentUser={mockUser}
177
+ mode="review"
178
+ onTabSelect={switchDocument}
179
+ onTabClose={closeDocument}
180
+ />
181
+ );
182
+ };
183
+ ```
184
+
185
+ ## Hook Contracts
79
186
 
80
- ### `UseAIDocEditorReturn`
187
+ ### `UseAIDocEditorReturn` (Single-Document, Deprecated)
81
188
 
82
189
  ```typescript
83
190
  interface UseAIDocEditorReturn {
@@ -89,38 +196,83 @@ interface UseAIDocEditorReturn {
89
196
  }
90
197
  ```
91
198
 
199
+ ### `UseAIMultiTabDocEditorReturn` (Multi-Tab, Recommended)
200
+
201
+ ```typescript
202
+ interface UseAIMultiTabDocEditorReturn {
203
+ documents: DocumentWithAnnotations[];
204
+ activeDocumentId?: string;
205
+ addDocument: (file: DocumentFile, content: string | JSONContent) => void;
206
+ closeDocument: (documentId: string) => void;
207
+ switchDocument: (documentId: string) => void;
208
+ addAnnotation: (documentId: string, annotation: Annotation) => Promise<void> | void;
209
+ updateAnnotation: (documentId: string, annotation: Annotation) => Promise<void> | void;
210
+ deleteAnnotation: (documentId: string, annotationId: string) => Promise<void> | void;
211
+ setDocumentDirty: (documentId: string, isDirty: boolean) => void;
212
+ loading: boolean;
213
+ }
214
+ ```
215
+
92
216
  ## Component Props
93
217
 
94
- ### `AIDocEditorProps`
218
+ ### `AIDocEditorSingleProps` (Single-Document Mode)
95
219
 
96
220
  ```typescript
97
- interface AIDocEditorProps {
221
+ interface AIDocEditorSingleProps {
98
222
  content: JSONContent | string;
99
223
  format?: 'json' | 'markdown';
100
224
  annotations: Annotation[];
101
225
  selectedAnnotationId?: string;
102
226
  currentUser: User;
103
227
  mode: 'review' | 'readonly';
104
- onContentUpdate?: (content: JSONContent) => void;
105
- onAnnotationClick?: (annotation: Annotation) => void;
106
- onAnnotationHover?: (annotation: Annotation | null) => void;
107
- onTextSelect?: (range: { from: number; to: number }, selectedText: string) => void;
108
- onAnnotationAdd?: (annotation: Annotation) => void;
109
- onAnnotationUpdate?: (annotation: Annotation) => void;
110
- onAnnotationDelete?: (annotationId: string) => void;
111
- className?: string;
228
+ // ... event callbacks (onAnnotationAdd, etc.)
112
229
  }
113
230
  ```
114
231
 
232
+ ### `AIDocEditorMultiTabProps` (Multi-Tab Mode)
233
+
234
+ ```typescript
235
+ interface AIDocEditorMultiTabProps {
236
+ documents: DocumentWithAnnotations[];
237
+ activeDocumentId?: string;
238
+ currentUser: User;
239
+ mode: 'review' | 'readonly';
240
+ onTabSelect?: (documentId: string) => void;
241
+ onTabClose?: (documentId: string) => void;
242
+ // ... other event callbacks
243
+ }
244
+ ```
245
+
246
+ ### Shared Props (Both Modes)
247
+
248
+ ```typescript
249
+ onContentUpdate?: (content: JSONContent) => void;
250
+ onAnnotationClick?: (annotation: Annotation) => void;
251
+ onAnnotationHover?: (annotation: Annotation | null) => void;
252
+ onTextSelect?: (range: { from: number; to: number }, selectedText: string) => void;
253
+ onAnnotationAdd?: (annotation: Annotation) => void;
254
+ onAnnotationUpdate?: (annotation: Annotation) => void;
255
+ onAnnotationDelete?: (annotationId: string) => void;
256
+ className?: string;
257
+ ```
258
+
115
259
  ## Files
116
260
 
117
- - `AIDocEditor.tsx` - Main component implementation
118
- - `AIDocEditor.stories.tsx` - Storybook stories and examples
119
- - `AIDocEditor.behaviors.stories.tsx` - Behavior-driven stories
120
- - `AIDocEditor.mocks.ts` - Shared mock data
121
- - `useAIDocEditor.d.ts` - Hook contract definition
122
- - `useAIDocEditor.mock.ts` - Mock implementation for testing
261
+ - `AIDocEditor.tsx` - Main component implementation with mode detection
262
+ - `AIDocEditor.stories.tsx` - Storybook stories for both single-doc and multi-tab modes
263
+ - `AIDocEditor.behaviors.stories.tsx` - Behavior-driven stories including tab interactions
264
+ - `AIDocEditor.mocks.ts` - Shared mock data for both modes
265
+ - `useAIDocEditor.d.ts` - Hook contract definitions
266
+ - `useAIDocEditor.mock.ts` - Mock implementations for both single and multi-tab modes
123
267
  - `index.ts` - Public exports
268
+ - `README.md` - This file
269
+
270
+ ## Composites Used
271
+
272
+ - `DocumentTabBar` - VS Code-style tab bar for multi-document display
273
+ - Displays open documents as tabs with dirty indicators
274
+ - Handles tab selection and closing
275
+ - Horizontally scrollable when many tabs are open
124
276
 
125
277
  ## References
126
278