@ngenux/ngage-whiteboarding 1.0.8 → 1.0.9

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 (49) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.esm.js +106 -91
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +113 -90
  6. package/dist/index.js.map +1 -1
  7. package/dist/src/components/Whiteboard/index.d.ts.map +1 -1
  8. package/dist/src/context/WhiteboardContext.d.ts.map +1 -1
  9. package/dist/src/utils/socket-utility.d.ts +6 -1
  10. package/dist/src/utils/socket-utility.d.ts.map +1 -1
  11. package/dist/utils/index.d.ts +13 -0
  12. package/dist/utils/index.d.ts.map +1 -0
  13. package/dist/utils/socket-utility.esm.js +168 -0
  14. package/dist/utils/socket-utility.esm.js.map +1 -0
  15. package/dist/utils/socket-utility.js +177 -0
  16. package/dist/utils/socket-utility.js.map +1 -0
  17. package/dist/utils/src/components/Shapes/Arrow.d.ts +11 -0
  18. package/dist/utils/src/components/Shapes/Arrow.d.ts.map +1 -0
  19. package/dist/utils/src/components/Shapes/Ellipse.d.ts +11 -0
  20. package/dist/utils/src/components/Shapes/Ellipse.d.ts.map +1 -0
  21. package/dist/utils/src/components/Shapes/ErasedShape.d.ts +11 -0
  22. package/dist/utils/src/components/Shapes/ErasedShape.d.ts.map +1 -0
  23. package/dist/utils/src/components/Shapes/FreehandDrawing.d.ts +11 -0
  24. package/dist/utils/src/components/Shapes/FreehandDrawing.d.ts.map +1 -0
  25. package/dist/utils/src/components/Shapes/Line.d.ts +11 -0
  26. package/dist/utils/src/components/Shapes/Line.d.ts.map +1 -0
  27. package/dist/utils/src/components/Shapes/Rectangle.d.ts +11 -0
  28. package/dist/utils/src/components/Shapes/Rectangle.d.ts.map +1 -0
  29. package/dist/utils/src/components/Whiteboard/Board.d.ts +15 -0
  30. package/dist/utils/src/components/Whiteboard/Board.d.ts.map +1 -0
  31. package/dist/utils/src/components/Whiteboard/Toolbar.d.ts +21 -0
  32. package/dist/utils/src/components/Whiteboard/Toolbar.d.ts.map +1 -0
  33. package/dist/utils/src/components/Whiteboard/index.d.ts +11 -0
  34. package/dist/utils/src/components/Whiteboard/index.d.ts.map +1 -0
  35. package/dist/utils/src/context/WhiteboardContext.d.ts +128 -0
  36. package/dist/utils/src/context/WhiteboardContext.d.ts.map +1 -0
  37. package/dist/utils/src/hooks/useCapture.d.ts +4 -0
  38. package/dist/utils/src/hooks/useCapture.d.ts.map +1 -0
  39. package/dist/utils/src/hooks/useCollaborativeWhiteboard.d.ts +27 -0
  40. package/dist/utils/src/hooks/useCollaborativeWhiteboard.d.ts.map +1 -0
  41. package/dist/utils/src/lib/utils.d.ts +3 -0
  42. package/dist/utils/src/lib/utils.d.ts.map +1 -0
  43. package/dist/utils/src/types/index.d.ts +123 -0
  44. package/dist/utils/src/types/index.d.ts.map +1 -0
  45. package/dist/utils/src/utils/compression.d.ts +14 -0
  46. package/dist/utils/src/utils/compression.d.ts.map +1 -0
  47. package/dist/utils/src/utils/socket-utility.d.ts +11 -0
  48. package/dist/utils/src/utils/socket-utility.d.ts.map +1 -0
  49. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -35275,12 +35275,16 @@ const WhiteboardProvider = ({ children, webSocketUrl }) => {
35275
35275
  };
