@washi-ui/react 1.0.0

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.
@@ -0,0 +1,335 @@
1
+ import { WashiAdapter, WashiMode, MountOptions, PinPlacedEvent, Comment, NewComment, Washi } from '@washi-ui/core';
2
+ export { Comment, CommentClickedEvent, CommentDeletedEvent, CommentUpdatedEvent, ErrorEvent, ModeChangedEvent, MountOptions, NewComment, PinPlacedEvent, WashiAdapter, WashiEvent, WashiMode } from '@washi-ui/core';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import React$1, { ReactNode, IframeHTMLAttributes } from 'react';
5
+
6
+ /**
7
+ * Options for the useWashi hook
8
+ */
9
+ interface UseWashiOptions {
10
+ /** Required: The storage adapter for persisting comments */
11
+ adapter: WashiAdapter;
12
+ /** Optional: Initial mode ('view' or 'annotate'). Defaults to 'view' */
13
+ initialMode?: WashiMode;
14
+ /** Optional: Mount options for the Washi instance */
15
+ mountOptions?: MountOptions;
16
+ /** Optional: Callback when a pin is placed on the overlay in annotate mode */
17
+ onPinPlaced?: (event: PinPlacedEvent) => void;
18
+ /** Optional: Callback when a pin is clicked */
19
+ onCommentClick?: (comment: Comment) => void;
20
+ /** Optional: Callback when a comment is updated */
21
+ onCommentUpdate?: (data: {
22
+ id: string;
23
+ updates: Partial<Comment>;
24
+ }) => void;
25
+ /** Optional: Callback when a comment is deleted */
26
+ onCommentDelete?: (id: string) => void;
27
+ }
28
+ /**
29
+ * Return type of the useWashi hook
30
+ */
31
+ interface UseWashiReturn {
32
+ /** Ref to attach to the iframe element */
33
+ iframeRef: React.RefObject<HTMLIFrameElement | null>;
34
+ /** Current mode */
35
+ mode: WashiMode;
36
+ /** Function to change the mode */
37
+ setMode: (mode: WashiMode) => void;
38
+ /** Array of all comments */
39
+ comments: Comment[];
40
+ /** Add a new comment. Returns the completed Comment with generated id and createdAt. */
41
+ addComment: (input: NewComment) => Promise<Comment>;
42
+ /** Update an existing comment */
43
+ updateComment: (id: string, updates: Partial<Comment>) => Promise<void>;
44
+ /** Delete a comment */
45
+ deleteComment: (id: string) => Promise<void>;
46
+ /** Whether the Washi instance is mounted and ready */
47
+ isReady: boolean;
48
+ /** Any error that occurred during mounting or operations */
49
+ error: Error | null;
50
+ }
51
+ /**
52
+ * React hook for using Washi comment system.
53
+ *
54
+ * @param options - Configuration options
55
+ * @returns Object with iframe ref, state, and methods
56
+ *
57
+ * @example
58
+ * ```tsx
59
+ * function CommentableContent() {
60
+ * const {
61
+ * iframeRef,
62
+ * mode,
63
+ * setMode,
64
+ * comments,
65
+ * addComment,
66
+ * isReady
67
+ * } = useWashi({
68
+ * adapter: new MyAdapter(),
69
+ * onPinPlaced: ({ x, y }) => {
70
+ * // Show comment input dialog at position
71
+ * },
72
+ * onCommentClick: (comment) => {
73
+ * // Show comment details
74
+ * }
75
+ * });
76
+ *
77
+ * return (
78
+ * <div>
79
+ * <button onClick={() => setMode(mode === 'view' ? 'annotate' : 'view')}>
80
+ * Toggle Mode
81
+ * </button>
82
+ * <div style={{ position: 'relative' }}>
83
+ * <iframe ref={iframeRef} src="/content.html" />
84
+ * </div>
85
+ * </div>
86
+ * );
87
+ * }
88
+ * ```
89
+ */
90
+ declare function useWashi(options: UseWashiOptions): UseWashiReturn;
91
+
92
+ /**
93
+ * Context value provided by WashiProvider
94
+ */
95
+ interface WashiContextValue {
96
+ /** The Washi instance (null if not mounted) */
97
+ washi: Washi | null;
98
+ /** The registered iframe element (null if not mounted) */
99
+ iframeEl: HTMLIFrameElement | null;
100
+ /** Current mode */
101
+ mode: WashiMode;
102
+ /** Function to change the mode */
103
+ setMode: (mode: WashiMode) => void;
104
+ /** Array of all comments */
105
+ comments: Comment[];
106
+ /** Add a new comment. Returns the completed Comment with generated id and createdAt. */
107
+ addComment: (input: NewComment) => Promise<Comment>;
108
+ /** Update an existing comment */
109
+ updateComment: (id: string, updates: Partial<Comment>) => Promise<void>;
110
+ /** Delete a comment */
111
+ deleteComment: (id: string) => Promise<void>;
112
+ /** Refresh comments from adapter */
113
+ refreshComments: () => void;
114
+ /** Whether the Washi instance is mounted and ready */
115
+ isReady: boolean;
116
+ /** Any error that occurred */
117
+ error: Error | null;
118
+ /** Register an iframe element for mounting */
119
+ registerIframe: (iframe: HTMLIFrameElement | null) => void;
120
+ /** Subscribe to pin placement events (overlay clicked in annotate mode) */
121
+ onPinPlaced: (callback: (event: PinPlacedEvent) => void) => () => void;
122
+ /** Subscribe to comment click events */
123
+ onCommentClick: (callback: (comment: Comment) => void) => () => void;
124
+ /** Set the active pin for highlighting */
125
+ setActivePin: (commentId: string | null) => void;
126
+ /** Get the index of a comment (sorted by createdAt) */
127
+ getCommentIndex: (commentId: string) => number;
128
+ /** Currently selected/active comment (for custom dialog rendering) */
129
+ activeComment: Comment | null;
130
+ /** Set the active comment (for custom dialog rendering) */
131
+ setActiveComment: (comment: Comment | null) => void;
132
+ }
133
+ /**
134
+ * Props for WashiProvider
135
+ */
136
+ interface WashiProviderProps {
137
+ /** Required: The storage adapter for persisting comments */
138
+ adapter: WashiAdapter;
139
+ /** Optional: Initial mode ('view' or 'annotate'). Defaults to 'view' */
140
+ initialMode?: WashiMode;
141
+ /** Optional: Mount options for the Washi instance */
142
+ mountOptions?: MountOptions;
143
+ /** Child components */
144
+ children: ReactNode;
145
+ }
146
+ /**
147
+ * Provider component for Washi context.
148
+ * Use with WashiFrame and useWashiContext.
149
+ *
150
+ * @example
151
+ * ```tsx
152
+ * function App() {
153
+ * return (
154
+ * <WashiProvider adapter={new MyAdapter()}>
155
+ * <WashiFrame src="/content.html" />
156
+ * <CommentSidebar />
157
+ * </WashiProvider>
158
+ * );
159
+ * }
160
+ * ```
161
+ */
162
+ declare function WashiProvider({ adapter, initialMode, mountOptions, children, }: WashiProviderProps): react_jsx_runtime.JSX.Element;
163
+ /**
164
+ * Hook to access Washi context.
165
+ * Must be used within a WashiProvider.
166
+ *
167
+ * @throws Error if used outside of WashiProvider
168
+ *
169
+ * @example
170
+ * ```tsx
171
+ * function CommentSidebar() {
172
+ * const { comments, deleteComment } = useWashiContext();
173
+ *
174
+ * return (
175
+ * <ul>
176
+ * {comments.map(c => (
177
+ * <li key={c.id}>
178
+ * {c.text}
179
+ * <button onClick={() => deleteComment(c.id)}>Delete</button>
180
+ * </li>
181
+ * ))}
182
+ * </ul>
183
+ * );
184
+ * }
185
+ * ```
186
+ */
187
+ declare function useWashiContext(): WashiContextValue;
188
+
189
+ /**
190
+ * Props for WashiFrame component
191
+ */
192
+ interface WashiFrameProps extends Omit<IframeHTMLAttributes<HTMLIFrameElement>, 'ref'> {
193
+ /** URL to load in the iframe. Omit when using srcDoc to pass an HTML string. */
194
+ src?: string;
195
+ /** Optional: Additional CSS class name */
196
+ className?: string;
197
+ /** Optional: Inline styles */
198
+ style?: React$1.CSSProperties;
199
+ }
200
+ /**
201
+ * Iframe wrapper component that automatically registers with WashiProvider.
202
+ * Must be used within a WashiProvider.
203
+ *
204
+ * @example
205
+ * ```tsx
206
+ * <WashiProvider adapter={adapter}>
207
+ * <WashiFrame
208
+ * src="/content.html"
209
+ * style={{ width: '100%', height: '600px', border: 'none' }}
210
+ * />
211
+ * </WashiProvider>
212
+ * ```
213
+ */
214
+ declare function WashiFrame({ src, className, style, ...props }: WashiFrameProps): react_jsx_runtime.JSX.Element;
215
+
216
+ /**
217
+ * Props for CommentList component
218
+ */
219
+ interface CommentListProps {
220
+ /**
221
+ * Render function for each comment.
222
+ * Receives the comment and action handlers.
223
+ */
224
+ renderComment: (comment: Comment, actions: {
225
+ onResolve: () => Promise<void>;
226
+ onDelete: () => Promise<void>;
227
+ onUpdate: (updates: Partial<Comment>) => Promise<void>;
228
+ }) => ReactNode;
229
+ /**
230
+ * Optional: Filter function to show only certain comments
231
+ */
232
+ filter?: (comment: Comment) => boolean;
233
+ /**
234
+ * Optional: Sort function for comments
235
+ */
236
+ sort?: (a: Comment, b: Comment) => number;
237
+ /**
238
+ * Optional: Component to render when there are no comments
239
+ */
240
+ emptyState?: ReactNode;
241
+ /**
242
+ * Optional: CSS class name for the list container
243
+ */
244
+ className?: string;
245
+ /**
246
+ * Optional: Inline styles for the list container
247
+ */
248
+ style?: React$1.CSSProperties;
249
+ }
250
+ /**
251
+ * Helper component for rendering a list of comments.
252
+ * Must be used within a WashiProvider.
253
+ *
254
+ * @example
255
+ * ```tsx
256
+ * <CommentList
257
+ * renderComment={(comment, { onResolve, onDelete }) => (
258
+ * <div key={comment.id} className="comment-item">
259
+ * <p>{comment.text}</p>
260
+ * <div className="actions">
261
+ * <button onClick={onResolve}>
262
+ * {comment.resolved ? 'Unresolve' : 'Resolve'}
263
+ * </button>
264
+ * <button onClick={onDelete}>Delete</button>
265
+ * </div>
266
+ * </div>
267
+ * )}
268
+ * filter={(c) => !c.resolved}
269
+ * sort={(a, b) => b.createdAt - a.createdAt}
270
+ * emptyState={<p>No comments yet</p>}
271
+ * />
272
+ * ```
273
+ */
274
+ declare function CommentList({ renderComment, filter, sort, emptyState, className, style, }: CommentListProps): react_jsx_runtime.JSX.Element;
275
+
276
+ type WashiToolBubblePosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
277
+ interface WashiToolBubbleProps {
278
+ position?: WashiToolBubblePosition;
279
+ sidebarOpen?: boolean;
280
+ onSidebarToggle?: () => void;
281
+ accentColor?: string;
282
+ }
283
+ declare function WashiToolBubble({ position, sidebarOpen, onSidebarToggle, accentColor, }: WashiToolBubbleProps): react_jsx_runtime.JSX.Element;
284
+
285
+ interface WashiCommentsSidebarProps {
286
+ open: boolean;
287
+ onClose: () => void;
288
+ /** Which corner the tool bubble is anchored to. Panel slides in from that side and stops above the bubble. Default: 'bottom-right' */
289
+ position?: WashiToolBubblePosition;
290
+ accentColor?: string;
291
+ }
292
+ declare function WashiCommentsSidebar({ open, onClose, position, accentColor, }: WashiCommentsSidebarProps): react_jsx_runtime.JSX.Element | null;
293
+
294
+ interface WashiPinDialogProps {
295
+ accentColor?: string;
296
+ /** Optional callback fired after a comment is successfully created */
297
+ onComment?: (comment: Comment) => void;
298
+ }
299
+ /**
300
+ * Self-contained pin comment dialog.
301
+ *
302
+ * Subscribes to `pin:placed` events from the context and renders a small
303
+ * popover anchored to the clicked position. On submit it calls `addComment`
304
+ * and switches the mode back to 'view' automatically.
305
+ *
306
+ * Drop this anywhere inside a `<WashiProvider>` — no props required.
307
+ */
308
+ declare function WashiPinDialog({ accentColor, onComment }: WashiPinDialogProps): react_jsx_runtime.JSX.Element | null;
309
+
310
+ interface WashiUIProps {
311
+ /** Corner where the tool bubble (and sidebar) are anchored. Default: 'bottom-right' */
312
+ position?: WashiToolBubblePosition;
313
+ accentColor?: string;
314
+ /** Show a loading spinner while the iframe initialises. Default: true */
315
+ showLoader?: boolean;
316
+ }
317
+ /**
318
+ * All-in-one Washi UI layer.
319
+ *
320
+ * Renders the tool bubble, comments sidebar, pin dialog, and an optional
321
+ * loading overlay — all wired together. Drop it inside a `<WashiProvider>`.
322
+ *
323
+ * @example
324
+ * ```tsx
325
+ * <WashiProvider adapter={adapter}>
326
+ * <div style={{ position: 'fixed', inset: 0 }}>
327
+ * <WashiFrame src="/content.html" style={{ width: '100%', height: '100%', border: 'none' }} />
328
+ * </div>
329
+ * <WashiUI />
330
+ * </WashiProvider>
331
+ * ```
332
+ */
333
+ declare function WashiUI({ position, accentColor, showLoader, }: WashiUIProps): react_jsx_runtime.JSX.Element;
334
+
335
+ export { CommentList, type CommentListProps, type UseWashiOptions, type UseWashiReturn, WashiCommentsSidebar, type WashiCommentsSidebarProps, type WashiContextValue, WashiFrame, type WashiFrameProps, WashiPinDialog, type WashiPinDialogProps, WashiProvider, type WashiProviderProps, WashiToolBubble, type WashiToolBubblePosition, type WashiToolBubbleProps, WashiUI, type WashiUIProps, useWashi, useWashiContext };