@tangle-network/ui 11.5.0 → 11.7.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +70 -2
  3. package/dist/chat.d.ts +18 -8
  4. package/dist/chat.js +6 -5
  5. package/dist/{chunk-XROQW5J7.js → chunk-4ENFLPWQ.js} +1 -1
  6. package/dist/{chunk-XPYPZMYT.js → chunk-6RIX7M27.js} +1 -1
  7. package/dist/{chunk-R5GVQDL3.js → chunk-CVX53NCC.js} +7 -5
  8. package/dist/{chunk-ULDNFLIM.js → chunk-EIUE5GV2.js} +10 -14
  9. package/dist/chunk-L57WRIND.js +59 -0
  10. package/dist/chunk-LFVF2HFB.js +19 -0
  11. package/dist/{chunk-7O22XQ4D.js → chunk-PLWRAS5Z.js} +1 -1
  12. package/dist/{chunk-NZLLDHEG.js → chunk-QGTIBEPX.js} +608 -420
  13. package/dist/{chunk-AZWDI2JG.js → chunk-UYTRNR7Z.js} +1 -1
  14. package/dist/{chunk-RKC3GXHE.js → chunk-VDCZHOOO.js} +99 -104
  15. package/dist/{chunk-J2G7KCYH.js → chunk-XT4JMYVB.js} +109 -67
  16. package/dist/{document-editor-pane-MX3FIZSE.js → document-editor-pane-A3JURPW5.js} +1 -1
  17. package/dist/{document-editor-pane-C3cYEDWZ.d.ts → document-editor-pane-IAEQn_Dl.d.ts} +8 -4
  18. package/dist/editor.d.ts +5 -4
  19. package/dist/editor.js +1 -1
  20. package/dist/files.d.ts +1 -1
  21. package/dist/files.js +1 -1
  22. package/dist/hooks.js +6 -5
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +16 -11
  25. package/dist/primitives.d.ts +15 -1
  26. package/dist/primitives.js +5 -1
  27. package/dist/run.d.ts +22 -17
  28. package/dist/run.js +8 -6
  29. package/dist/sdk-hooks.js +6 -5
  30. package/dist/utils.d.ts +6 -0
  31. package/dist/utils.js +1 -1
  32. package/package.json +1 -1
  33. package/src/chat/agent-timeline.stories.tsx +163 -10
  34. package/src/chat/agent-timeline.test.tsx +114 -7
  35. package/src/chat/agent-timeline.tsx +120 -158
  36. package/src/chat/chat-container.test.tsx +59 -0
  37. package/src/chat/user-message.test.tsx +33 -0
  38. package/src/chat/user-message.tsx +13 -8
  39. package/src/editor/document-editor-pane.test.tsx +58 -0
  40. package/src/editor/editor-lazy.test.tsx +102 -0
  41. package/src/editor/editor-lazy.ts +40 -0
  42. package/src/editor/editor-loading.tsx +25 -0
  43. package/src/editor/editor-peers.test.ts +250 -0
  44. package/src/editor/editor-peers.ts +272 -0
  45. package/src/editor/editor-provider.test.tsx +226 -0
  46. package/src/editor/editor-provider.tsx +301 -265
  47. package/src/editor/editor-toolbar.tsx +1 -1
  48. package/src/editor/markdown-document-editor.test.tsx +121 -0
  49. package/src/editor/markdown-document-editor.tsx +114 -82
  50. package/src/editor/tiptap-editor.test.tsx +228 -0
  51. package/src/editor/tiptap-editor.tsx +162 -130
  52. package/src/primitives/index.ts +3 -0
  53. package/src/primitives/text-shimmer.test.tsx +34 -0
  54. package/src/primitives/text-shimmer.tsx +82 -0
  55. package/src/run/inline-thinking-item.stories.tsx +2 -2
  56. package/src/run/inline-thinking-item.tsx +2 -2
  57. package/src/run/inline-tool-item.test.tsx +76 -0
  58. package/src/run/inline-tool-item.tsx +9 -7
  59. package/src/run/run-group.tsx +4 -3
  60. package/src/run/run-row-shell.test.tsx +74 -4
  61. package/src/run/run-row-shell.tsx +81 -53
  62. package/src/run/tool-call-step.tsx +9 -7
  63. package/src/utils/tool-display.test.ts +53 -0
  64. package/src/utils/tool-display.ts +16 -15
  65. package/dist/chunk-LQS34IGP.js +0 -0
  66. /package/dist/{chunk-EJ5NBW7V.js → chunk-LDLOJKPC.js} +0 -0