35276
35276
  const requestStateFromPeers = () => {
35277
35277
  if (currentQueueAction) {
35278
- currentQueueAction({
35279
- type: 'request_state',
35280
- payload: '',
35281
- requesterId: state.userId,
35282
- timestamp: Date.now(),
35283
- });
35278
+ setTimeout(() => {
35279
+ if (currentQueueAction) {
35280
+ currentQueueAction({
35281
+ type: 'request_state',
35282
+ payload: '',
35283
+ requesterId: state.userId,
35284
+ timestamp: Date.now(),
35285
+ });
35286
+ }
35287
+ }, 2000);
35284
35288
  }
35285
35289
  else {
35286
35290
  console.warn('[STATE_SYNC] No queue action available for state request');
@@ -37089,32 +37093,6 @@ const Eraser = createLucideIcon("Eraser", [
37089
37093
  */
37090
37094
 
37091
37095
 
37092
- const LockOpen = createLucideIcon("LockOpen", [
37093
- ["rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2", key: "1w4ew1" }],
37094
- ["path", { d: "M7 11V7a5 5 0 0 1 9.9-1", key: "1mm8w8" }]
37095
- ]);
37096
-
37097
- /**
37098
- * @license lucide-react v0.460.0 - ISC
37099
- *
37100
- * This source code is licensed under the ISC license.
37101
- * See the LICENSE file in the root directory of this source tree.
37102
- */
37103
-
37104
-
37105
- const Lock = createLucideIcon("Lock", [
37106
- ["rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2", key: "1w4ew1" }],
37107
- ["path", { d: "M7 11V7a5 5 0 0 1 10 0v4", key: "fwvmzm" }]
37108
- ]);
37109
-
37110
- /**
37111
- * @license lucide-react v0.460.0 - ISC
37112
- *
37113
- * This source code is licensed under the ISC license.
37114
- * See the LICENSE file in the root directory of this source tree.
37115
- */
37116
-
37117
-
37118
37096
  const Minus = createLucideIcon("Minus", [["path", { d: "M5 12h14", key: "1ays0h" }]]);
37119
37097
 
37120
37098
  /**
@@ -37195,7 +37173,7 @@ const Undo2 = createLucideIcon("Undo2", [
37195
37173
  ]);
37196
37174
 
37197
37175
  // Top Toolbar Component
37198
- const TopToolbar = ({ queueAction, handleExportImage, handleClear, handleLockToggle, isAdmin = false, hasToolAccess = false, isGloballyUnlocked = false, shouldBeOpenByDefault = true, hasVideoBackground = false }) => {
37176
+ const TopToolbar = ({ queueAction, handleExportImage, handleClear, handleLockToggle, isAdmin = false, hasToolAccess = false, isGloballyUnlocked = true, shouldBeOpenByDefault = true, hasVideoBackground = false }) => {
37199
37177
  const { state, dispatch } = useWhiteboard();
37200
37178
  const [isVisible, setIsVisible] = React.useState(shouldBeOpenByDefault);
37201
37179
  const [isInitialized, setIsInitialized] = React.useState(false);
@@ -37271,9 +37249,7 @@ const TopToolbar = ({ queueAction, handleExportImage, handleClear, handleLockTog
37271
37249
  if (!isInitialized) {
37272
37250
  return null;
37273
37251
  }
37274
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "absolute top-5 left-1/2 transform -translate-x-1/2 flex flex-col items-center z-10", children: [!isVisible && (jsxRuntime.jsx("button", { className: "w-10 h-10 flex items-center justify-center bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300", onClick: handleToggleVisibility, title: "Show Tools", children: jsxRuntime.jsx(ChevronDown, { size: 16, className: "text-current" }) })), isVisible && (jsxRuntime.jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg", children: jsxRuntime.jsxs("div", { className: "flex items-center gap-1 p-1", children: [isAdmin && (jsxRuntime.jsx("button", { className: `w-10 h-10 flex items-center justify-center rounded transition-colors ${isGloballyUnlocked
37275
- ? 'bg-green-100 dark:bg-green-900/50 text-green-600 dark:text-green-400 hover:bg-green-200 dark:hover:bg-green-900/70'
37276
- : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'}`, onClick: handleLockToggle, title: isGloballyUnlocked ? 'Whiteboard unlocked for all users - Click to lock' : 'Whiteboard locked - Click to unlock for all users', children: isGloballyUnlocked ? jsxRuntime.jsx(LockOpen, { size: 16, className: "text-current" }) : jsxRuntime.jsx(Lock, { size: 16, className: "text-current" }) })), jsxRuntime.jsx("button", { className: `w-10 h-10 flex items-center justify-center rounded ${hasToolAccess ? 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300' : 'opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-600'}`, onClick: handleUndo, disabled: !hasToolAccess, title: hasToolAccess ? 'Undo' : 'Access restricted', children: jsxRuntime.jsx(Undo2, { size: 16, className: "text-current" }) }), jsxRuntime.jsx("button", { className: `w-10 h-10 flex items-center justify-center rounded ${hasToolAccess ? 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300' : 'opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-600'}`, onClick: handleRedo, disabled: !hasToolAccess, title: hasToolAccess ? 'Redo' : 'Access restricted', children: jsxRuntime.jsx(Redo2, { size: 16, className: "text-current" }) }), jsxRuntime.jsx("div", { className: "w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1" }), tools.map((tool) => (jsxRuntime.jsx("button", { className: `w-10 h-10 flex items-center justify-center rounded transition-colors ${!hasToolAccess
37252
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "absolute top-5 left-1/2 transform -translate-x-1/2 flex flex-col items-center z-10", children: [!isVisible && (jsxRuntime.jsx("button", { className: "w-10 h-10 flex items-center justify-center bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300", onClick: handleToggleVisibility, title: "Show Tools", children: jsxRuntime.jsx(ChevronDown, { size: 16, className: "text-current" }) })), isVisible && (jsxRuntime.jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg", children: jsxRuntime.jsxs("div", { className: "flex items-center gap-1 p-1", children: [jsxRuntime.jsx("button", { className: `w-10 h-10 flex items-center justify-center rounded ${hasToolAccess ? 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300' : 'opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-600'}`, onClick: handleUndo, disabled: !hasToolAccess, title: hasToolAccess ? 'Undo' : 'Access restricted', children: jsxRuntime.jsx(Undo2, { size: 16, className: "text-current" }) }), jsxRuntime.jsx("button", { className: `w-10 h-10 flex items-center justify-center rounded ${hasToolAccess ? 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300' : 'opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-600'}`, onClick: handleRedo, disabled: !hasToolAccess, title: hasToolAccess ? 'Redo' : 'Access restricted', children: jsxRuntime.jsx(Redo2, { size: 16, className: "text-current" }) }), jsxRuntime.jsx("div", { className: "w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1" }), tools.map((tool) => (jsxRuntime.jsx("button", { className: `w-10 h-10 flex items-center justify-center rounded transition-colors ${!hasToolAccess
37277
37253
  ? 'opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-600'
37278
37254
  : state.tool === tool.type
37279
37255
  ? 'bg-purple-100 dark:bg-purple-900/50 text-purple-600 dark:text-purple-300'
@@ -42331,6 +42307,7 @@ Object.assign(lookup, {
42331
42307
  let socket = null;
42332
42308
  const joinedRooms = new Set();
42333
42309
  const setupCallbacks = new Map();
42310
+ const statusChangeCallbacks = new Set();
42334
42311
  let currentWebSocketUrl = undefined;
42335
42312
  // Initialize socket connection
42336
42313
  const initializeSocket = (webSocketUrl) => {
@@ -42346,7 +42323,6 @@ const initializeSocket = (webSocketUrl) => {
42346
42323
  setupCallbacks.clear();
42347
42324
  }
42348
42325
  currentWebSocketUrl = webSocketUrl;
42349
- console.log('[SOCKET] Using socket server URL:', socketServerUrl);
42350
42326
  if (!socketServerUrl) {
42351
42327
  console.error('[SOCKET] No socket server URL provided');
42352
42328
  }
@@ -42357,29 +42333,21 @@ const initializeSocket = (webSocketUrl) => {
42357
42333
  reconnectionDelay: 1000,
42358
42334
  });
42359
42335
  socket.on('connect', () => {
42360
- console.log('[SOCKET] Connected to server');
42361
- // Re-join all rooms after reconnection
42336
+ statusChangeCallbacks.forEach(callback => callback(true));
42362
42337
  joinedRooms.forEach(roomId => {
42363
42338
  socket.emit('join-room', roomId);
42364
- console.log('[SOCKET] Re-joined room:', roomId);
42365
42339
  });
42366
42340
  });
42367
42341
  socket.on('disconnect', () => {
42368
- console.log('[SOCKET] Disconnected from server');
42342
+ statusChangeCallbacks.forEach(callback => callback(false));
42369
42343
  });
42370
- socket.on('connect_error', (error) => {
42371
- console.error('[SOCKET] Connection error:', error);
42344
+ socket.on('connect_error', () => {
42345
+ // Connection error handled by Socket.IO reconnection logic
42372
42346
  });
42373
42347
  // Set up the global receive-message listener once
42374
42348
  socket.on('receive-message', (message) => {
42375
42349
  const callback = setupCallbacks.get(message.roomId);
42376
42350
  if (callback) {
42377
- console.log('[SOCKET] Received message from room:', message.roomId, {
42378
- compression: message.data.compressionType,
42379
- originalSize: message.data.originalSize,
42380
- compressedSize: message.data.compressedSize,
42381
- from: message.from
42382
- });
42383
42351
  callback(message.data);
42384
42352
  }
42385
42353
  });
@@ -42413,18 +42381,23 @@ const onSend = (roomId, data, webSocketUrl) => {
42413
42381
  console.error('[SOCKET] Error sending message:', error);
42414
42382
  }
42415
42383
  };
42416
- const onReceive = (roomId, callback, webSocketUrl) => {
42384
+ const onReceive = (roomId, callback, webSocketUrl, onRoomJoined) => {
42417
42385
  const socketInstance = initializeSocket(webSocketUrl);
42418
42386
  // Store the callback for this room
42419
42387
  setupCallbacks.set(roomId, callback);
42420
- // Only join the room if we haven't already
42421
42388
  if (!joinedRooms.has(roomId)) {
42422
42389
  socketInstance.emit('join-room', roomId);
42423
42390
  joinedRooms.add(roomId);
42424
- console.log('[SOCKET] Joined room:', roomId);
42391
+ if (onRoomJoined) {
42392
+ setTimeout(() => {
42393
+ onRoomJoined();
42394
+ }, 100);
42395
+ }
42425
42396
  }
42426
42397
  else {
42427
- console.log('[SOCKET] Already in room:', roomId);
42398
+ if (onRoomJoined) {
42399
+ onRoomJoined();
42400
+ }
42428
42401
  }
42429
42402
  };
42430
42403
  const leaveRoom = (roomId) => {
@@ -42441,20 +42414,66 @@ const disconnectSocket = () => {
42441
42414
  socket = null;
42442
42415
  joinedRooms.clear();
42443
42416
  setupCallbacks.clear();
42444
- console.log('[SOCKET] Socket disconnected and cleaned up');
42445
42417
  }
42446
42418
  };
42419
+ // Get current socket connection status
42420
+ const isSocketConnected = () => {
42421
+ return socket?.connected ?? false;
42422
+ };
42423
+ // Get current socket instance
42424
+ const getSocket = () => {
42425
+ return socket;
42426
+ };
42427
+ // Subscribe to connection status changes
42428
+ const onSocketStatusChange = (callback) => {
42429
+ const socketInstance = socket || initializeSocket();
42430
+ statusChangeCallbacks.add(callback);
42431
+ callback(socketInstance.connected);
42432
+ return () => {
42433
+ statusChangeCallbacks.delete(callback);
42434
+ };
42435
+ };
42436
+ const waitForSocket = (webSocketUrl, timeoutMs = 5000) => {
42437
+ return new Promise((resolve) => {
42438
+ const socketInstance = initializeSocket(webSocketUrl);
42439
+ if (socketInstance.connected) {
42440
+ resolve();
42441
+ return;
42442
+ }
42443
+ const handleConnect = () => {
42444
+ socketInstance.off('connect', handleConnect);
42445
+ clearTimeout(timeoutHandle);
42446
+ resolve();
42447
+ };
42448
+ socketInstance.on('connect', handleConnect);
42449
+ const timeoutHandle = setTimeout(() => {
42450
+ socketInstance.off('connect', handleConnect);
42451
+ resolve();
42452
+ }, timeoutMs);
42453
+ });
42454
+ };
42447
42455
 
42448
42456
  const Whiteboard = ({ roomId, isAdmin = false, allowedUsers = [], userId, transparentBackground = false, videoStream }) => {
42449
42457
  const { state, dispatch, setQueueAction, requestStateFromPeers, webSocketUrl } = useWhiteboard();
42450
42458
  const [lastCollaborativeAction, setLastCollaborativeAction] = React.useState(null);
42451
42459
  const [hasRequestedState, setHasRequestedState] = React.useState(false);
42452
42460
  const [lastStateRequestTime, setLastStateRequestTime] = React.useState(0);
42453
- const [isGloballyUnlocked, setIsGloballyUnlocked] = React.useState(false); // Global unlock status
42461
+ const [isSocketConnected, setIsSocketConnected] = React.useState(false);
42462
+ const [isRoomJoined, setIsRoomJoined] = React.useState(false);
42463
+ const [isGloballyUnlocked, setIsGloballyUnlocked] = React.useState(true); // Global unlock status
42454
42464
  const [syncedAllowedUsers, setSyncedAllowedUsers] = React.useState(allowedUsers); // Synced allowed users from collaboration
42455
42465
  const isCollaborativeUpdateRef = React.useRef(false); // Track if update came from collaboration
42456
42466
  const lastClearTimeRef = React.useRef(0); // Track when last clear happened
42457
42467
  const boardRef = React.useRef(null);
42468
+ React.useEffect(() => {
42469
+ const unsubscribe = onSocketStatusChange((connected) => {
42470
+ setIsSocketConnected(connected);
42471
+ });
42472
+ return () => {
42473
+ console.log('[WHITEBOARD] Unsubscribing from socket status listener');
42474
+ unsubscribe();
42475
+ };
42476
+ }, []); // Empty dependencies - single listener for component lifecycle
42458
42477
  // Set userId in context when component mounts or userId changes
42459
42478
  React.useEffect(() => {
42460
42479
  dispatch({ type: 'SET_USER_ID', payload: userId });
@@ -42535,7 +42554,9 @@ const Whiteboard = ({ roomId, isAdmin = false, allowedUsers = [], userId, transp
42535
42554
  setHasRequestedState(false);
42536
42555
  }
42537
42556
  callback(data);
42538
- }, webSocketUrl);
42557
+ }, webSocketUrl, () => {
42558
+ setIsRoomJoined(true);
42559
+ });
42539
42560
  }, [roomId, webSocketUrl]);
42540
42561
  // Initialize the collaborative whiteboard hook
42541
42562
  const collaborativeConfig = React.useMemo(() => ({
@@ -42572,48 +42593,42 @@ const Whiteboard = ({ roomId, isAdmin = false, allowedUsers = [], userId, transp
42572
42593
  });
42573
42594
  }
42574
42595
  }, [allowedUsers, queueAction, userId, syncedAllowedUsers]);
42575
- // Request state from peers when joining/rejoining the room
42596
+ // Request state from peers when room is successfully joined AND socket is connected
42597
+ // Need both conditions to ensure message can actually be sent
42576
42598
  React.useEffect(() => {
42577
- if (queueAction && typeof queueAction === 'function' && !hasRequestedState) {
42578
- const requestTimer = setTimeout(() => {
42579
- const now = Date.now();
42580
- if (now - lastClearTimeRef.current < 10000) {
42581
- return;
42582
- }
42583
- if (now - lastStateRequestTime > 5000) {
42584
- requestStateFromPeers();
42585
- setHasRequestedState(true);
42586
- setLastStateRequestTime(now);
42587
- }
42588
- }, 500);
42589
- return () => clearTimeout(requestTimer);
42599
+ if (!isRoomJoined || !isSocketConnected || hasRequestedState || state.shapes.length > 0 || !queueAction) {
42600
+ return;
42590
42601
  }
42591
- }, [roomId, queueAction, requestStateFromPeers, hasRequestedState, lastStateRequestTime]);
42602
+ const now = Date.now();
42603
+ if (now - lastClearTimeRef.current < 10000) {
42604
+ return;
42605
+ }
42606
+ requestStateFromPeers();
42607
+ setHasRequestedState(true);
42608
+ setLastStateRequestTime(Date.now());
42609
+ }, [isRoomJoined, isSocketConnected, state.shapes.length, hasRequestedState, queueAction, requestStateFromPeers, userId, roomId]);
42592
42610
  // Reset request flag when room changes
42593
42611
  React.useEffect(() => {
42594
42612
  setHasRequestedState(false);
42595
42613
  setLastStateRequestTime(0);
42614
+ setIsRoomJoined(false);
42596
42615
  }, [roomId]);
42597
- // Monitor for empty canvas and request state only if we haven't tried recently
42616
+ // Retry state request if canvas is still empty after 3 seconds
42598
42617
  React.useEffect(() => {
42599
- if (queueAction &&
42600
- typeof queueAction === 'function' &&
42601
- state.shapes.length === 0 &&
42602
- !hasRequestedState) {
42603
- const now = Date.now();
42604
- if (now - lastClearTimeRef.current < 10000) {
42605
- return;
42606
- }
42607
- if (now - lastStateRequestTime > 10000) {
42608
- const reconnectTimer = setTimeout(() => {
42609
- requestStateFromPeers();
42610
- setHasRequestedState(true);
42611
- setLastStateRequestTime(now);
42612
- }, 2000);
42613
- return () => clearTimeout(reconnectTimer);
42614
- }
42618
+ if (!isRoomJoined || !isSocketConnected || hasRequestedState || state.shapes.length > 0 || !queueAction) {
42619
+ return;
42620
+ }
42621
+ const now = Date.now();
42622
+ // Don't retry if we recently cleared
42623
+ if (now - lastClearTimeRef.current < 10000) {
42624
+ return;
42615
42625
  }
42616
- }, [queueAction, state.shapes.length, requestStateFromPeers, hasRequestedState, lastStateRequestTime]);
42626
+ const retryTimer = setTimeout(() => {
42627
+ requestStateFromPeers();
42628
+ setLastStateRequestTime(Date.now());
42629
+ }, 3000);
42630
+ return () => clearTimeout(retryTimer);
42631
+ }, [isRoomJoined, isSocketConnected, state.shapes.length, queueAction, requestStateFromPeers, lastStateRequestTime, userId]);
42617
42632
  // Cleanup stale active drawings periodically
42618
42633
  React.useEffect(() => {
42619
42634
  const cleanupInterval = setInterval(() => {
@@ -42815,7 +42830,7 @@ const Whiteboard = ({ roomId, isAdmin = false, allowedUsers = [], userId, transp
42815
42830
  });
42816
42831
  }
42817
42832
  };
42818
- }, [isAdmin, queueAction, userId, dispatch]);
42833
+ }, [isAdmin, userId, dispatch]);
42819
42834
  // Global cleanup on app unmount
42820
42835
  React.useEffect(() => {
42821
42836
  const handleBeforeUnload = () => {
@@ -45861,5 +45876,13 @@ function cn(...inputs) {
45861
45876
  exports.Whiteboard = Whiteboard;
45862
45877
  exports.WhiteboardProvider = WhiteboardProvider;
45863
45878
  exports.cn = cn;
45879
+ exports.disconnectSocket = disconnectSocket;
45880
+ exports.getSocket = getSocket;
45881
+ exports.isSocketConnected = isSocketConnected;
45882
+ exports.leaveRoom = leaveRoom;
45883
+ exports.onReceive = onReceive;
45884
+ exports.onSend = onSend;
45885
+ exports.onSocketStatusChange = onSocketStatusChange;
45864
45886
  exports.useWhiteboardStream = useCapture;
45887
+ exports.waitForSocket = waitForSocket;
45865
45888
  //# sourceMappingURL=index.js.map