@xcelsior/ui-spreadsheets 1.0.5 → 1.0.6

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcelsior/ui-spreadsheets",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
@@ -1,3 +1,4 @@
1
+ import { useState, useEffect } from 'react';
1
2
  import { cn } from '../utils';
2
3
  import type { CellComment } from '../types';
3
4
 
@@ -6,28 +7,43 @@ import type { CellComment } from '../types';
6
7
  export interface AddCommentModalProps {
7
8
  /** Whether the modal is open */
8
9
  isOpen: boolean;
9
- /** Current comment text */
10
- commentText: string;
11
10
  /** Column label for the cell (optional) */
12
11
  columnLabel?: string;
13
- /** Callback to update comment text */
14
- onCommentTextChange: (text: string) => void;
15
- /** Callback to add the comment */
16
- onAdd: () => void;
12
+ /** Callback to add the comment with the text */
13
+ onAdd: (text: string) => void;
17
14
  /** Callback to close/cancel */
18
15
  onClose: () => void;
19
16
  }
20
17
 
21
18
  export function AddCommentModal({
22
19
  isOpen,
23
- commentText,
24
20
  columnLabel,
25
- onCommentTextChange,
26
21
  onAdd,
27
22
  onClose,
28
23
  }: AddCommentModalProps) {
24
+ const [commentText, setCommentText] = useState('');
25
+
26
+ // Reset text when modal opens/closes
27
+ useEffect(() => {
28
+ if (!isOpen) {
29
+ setCommentText('');
30
+ }
31
+ }, [isOpen]);
32
+
29
33
  if (!isOpen) return null;
30
34
 
35
+ const handleAdd = () => {
36
+ if (commentText.trim()) {
37
+ onAdd(commentText);
38
+ setCommentText('');
39
+ }
40
+ };
41
+
42
+ const handleClose = () => {
43
+ setCommentText('');
44
+ onClose();
45
+ };
46
+
31
47
  return (
32
48
  <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
33
49
  <div className="bg-white rounded-lg shadow-xl p-6 w-96 max-w-full mx-4">
@@ -36,21 +52,22 @@ export function AddCommentModal({
36
52
  </h3>
37
53
  <textarea
38
54
  value={commentText}
39
- onChange={(e) => onCommentTextChange(e.target.value)}
55
+ onChange={(e) => setCommentText(e.target.value)}
40
56
  placeholder="Enter your comment..."
41
57
  className="w-full h-24 p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none"
58
+ autoFocus
42
59
  />
43
60
  <div className="flex justify-end gap-2 mt-4">
44
61
  <button
45
62
  type="button"
46
- onClick={onClose}
63
+ onClick={handleClose}
47
64
  className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
48
65
  >
49
66
  Cancel
50
67
  </button>
51
68
  <button
52
69
  type="button"
53
- onClick={onAdd}
70
+ onClick={handleAdd}
54
71
  disabled={!commentText.trim()}
55
72
  className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
56
73
  >
@@ -178,8 +178,6 @@ export function Spreadsheet<T extends Record<string, any>>({
178
178
  cellHasComments,
179
179
  commentModalCell,
180
180
  setCommentModalCell,
181
- commentText,
182
- setCommentText,
183
181
  viewCommentsCell,
184
182
  setViewCommentsCell,
185
183
  handleAddCellComment,
@@ -1054,7 +1052,6 @@ export function Spreadsheet<T extends Record<string, any>>({
1054
1052
  {/* Add Cell Comment Modal */}
1055
1053
  <AddCommentModal
1056
1054
  isOpen={commentModalCell !== null}
1057
- commentText={commentText}
1058
1055
  columnLabel={
1059
1056
  commentModalCell
1060
1057
  ? commentModalCell.columnId === ROW_INDEX_COLUMN_ID
@@ -1062,13 +1059,11 @@ export function Spreadsheet<T extends Record<string, any>>({
1062
1059
  : columns.find((c) => c.id === commentModalCell.columnId)?.label
1063
1060
  : undefined
1064
1061
  }
1065
- onCommentTextChange={setCommentText}
1066
- onAdd={() =>
1062
+ onAdd={(text) =>
1067
1063
  commentModalCell !== null &&
1068
- handleAddCellComment(commentModalCell.rowId, commentModalCell.columnId)
1064
+ handleAddCellComment(commentModalCell.rowId, commentModalCell.columnId, text)
1069
1065
  }
1070
1066
  onClose={() => {
1071
- setCommentText('');
1072
1067
  setCommentModalCell(null);
1073
1068
  }}
1074
1069
  />
@@ -1,5 +1,5 @@
1
1
  import type React from 'react';
2
- import { useState, useRef, useEffect } from 'react';
2
+ import { useState, useRef, useEffect, memo } from 'react';
3
3
  import { HiOutlineClipboardCopy, HiOutlineClipboardCheck } from 'react-icons/hi';
4
4
  import { AiFillHighlight } from 'react-icons/ai';
5
5
  import { FaComment, FaRegComment } from 'react-icons/fa';
@@ -27,38 +27,38 @@ const cellPaddingNormal = 'px-2 py-1';
27
27
  * />
28
28
  * ```
29
29
  */
30
- export const SpreadsheetCell: React.FC<SpreadsheetCellProps> = ({
31
- value,
32
- column,
33
- row,
34
- rowIndex,
35
- rowId,
36
- isEditable = false,
37
- isEditing = false,
38
- isFocused = false,
39
- isRowSelected = false,
40
- isRowHovered = false,
41
- highlightColor,
42
- hasComments = false,
43
- unresolvedCommentCount = 0,
44
- isCopied = false,
45
- compactMode = false,
46
- isPinned = false,
47
- pinSide,
48
- leftOffset = 0,
49
- rightOffset = 0,
50
- onClick,
51
- onChange,
52
- onConfirm,
53
- onCancel,
54
- onCopyDown,
55
- onCopyToSelected,
56
- onHighlight,
57
- onAddComment,
58
- onViewComments,
59
- hasSelectedRows = false,
60
- className,
61
- }) => {
30
+ const SpreadsheetCell: React.FC<SpreadsheetCellProps> = ({
31
+ value,
32
+ column,
33
+ row,
34
+ rowIndex,
35
+ rowId,
36
+ isEditable = false,
37
+ isEditing = false,
38
+ isFocused = false,
39
+ isRowSelected = false,
40
+ isRowHovered = false,
41
+ highlightColor,
42
+ hasComments = false,
43
+ unresolvedCommentCount = 0,
44
+ isCopied = false,
45
+ compactMode = false,
46
+ isPinned = false,
47
+ pinSide,
48
+ leftOffset = 0,
49
+ rightOffset = 0,
50
+ onClick,
51
+ onChange,
52
+ onConfirm,
53
+ onCancel,
54
+ onCopyDown,
55
+ onCopyToSelected,
56
+ onHighlight,
57
+ onAddComment,
58
+ onViewComments,
59
+ hasSelectedRows = false,
60
+ className,
61
+ }) => {
62
62
  const [localValue, setLocalValue] = useState(value);
63
63
  const inputRef = useRef<HTMLInputElement>(null);
64
64
  const selectRef = useRef<HTMLSelectElement>(null);
@@ -126,53 +126,53 @@ export const SpreadsheetCell: React.FC<SpreadsheetCellProps> = ({
126
126
  const renderEditInput = () => {
127
127
  if (column.type === 'select' && column.options) {
128
128
  return (
129
- <select
130
- ref={selectRef}
131
- value={localValue ?? ''}
132
- onChange={(e) => {
133
- setLocalValue(e.target.value);
134
- onChange?.(e.target.value);
135
- onConfirm?.();
136
- }}
137
- onKeyDown={handleKeyDown}
138
- onBlur={() => onConfirm?.()}
139
- className={cn(
140
- 'w-full border border-gray-300 rounded text-xs focus:outline-none focus:ring-1 focus:ring-blue-500',
141
- compactMode ? 'px-1 py-0.5' : 'px-2 py-1'
142
- )}
143
- >
144
- {column.options.map((option) => (
145
- <option key={option} value={option}>
146
- {option}
147
- </option>
148
- ))}
149
- </select>
150
- );
151
- }
152
-
153
- return (
154
- <input
155
- ref={inputRef}
156
- type={column.type === 'number' ? 'number' : 'text'}
157
- step={column.type === 'number' ? '0.01' : undefined}
129
+ <select
130
+ ref={selectRef}
158
131
  value={localValue ?? ''}
159
132
  onChange={(e) => {
160
- const newValue =
161
- column.type === 'number'
162
- ? e.target.value === ''
163
- ? ''
164
- : parseFloat(e.target.value)
165
- : e.target.value;
166
- setLocalValue(newValue);
167
- onChange?.(newValue);
133
+ setLocalValue(e.target.value);
134
+ onChange?.(e.target.value);
135
+ onConfirm?.();
168
136
  }}
169
137
  onKeyDown={handleKeyDown}
170
138
  onBlur={() => onConfirm?.()}
171
139
  className={cn(
172
- 'w-full border border-gray-300 rounded text-xs focus:outline-none focus:ring-1 focus:ring-blue-500 bg-yellow-50',
173
- compactMode ? 'px-1 py-0.5' : 'px-2 py-1'
140
+ 'w-full border border-gray-300 rounded text-xs focus:outline-none focus:ring-1 focus:ring-blue-500',
141
+ compactMode ? 'px-1 py-0.5' : 'px-2 py-1'
174
142
  )}
175
- />
143
+ >
144
+ {column.options.map((option) => (
145
+ <option key={option} value={option}>
146
+ {option}
147
+ </option>
148
+ ))}
149
+ </select>
150
+ );
151
+ }
152
+
153
+ return (
154
+ <input
155
+ ref={inputRef}
156
+ type={column.type === 'number' ? 'number' : 'text'}
157
+ step={column.type === 'number' ? '0.01' : undefined}
158
+ value={localValue ?? ''}
159
+ onChange={(e) => {
160
+ const newValue =
161
+ column.type === 'number'
162
+ ? e.target.value === ''
163
+ ? ''
164
+ : parseFloat(e.target.value)
165
+ : e.target.value;
166
+ setLocalValue(newValue);
167
+ onChange?.(newValue);
168
+ }}
169
+ onKeyDown={handleKeyDown}
170
+ onBlur={() => onConfirm?.()}
171
+ className={cn(
172
+ 'w-full border border-gray-300 rounded text-xs focus:outline-none focus:ring-1 focus:ring-blue-500 bg-yellow-50',
173
+ compactMode ? 'px-1 py-0.5' : 'px-2 py-1'
174
+ )}
175
+ />
176
176
  );
177
177
  };
178
178
 
@@ -198,136 +198,163 @@ export const SpreadsheetCell: React.FC<SpreadsheetCellProps> = ({
198
198
  }
199
199
 
200
200
  return (
201
- <td
202
- onClick={onClick}
203
- onKeyDown={handleCellKeyDown}
204
- data-cell-id={`${rowId}-${column.id}`}
205
- className={cn(
206
- 'border border-gray-200 text-xs group cursor-pointer transition-colors',
207
- cellPadding,
208
- column.align === 'right' && 'text-right',
209
- column.align === 'center' && 'text-center',
210
- isCopied && 'animate-pulse',
211
- isFocused && 'ring-2 ring-blue-500 ring-inset',
212
- isPinned ? 'z-20' : 'z-0',
213
- className
214
- )}
215
- style={{
216
- backgroundColor: getBackgroundColor(),
217
- minWidth: column.minWidth || column.width,
218
- ...positionStyles,
219
- }}
220
- >
221
- {isEditing ? (
222
- renderEditInput()
223
- ) : (
224
- <div className="flex items-center gap-1 relative">
225
- {/* Main content */}
226
- <div
227
- className={cn(
228
- 'flex-1 truncate',
229
- isEditable &&
230
- 'cursor-text hover:bg-gray-50 px-0.5 rounded min-h-[18px] flex items-center bg-yellow-50/50'
231
- )}
232
- title={String(value ?? '')}
233
- >
234
- {renderContent()}
235
- </div>
201
+ <td
202
+ onClick={onClick}
203
+ onKeyDown={handleCellKeyDown}
204
+ data-cell-id={`${rowId}-${column.id}`}
205
+ className={cn(
206
+ 'border border-gray-200 text-xs group cursor-pointer transition-colors',
207
+ cellPadding,
208
+ column.align === 'right' && 'text-right',
209
+ column.align === 'center' && 'text-center',
210
+ isCopied && 'animate-pulse',
211
+ isFocused && 'ring-2 ring-blue-500 ring-inset',
212
+ isPinned ? 'z-20' : 'z-0',
213
+ className
214
+ )}
215
+ style={{
216
+ backgroundColor: getBackgroundColor(),
217
+ minWidth: column.minWidth || column.width,
218
+ ...positionStyles,
219
+ }}
220
+ >
221
+ {isEditing ? (
222
+ renderEditInput()
223
+ ) : (
224
+ <div className="flex items-center gap-1 relative">
225
+ {/* Main content */}
226
+ <div
227
+ className={cn(
228
+ 'flex-1 truncate',
229
+ isEditable &&
230
+ 'cursor-text hover:bg-gray-50 px-0.5 rounded min-h-[18px] flex items-center bg-yellow-50/50'
231
+ )}
232
+ title={String(value ?? '')}
233
+ >
234
+ {renderContent()}
235
+ </div>
236
236
 
237
- {/* Action buttons - show on hover, except comment indicator which is always visible */}
238
- <div className="flex items-center gap-0.5 shrink-0">
239
- {/* Copy down button - hover only */}
240
- {value !== null && value !== undefined && value !== '' && onCopyDown && (
241
- <button
242
- type="button"
243
- onClick={(e) => {
244
- e.stopPropagation();
245
- onCopyDown();
246
- }}
247
- className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded"
248
- title="Copy value down to rows below"
249
- >
250
- <HiOutlineClipboardCopy className="h-2.5 w-2.5 text-gray-500" />
251
- </button>
252
- )}
237
+ {/* Action buttons - show on hover, except comment indicator which is always visible */}
238
+ <div className="flex items-center gap-0.5 shrink-0">
239
+ {/* Copy down button - hover only */}
240
+ {value !== null && value !== undefined && value !== '' && onCopyDown && (
241
+ <button
242
+ type="button"
243
+ onClick={(e) => {
244
+ e.stopPropagation();
245
+ onCopyDown();
246
+ }}
247
+ className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded"
248
+ title="Copy value down to rows below"
249
+ >
250
+ <HiOutlineClipboardCopy className="h-2.5 w-2.5 text-gray-500" />
251
+ </button>
252
+ )}
253
253
 
254
- {/* Copy to selected button - hover only */}
255
- {hasSelectedRows &&
256
- value !== null &&
257
- value !== undefined &&
258
- value !== '' &&
259
- onCopyToSelected && (
260
- <button
261
- type="button"
262
- onClick={(e) => {
263
- e.stopPropagation();
264
- onCopyToSelected();
265
- }}
266
- className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-green-100 hover:bg-green-200 rounded"
267
- title="Copy to selected rows"
268
- >
269
- <HiOutlineClipboardCheck className="h-2.5 w-2.5 text-green-600" />
270
- </button>
271
- )}
254
+ {/* Copy to selected button - hover only */}
255
+ {hasSelectedRows &&
256
+ value !== null &&
257
+ value !== undefined &&
258
+ value !== '' &&
259
+ onCopyToSelected && (
260
+ <button
261
+ type="button"
262
+ onClick={(e) => {
263
+ e.stopPropagation();
264
+ onCopyToSelected();
265
+ }}
266
+ className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-green-100 hover:bg-green-200 rounded"
267
+ title="Copy to selected rows"
268
+ >
269
+ <HiOutlineClipboardCheck className="h-2.5 w-2.5 text-green-600" />
270
+ </button>
271
+ )}
272
272
 
273
- {/* Highlight button - hover only */}
274
- {onHighlight && (
275
- <button
276
- type="button"
277
- onClick={(e) => {
278
- e.stopPropagation();
279
- onHighlight();
280
- }}
281
- className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded"
282
- title="Highlight cell"
283
- >
284
- <AiFillHighlight
285
- className={cn(
286
- 'h-2.5 w-2.5',
287
- highlightColor ? 'text-amber-500' : 'text-gray-500'
288
- )}
289
- />
290
- </button>
291
- )}
273
+ {/* Highlight button - hover only */}
274
+ {onHighlight && (
275
+ <button
276
+ type="button"
277
+ onClick={(e) => {
278
+ e.stopPropagation();
279
+ onHighlight();
280
+ }}
281
+ className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded"
282
+ title="Highlight cell"
283
+ >
284
+ <AiFillHighlight
285
+ className={cn(
286
+ 'h-2.5 w-2.5',
287
+ highlightColor ? 'text-amber-500' : 'text-gray-500'
288
+ )}
289
+ />
290
+ </button>
291
+ )}
292
292
 
293
- {/* Comment button - always visible when has comments, hover only when adding */}
294
- {hasComments && onViewComments ? (
295
- <button
296
- type="button"
297
- onClick={(e) => {
298
- e.stopPropagation();
299
- onViewComments();
300
- }}
301
- className="p-0.5 bg-amber-100 hover:bg-amber-200 rounded transition-colors flex items-center gap-0.5"
302
- title={`${unresolvedCommentCount} comment(s) - click to view`}
303
- >
304
- <FaComment className="h-2.5 w-2.5 text-amber-500" />
305
- {unresolvedCommentCount > 0 && (
306
- <span className="text-[9px] font-medium text-amber-600">
293
+ {/* Comment button - always visible when has comments, hover only when adding */}
294
+ {hasComments && onViewComments ? (
295
+ <button
296
+ type="button"
297
+ onClick={(e) => {
298
+ e.stopPropagation();
299
+ onViewComments();
300
+ }}
301
+ className="p-0.5 bg-amber-100 hover:bg-amber-200 rounded transition-colors flex items-center gap-0.5"
302
+ title={`${unresolvedCommentCount} comment(s) - click to view`}
303
+ >
304
+ <FaComment className="h-2.5 w-2.5 text-amber-500" />
305
+ {unresolvedCommentCount > 0 && (
306
+ <span className="text-[9px] font-medium text-amber-600">
307
307
  {unresolvedCommentCount > 99
308
- ? '99+'
309
- : unresolvedCommentCount}
308
+ ? '99+'
309
+ : unresolvedCommentCount}
310
310
  </span>
311
- )}
312
- </button>
313
- ) : onAddComment ? (
314
- <button
315
- type="button"
316
- onClick={(e) => {
317
- e.stopPropagation();
318
- onAddComment();
319
- }}
320
- className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded"
321
- title="Add comment"
322
- >
323
- <FaRegComment className="h-2.5 w-2.5 text-gray-500" />
324
- </button>
325
- ) : null}
326
- </div>
311
+ )}
312
+ </button>
313
+ ) : onAddComment ? (
314
+ <button
315
+ type="button"
316
+ onClick={(e) => {
317
+ e.stopPropagation();
318
+ onAddComment();
319
+ }}
320
+ className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded"
321
+ title="Add comment"
322
+ >
323
+ <FaRegComment className="h-2.5 w-2.5 text-gray-500" />
324
+ </button>
325
+ ) : null}
327
326
  </div>
328
- )}
329
- </td>
327
+ </div>
328
+ )}
329
+ </td>
330
330
  );
331
331
  };
332
332
 
333
333
  SpreadsheetCell.displayName = 'SpreadsheetCell';
334
+
335
+ /**
336
+ * Memoized SpreadsheetCell to prevent unnecessary re-renders
337
+ * Only re-renders when props that affect this specific cell change
338
+ */
339
+ export const MemoizedSpreadsheetCell = memo(SpreadsheetCell, (prevProps, nextProps) => {
340
+ // Quick bail-out checks for most common changes
341
+ if (prevProps.isEditing !== nextProps.isEditing) return false;
342
+ if (prevProps.isFocused !== nextProps.isFocused) return false;
343
+ if (prevProps.value !== nextProps.value) return false;
344
+ if (prevProps.isRowSelected !== nextProps.isRowSelected) return false;
345
+ if (prevProps.isRowHovered !== nextProps.isRowHovered) return false;
346
+ if (prevProps.highlightColor !== nextProps.highlightColor) return false;
347
+ if (prevProps.hasComments !== nextProps.hasComments) return false;
348
+ if (prevProps.unresolvedCommentCount !== nextProps.unresolvedCommentCount) return false;
349
+ if (prevProps.isCopied !== nextProps.isCopied) return false;
350
+ if (prevProps.isPinned !== nextProps.isPinned) return false;
351
+ if (prevProps.leftOffset !== nextProps.leftOffset) return false;
352
+ if (prevProps.rightOffset !== nextProps.rightOffset) return false;
353
+
354
+ // All relevant props are equal, skip re-render
355
+ return true;
356
+ });
357
+
358
+ MemoizedSpreadsheetCell.displayName = 'MemoizedSpreadsheetCell';
359
+
360
+ export { MemoizedSpreadsheetCell as SpreadsheetCell };
@@ -17,15 +17,13 @@ export interface UseSpreadsheetCommentsReturn {
17
17
  // Add comment modal state
18
18
  commentModalCell: CellPosition | null;
19
19
  setCommentModalCell: (cell: CellPosition | null) => void;
20
- commentText: string;
21
- setCommentText: (text: string) => void;
22
20
 
23
21
  // View comments modal state
24
22
  viewCommentsCell: CellPosition | null;
25
23
  setViewCommentsCell: (cell: CellPosition | null) => void;
26
24
 
27
25
  // Actions
28
- handleAddCellComment: (rowId: string | number, columnId: string) => void;
26
+ handleAddCellComment: (rowId: string | number, columnId: string, text: string) => void;
29
27
  handleToggleCommentResolved: (commentId: string) => void;
30
28
 
31
29
  // Utility
@@ -41,7 +39,6 @@ export function useSpreadsheetComments({
41
39
 
42
40
  // Modal states
43
41
  const [commentModalCell, setCommentModalCell] = useState<CellPosition | null>(null);
44
- const [commentText, setCommentText] = useState('');
45
42
  const [viewCommentsCell, setViewCommentsCell] = useState<CellPosition | null>(null);
46
43
 
47
44
  // Use external comments if provided, otherwise use internal
@@ -75,12 +72,12 @@ export function useSpreadsheetComments({
75
72
 
76
73
  // Add a cell comment
77
74
  const handleAddCellComment = useCallback(
78
- (rowId: string | number, columnId: string) => {
79
- if (!commentText.trim()) return;
75
+ (rowId: string | number, columnId: string, text: string) => {
76
+ if (!text.trim()) return;
80
77
 
81
78
  if (onAddCellComment) {
82
79
  // Controlled mode
83
- onAddCellComment(rowId, columnId, commentText);
80
+ onAddCellComment(rowId, columnId, text);
84
81
  } else {
85
82
  // Uncontrolled mode
86
83
  setCellCommentsInternal((prev) => [
@@ -89,16 +86,15 @@ export function useSpreadsheetComments({
89
86
  id: `comment-${Date.now()}`,
90
87
  rowId,
91
88
  columnId,
92
- text: commentText,
89
+ text,
93
90
  timestamp: new Date(),
94
91
  resolved: false,
95
92
  },
96
93
  ]);
97
94
  }
98
- setCommentText('');
99
95
  setCommentModalCell(null);
100
96
  },
101
- [commentText, onAddCellComment]
97
+ [onAddCellComment]
102
98
  );
103
99
 
104
100
  // Toggle comment resolved status
@@ -117,8 +113,6 @@ export function useSpreadsheetComments({
117
113
  // Add comment modal state
118
114
  commentModalCell,
119
115
  setCommentModalCell,
120
- commentText,
121
- setCommentText,
122
116
 
123
117
  // View comments modal state
124
118
  viewCommentsCell,