@@ -1,9 +1,11 @@
1
1
  "use client";
2
2
 
3
- import { HocuspocusProvider } from "@hocuspocus/provider";
3
+ import type { HocuspocusProvider } from "@hocuspocus/provider";
4
4
  import {
5
+ type ComponentType,
5
6
  createContext,
6
7
  type ReactNode,
8
+ Suspense,
7
9
  useCallback,
8
10
  useContext,
9
11
  useEffect,
@@ -11,7 +13,9 @@ import {
11
13
  useRef,
12
14
  useState,
13
15
  } from "react";
14
- import * as Y from "yjs";
16
+ import type * as Y from "yjs";
17
+ import { retryableLazyEditor } from "./editor-lazy";
18
+ import { type EditorProviderPeers, loadEditorProviderPeers } from "./editor-peers";
15
19
 
16
20
  /**
17
21
  * Connection state for the Hocuspocus provider.
@@ -54,6 +58,9 @@ export interface EditorContextValue {
54
58
  disconnect: () => void;
55
59
  }
56
60
 
61
+ // Module scope, and never inside the factory below: `useEditorContext` and
62
+ // every hook in `use-editor` read THIS context, so a per-build context would
63
+ // leave them with no provider.
57
64
  const EditorContext = createContext<EditorContextValue | null>(null);
58
65
 
59
66
  /**
@@ -122,295 +129,324 @@ function generateUserColor(): string {
122
129
  }
123
130
 
124
131
  /**
125
- * EditorProvider wraps children with Hocuspocus collaboration context.
126
- * Manages WebSocket connection, Y.Doc, and awareness state.
132
+ * Builds the collaboration provider against loaded yjs and Hocuspocus
133
+ * namespaces. The peers arrive as an argument so that this module reaches
134
+ * them through type-only imports, which a bundler erases.
127
135
  */
128
- export function EditorProvider({
129
- websocketUrl,
130
- documentName,
131
- token,
132
- tokenExpiresAt,
133
- user,
134
- autoConnect = true,
135
- autoReconnect = true,
136
- maxReconnectAttempts = 5,
137
- onConnectionChange,
138
- onSync,
139
- onAuthError,
140
- onRefreshToken,
141
- children,
142
- }: EditorProviderProps) {
143
- const [connectionState, setConnectionState] =
144
- useState<ConnectionState>("disconnected");
145
- const [collaborators, setCollaborators] = useState<Collaborator[]>([]);
146
- const [isSynced, setIsSynced] = useState(false);
147
-
148
- // Use refs to avoid recreating provider on every render
149
- const docRef = useRef<Y.Doc | null>(null);
150
- const providerRef = useRef<HocuspocusProvider | null>(null);
151
- const reconnectAttemptsRef = useRef(0);
152
- const tokenRef = useRef(token);
153
- const tokenExpiryRef = useRef<number | undefined>(tokenExpiresAt);
154
- const refreshPromiseRef = useRef<Promise<string | null> | null>(null);
155
- const refreshTimerRef = useRef<number | null>(null);
156
-
157
- tokenRef.current = token;
158
- tokenExpiryRef.current = tokenExpiresAt;
159
-
160
- // Initialize Y.Doc once
161
- if (!docRef.current) {
162
- docRef.current = new Y.Doc();
163
- }
164
- const doc = docRef.current;
165
-
166
- // User color (generate once per session)
167
- const userColor = useMemo(
168
- () => user.color ?? generateUserColor(),
169
- [user.color],
170
- );
171
-
172
- // Update connection state and notify callback
173
- const updateConnectionState = useCallback(
174
- (state: ConnectionState) => {
175
- setConnectionState(state);
176
- onConnectionChange?.(state);
177
- },
178
- [onConnectionChange],
179
- );
180
-
181
- // Update collaborators from awareness
182
- const updateCollaborators = useCallback(
183
- (awareness: HocuspocusProvider["awareness"]) => {
184
- if (!awareness) return;
185
-
186
- const states = awareness.getStates();
187
- const collabs: Collaborator[] = [];
188
-
189
- states.forEach((state: Record<string, unknown>, clientId: number) => {
190
- // Skip our own client
191
- if (clientId === awareness.clientID) return;
192
-
193
- if (state.user) {
194
- collabs.push({
195
- clientId,
196
- user: state.user as Collaborator["user"],
197
- });
198
- }
199
- });
200
-
201
- setCollaborators(collabs);
202
- },
203
- [],
204
- );
205
-
206
- const clearRefreshTimer = useCallback(() => {
207
- if (refreshTimerRef.current != null) {
208
- window.clearTimeout(refreshTimerRef.current);
209
- refreshTimerRef.current = null;
210
- }
211
- }, []);
136
+ export function createEditorProvider(
137
+ peers: EditorProviderPeers,
138
+ ): ComponentType<EditorProviderProps> {
139
+ const { Doc } = peers.yjs;
140
+ const { HocuspocusProvider } = peers.hocuspocus;
212
141
 
213
- const refreshToken = useCallback(async (): Promise<string | null> => {
214
- if (!onRefreshToken) {
215
- return null;
142
+ return function EditorProvider({
143
+ websocketUrl,
144
+ documentName,
145
+ token,
146
+ tokenExpiresAt,
147
+ user,
148
+ autoConnect = true,
149
+ autoReconnect = true,
150
+ maxReconnectAttempts = 5,
151
+ onConnectionChange,
152
+ onSync,
153
+ onAuthError,
154
+ onRefreshToken,
155
+ children,
156
+ }: EditorProviderProps) {
157
+ const [connectionState, setConnectionState] =
158
+ useState<ConnectionState>("disconnected");
159
+ const [collaborators, setCollaborators] = useState<Collaborator[]>([]);
160
+ const [isSynced, setIsSynced] = useState(false);
161
+
162
+ // Use refs to avoid recreating provider on every render
163
+ const docRef = useRef<Y.Doc | null>(null);
164
+ const providerRef = useRef<HocuspocusProvider | null>(null);
165
+ const reconnectAttemptsRef = useRef(0);
166
+ const tokenRef = useRef(token);
167
+ const tokenExpiryRef = useRef<number | undefined>(tokenExpiresAt);
168
+ const refreshPromiseRef = useRef<Promise<string | null> | null>(null);
169
+ const refreshTimerRef = useRef<number | null>(null);
170
+
171
+ tokenRef.current = token;
172
+ tokenExpiryRef.current = tokenExpiresAt;
173
+
174
+ // Initialize Y.Doc once
175
+ if (!docRef.current) {
176
+ docRef.current = new Doc();
216
177
  }
178
+ const doc = docRef.current;
179
+
180
+ // User color (generate once per session)
181
+ const userColor = useMemo(
182
+ () => user.color ?? generateUserColor(),
183
+ [user.color],
184
+ );
185
+
186
+ // Update connection state and notify callback
187
+ const updateConnectionState = useCallback(
188
+ (state: ConnectionState) => {
189
+ setConnectionState(state);
190
+ onConnectionChange?.(state);
191
+ },
192
+ [onConnectionChange],
193
+ );
194
+
195
+ // Update collaborators from awareness
196
+ const updateCollaborators = useCallback(
197
+ (awareness: HocuspocusProvider["awareness"]) => {
198
+ if (!awareness) return;
199
+
200
+ const states = awareness.getStates();
201
+ const collabs: Collaborator[] = [];
202
+
203
+ states.forEach((state: Record<string, unknown>, clientId: number) => {
204
+ // Skip our own client
205
+ if (clientId === awareness.clientID) return;
206
+
207
+ if (state.user) {
208
+ collabs.push({
209
+ clientId,
210
+ user: state.user as Collaborator["user"],
211
+ });
212
+ }
213
+ });
214
+
215
+ setCollaborators(collabs);
216
+ },
217
+ [],
218
+ );
217
219
 
218
- if (refreshPromiseRef.current) {
219
- return refreshPromiseRef.current;
220
- }
220
+ const clearRefreshTimer = useCallback(() => {
221
+ if (refreshTimerRef.current != null) {
222
+ window.clearTimeout(refreshTimerRef.current);
223
+ refreshTimerRef.current = null;
224
+ }
225
+ }, []);
221
226
 
222
- const refreshPromise = (async () => {
223
- const next = await onRefreshToken();
224
- const resolvedToken = typeof next === "string" ? next : next.token;
225
- const resolvedExpiry =
226
- typeof next === "string" ? undefined : next.expiresAt;
227
-
228
- tokenRef.current = resolvedToken;
229
- tokenExpiryRef.current = resolvedExpiry;
230
- return resolvedToken;
231
- })()
232
- .catch((error) => {
233
- onAuthError?.(
234
- error instanceof Error ? error : new Error(String(error)),
235
- );
227
+ const refreshToken = useCallback(async (): Promise<string | null> => {
228
+ if (!onRefreshToken) {
236
229
  return null;
237
- })
238
- .finally(() => {
239
- refreshPromiseRef.current = null;
240
- });
230
+ }
241
231
 
242
- refreshPromiseRef.current = refreshPromise;
243
- return refreshPromise;
244
- }, [onAuthError, onRefreshToken]);
232
+ if (refreshPromiseRef.current) {
233
+ return refreshPromiseRef.current;
234
+ }
245
235
 
246
- const scheduleTokenRefresh = useCallback(() => {
247
- clearRefreshTimer();
236
+ const refreshPromise = (async () => {
237
+ const next = await onRefreshToken();
238
+ const resolvedToken = typeof next === "string" ? next : next.token;
239
+ const resolvedExpiry =
240
+ typeof next === "string" ? undefined : next.expiresAt;
241
+
242
+ tokenRef.current = resolvedToken;
243
+ tokenExpiryRef.current = resolvedExpiry;
244
+ return resolvedToken;
245
+ })()
246
+ .catch((error) => {
247
+ onAuthError?.(
248
+ error instanceof Error ? error : new Error(String(error)),
249
+ );
250
+ return null;
251
+ })
252
+ .finally(() => {
253
+ refreshPromiseRef.current = null;
254
+ });
248
255
 
249
- if (
250
- !tokenExpiryRef.current ||
251
- !onRefreshToken ||
252
- typeof window === "undefined"
253
- ) {
254
- return;
255
- }
256
+ refreshPromiseRef.current = refreshPromise;
257
+ return refreshPromise;
258
+ }, [onAuthError, onRefreshToken]);
256
259
 
257
- const refreshAtMs = tokenExpiryRef.current * 1000 - 60_000;
258
- const delay = refreshAtMs - Date.now();
260
+ const scheduleTokenRefresh = useCallback(() => {
261
+ clearRefreshTimer();
259
262
 
260
- if (delay <= 0) {
261
- void refreshToken();
262
- return;
263
- }
263
+ if (
264
+ !tokenExpiryRef.current ||
265
+ !onRefreshToken ||
266
+ typeof window === "undefined"
267
+ ) {
268
+ return;
269
+ }
264
270
 
265
- refreshTimerRef.current = window.setTimeout(() => {
266
- void refreshToken();
267
- }, delay);
268
- }, [clearRefreshTimer, onRefreshToken, refreshToken]);
271
+ const refreshAtMs = tokenExpiryRef.current * 1000 - 60_000;
272
+ const delay = refreshAtMs - Date.now();
269
273
 
270
- // Connect to the collaboration server
271
- const connect = useCallback(() => {
272
- if (providerRef.current) {
273
- providerRef.current.connect();
274
- return;
275
- }
274
+ if (delay <= 0) {
275
+ void refreshToken();
276
+ return;
277
+ }
276
278
 
277
- updateConnectionState("connecting");
279
+ refreshTimerRef.current = window.setTimeout(() => {
280
+ void refreshToken();
281
+ }, delay);
282
+ }, [clearRefreshTimer, onRefreshToken, refreshToken]);
278
283
 
279
- const provider = new HocuspocusProvider({
280
- url: websocketUrl,
281
- name: documentName,
282
- document: doc,
283
- token: async () => tokenRef.current,
284
+ // Connect to the collaboration server
285
+ const connect = useCallback(() => {
286
+ if (providerRef.current) {
287
+ providerRef.current.connect();
288
+ return;
289
+ }
284
290
 
285
- onConnect: () => {
286
- reconnectAttemptsRef.current = 0;
287
- updateConnectionState("connected");
288
- scheduleTokenRefresh();
289
- },
291
+ updateConnectionState("connecting");
292
+
293
+ const provider = new HocuspocusProvider({
294
+ url: websocketUrl,
295
+ name: documentName,
296
+ document: doc,
297
+ token: async () => tokenRef.current,
298
+
299
+ onConnect: () => {
300
+ reconnectAttemptsRef.current = 0;
301
+ updateConnectionState("connected");
302
+ scheduleTokenRefresh();
303
+ },
304
+
305
+ onSynced: () => {
306
+ setIsSynced(true);
307
+ updateConnectionState("synced");
308
+ onSync?.();
309
+ },
310
+
311
+ onDisconnect: () => {
312
+ updateConnectionState("disconnected");
313
+ setIsSynced(false);
314
+ clearRefreshTimer();
315
+
316
+ // Auto-reconnect logic
317
+ if (
318
+ autoReconnect &&
319
+ reconnectAttemptsRef.current < maxReconnectAttempts
320
+ ) {
321
+ reconnectAttemptsRef.current += 1;
322
+ const delay = Math.min(
323
+ 1000 * 2 ** reconnectAttemptsRef.current,
324
+ 30000,
325
+ );
326
+ setTimeout(() => {
327
+ if (providerRef.current && !(providerRef.current as any).isConnected) {
328
+ providerRef.current.connect();
329
+ }
330
+ }, delay);
331
+ }
332
+ },
333
+
334
+ onAuthenticationFailed: ({ reason }: { reason?: string }) => {
335
+ const error = new Error(reason ?? "Authentication failed");
336
+ updateConnectionState("disconnected");
337
+ clearRefreshTimer();
338
+
339
+ if (onRefreshToken) {
340
+ void refreshToken().then((nextToken) => {
341
+ if (nextToken && providerRef.current) {
342
+ providerRef.current.connect();
343
+ return;
344
+ }
345
+
346
+ onAuthError?.(error);
347
+ });
348
+ return;
349
+ }
350
+
351
+ onAuthError?.(error);
352
+ },
353
+
354
+ onAwarenessUpdate: () => {
355
+ updateCollaborators(provider.awareness);
356
+ },
357
+ });
290
358
 
291
- onSynced: () => {
292
- setIsSynced(true);
293
- updateConnectionState("synced");
294
- onSync?.();
295
- },
359
+ // Set local user awareness
360
+ provider.awareness?.setLocalStateField("user", {
361
+ name: user.name,
362
+ color: userColor,
363
+ userId: user.userId,
364
+ });
296
365
 
297
- onDisconnect: () => {
366
+ providerRef.current = provider;
367
+ }, [
368
+ websocketUrl,
369
+ documentName,
370
+ doc,
371
+ user.name,
372
+ user.userId,
373
+ userColor,
374
+ autoReconnect,
375
+ maxReconnectAttempts,
376
+ clearRefreshTimer,
377
+ updateConnectionState,
378
+ updateCollaborators,
379
+ onSync,
380
+ onAuthError,
381
+ onRefreshToken,
382
+ refreshToken,
383
+ scheduleTokenRefresh,
384
+ ]);
385
+
386
+ // Disconnect from the collaboration server
387
+ const disconnect = useCallback(() => {
388
+ if (providerRef.current) {
389
+ providerRef.current.disconnect();
298
390
  updateConnectionState("disconnected");
299
- setIsSynced(false);
300
- clearRefreshTimer();
391
+ }
392
+ }, [updateConnectionState]);
301
393
 
302
- // Auto-reconnect logic
303
- if (
304
- autoReconnect &&
305
- reconnectAttemptsRef.current < maxReconnectAttempts
306
- ) {
307
- reconnectAttemptsRef.current += 1;
308
- const delay = Math.min(
309
- 1000 * 2 ** reconnectAttemptsRef.current,
310
- 30000,
311
- );
312
- setTimeout(() => {
313
- if (providerRef.current && !(providerRef.current as any).isConnected) {
314
- providerRef.current.connect();
315
- }
316
- }, delay);
317
- }
318
- },
394
+ // Auto-connect on mount
395
+ useEffect(() => {
396
+ if (autoConnect) {
397
+ connect();
398
+ }
319
399
 
320
- onAuthenticationFailed: ({ reason }: { reason?: string }) => {
321
- const error = new Error(reason ?? "Authentication failed");
322
- updateConnectionState("disconnected");
400
+ return () => {
401
+ // Cleanup on unmount
323
402
  clearRefreshTimer();
324
-
325
- if (onRefreshToken) {
326
- void refreshToken().then((nextToken) => {
327
- if (nextToken && providerRef.current) {
328
- providerRef.current.connect();
329
- return;
330
- }
331
-
332
- onAuthError?.(error);
333
- });
334
- return;
403
+ if (providerRef.current) {
404
+ providerRef.current.destroy();
405
+ providerRef.current = null;
335
406
  }
407
+ };
408
+ }, [autoConnect, clearRefreshTimer, connect]);
409
+
410
+ // Context value
411
+ const contextValue = useMemo<EditorContextValue>(
412
+ () => ({
413
+ doc,
414
+ provider: providerRef.current,
415
+ connectionState,
416
+ collaborators,
417
+ isSynced,
418
+ connect,
419
+ disconnect,
420
+ }),
421
+ [doc, connectionState, collaborators, isSynced, connect, disconnect],
422
+ );
423
+
424
+ return (
425
+ <EditorContext.Provider value={contextValue}>
426
+ {children}
427
+ </EditorContext.Provider>
428
+ );
429
+ };
430
+ }
336
431
 
337
- onAuthError?.(error);
338
- },
339
-
340
- onAwarenessUpdate: () => {
341
- updateCollaborators(provider.awareness);
342
- },
343
- });
344
-
345
- // Set local user awareness
346
- provider.awareness?.setLocalStateField("user", {
347
- name: user.name,
348
- color: userColor,
349
- userId: user.userId,
350
- });
351
-
352
- providerRef.current = provider;
353
- }, [
354
- websocketUrl,
355
- documentName,
356
- doc,
357
- user.name,
358
- user.userId,
359
- userColor,
360
- autoReconnect,
361
- maxReconnectAttempts,
362
- clearRefreshTimer,
363
- updateConnectionState,
364
- updateCollaborators,
365
- onSync,
366
- onAuthError,
367
- onRefreshToken,
368
- refreshToken,
369
- scheduleTokenRefresh,
370
- ]);
371
-
372
- // Disconnect from the collaboration server
373
- const disconnect = useCallback(() => {
374
- if (providerRef.current) {
375
- providerRef.current.disconnect();
376
- updateConnectionState("disconnected");
377
- }
378
- }, [updateConnectionState]);
379
-
380
- // Auto-connect on mount
381
- useEffect(() => {
382
- if (autoConnect) {
383
- connect();
384
- }
385
-
386
- return () => {
387
- // Cleanup on unmount
388
- clearRefreshTimer();
389
- if (providerRef.current) {
390
- providerRef.current.destroy();
391
- providerRef.current = null;
392
- }
393
- };
394
- }, [autoConnect, clearRefreshTimer, connect]);
395
-
396
- // Context value
397
- const contextValue = useMemo<EditorContextValue>(
398
- () => ({
399
- doc,
400
- provider: providerRef.current,
401
- connectionState,
402
- collaborators,
403
- isSynced,
404
- connect,
405
- disconnect,
406
- }),
407
- [doc, connectionState, collaborators, isSynced, connect, disconnect],
408
- );
432
+ const lazyEditorProvider = retryableLazyEditor(async () =>
433
+ createEditorProvider(await loadEditorProviderPeers()),
434
+ );
409
435
 
436
+ /**
437
+ * EditorProvider wraps children with Hocuspocus collaboration context.
438
+ * Manages WebSocket connection, Y.Doc, and awareness state. Loads `yjs` and
439
+ * `@hocuspocus/provider` — and no tiptap package — before it renders children,
440
+ * because every child hook reads a context that only the loaded provider can
441
+ * supply. A consumer that drives its own editor from that context therefore
442
+ * needs those two peers alone.
443
+ */
444
+ export function EditorProvider(props: EditorProviderProps) {
445
+ const LazyEditorProvider = lazyEditorProvider();
410
446
  return (
411
- <EditorContext.Provider value={contextValue}>
412
- {children}
413
- </EditorContext.Provider>
447
+ <Suspense fallback={null}>
448
+ <LazyEditorProvider {...props} />
449
+ </Suspense>
414
450
  );
415
451
  }
416
452
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { type Editor } from "@tiptap/react";
3
+ import type { Editor } from "@tiptap/react";
4
4
  import { cn } from "../lib/utils";
5
5
 
6
6
  /**