@xcelsior/ui-spreadsheets 1.0.4 → 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/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/Spreadsheet.tsx
2
- import { useCallback as useCallback6, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef3, useState as useState10 } from "react";
2
+ import { useCallback as useCallback6, useEffect as useEffect6, useMemo as useMemo3, useRef as useRef3, useState as useState11 } from "react";
3
3
 
4
4
  // ../../../node_modules/.pnpm/react-icons@4.12.0_react@18.3.1/node_modules/react-icons/lib/esm/iconBase.js
5
5
  import React2 from "react";
@@ -157,7 +157,7 @@ function cn(...inputs) {
157
157
  }
158
158
 
159
159
  // src/components/SpreadsheetCell.tsx
160
- import { useState, useRef, useEffect } from "react";
160
+ import { useState, useRef, useEffect, memo } from "react";
161
161
  import { jsx, jsxs } from "react/jsx-runtime";
162
162
  var cellPaddingCompact = "px-1.5 py-0.5";
163
163
  var cellPaddingNormal = "px-2 py-1";
@@ -335,31 +335,7 @@ var SpreadsheetCell = ({
335
335
  children: renderContent()
336
336
  }
337
337
  ),
338
- hasComments && /* @__PURE__ */ jsxs(
339
- "button",
340
- {
341
- type: "button",
342
- onClick: (e) => {
343
- e.stopPropagation();
344
- onViewComments?.();
345
- },
346
- className: "absolute -right-1 p-0.5 hover:bg-gray-100 rounded z-10",
347
- title: `${unresolvedCommentCount} unresolved comment(s)`,
348
- children: [
349
- /* @__PURE__ */ jsx(
350
- FaComment,
351
- {
352
- className: cn(
353
- "h-2.5 w-2.5",
354
- unresolvedCommentCount > 0 ? "text-amber-500" : "text-gray-400"
355
- )
356
- }
357
- ),
358
- unresolvedCommentCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 bg-amber-500 text-white text-[6px] rounded-full w-2.5 h-2.5 flex items-center justify-center", children: unresolvedCommentCount })
359
- ]
360
- }
361
- ),
362
- /* @__PURE__ */ jsxs("div", { className: "opacity-0 group-hover:opacity-100 flex items-center gap-0.5 transition-opacity shrink-0", children: [
338
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [
363
339
  value !== null && value !== void 0 && value !== "" && onCopyDown && /* @__PURE__ */ jsx(
364
340
  "button",
365
341
  {
@@ -368,7 +344,7 @@ var SpreadsheetCell = ({
368
344
  e.stopPropagation();
369
345
  onCopyDown();
370
346
  },
371
- className: "p-0.5 bg-gray-100 hover:bg-gray-200 rounded",
347
+ className: "opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded",
372
348
  title: "Copy value down to rows below",
373
349
  children: /* @__PURE__ */ jsx(HiOutlineClipboardCopy, { className: "h-2.5 w-2.5 text-gray-500" })
374
350
  }
@@ -381,7 +357,7 @@ var SpreadsheetCell = ({
381
357
  e.stopPropagation();
382
358
  onCopyToSelected();
383
359
  },
384
- className: "p-0.5 bg-green-100 hover:bg-green-200 rounded",
360
+ className: "opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-green-100 hover:bg-green-200 rounded",
385
361
  title: "Copy to selected rows",
386
362
  children: /* @__PURE__ */ jsx(HiOutlineClipboardCheck, { className: "h-2.5 w-2.5 text-green-600" })
387
363
  }
@@ -394,20 +370,35 @@ var SpreadsheetCell = ({
394
370
  e.stopPropagation();
395
371
  onHighlight();
396
372
  },
397
- className: "p-0.5 hover:bg-gray-100 rounded",
373
+ className: "opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded",
398
374
  title: "Highlight cell",
399
375
  children: /* @__PURE__ */ jsx(
400
376
  AiFillHighlight,
401
377
  {
402
378
  className: cn(
403
379
  "h-2.5 w-2.5",
404
- highlightColor ? "text-amber-500" : "text-gray-400"
380
+ highlightColor ? "text-amber-500" : "text-gray-500"
405
381
  )
406
382
  }
407
383
  )
408
384
  }
409
385
  ),
410
- onAddComment && /* @__PURE__ */ jsx(
386
+ hasComments && onViewComments ? /* @__PURE__ */ jsxs(
387
+ "button",
388
+ {
389
+ type: "button",
390
+ onClick: (e) => {
391
+ e.stopPropagation();
392
+ onViewComments();
393
+ },
394
+ className: "p-0.5 bg-amber-100 hover:bg-amber-200 rounded transition-colors flex items-center gap-0.5",
395
+ title: `${unresolvedCommentCount} comment(s) - click to view`,
396
+ children: [
397
+ /* @__PURE__ */ jsx(FaComment, { className: "h-2.5 w-2.5 text-amber-500" }),
398
+ unresolvedCommentCount > 0 && /* @__PURE__ */ jsx("span", { className: "text-[9px] font-medium text-amber-600", children: unresolvedCommentCount > 99 ? "99+" : unresolvedCommentCount })
399
+ ]
400
+ }
401
+ ) : onAddComment ? /* @__PURE__ */ jsx(
411
402
  "button",
412
403
  {
413
404
  type: "button",
@@ -415,17 +406,33 @@ var SpreadsheetCell = ({
415
406
  e.stopPropagation();
416
407
  onAddComment();
417
408
  },
418
- className: "p-0.5 hover:bg-gray-100 rounded",
409
+ className: "opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded",
419
410
  title: "Add comment",
420
- children: /* @__PURE__ */ jsx(FaRegComment, { className: "h-2.5 w-2.5 text-gray-400" })
411
+ children: /* @__PURE__ */ jsx(FaRegComment, { className: "h-2.5 w-2.5 text-gray-500" })
421
412
  }
422
- )
413
+ ) : null
423
414
  ] })
424
415
  ] })
425
416
  }
426
417
  );
427
418
  };
428
419
  SpreadsheetCell.displayName = "SpreadsheetCell";
420
+ var MemoizedSpreadsheetCell = memo(SpreadsheetCell, (prevProps, nextProps) => {
421
+ if (prevProps.isEditing !== nextProps.isEditing) return false;
422
+ if (prevProps.isFocused !== nextProps.isFocused) return false;
423
+ if (prevProps.value !== nextProps.value) return false;
424
+ if (prevProps.isRowSelected !== nextProps.isRowSelected) return false;
425
+ if (prevProps.isRowHovered !== nextProps.isRowHovered) return false;
426
+ if (prevProps.highlightColor !== nextProps.highlightColor) return false;
427
+ if (prevProps.hasComments !== nextProps.hasComments) return false;
428
+ if (prevProps.unresolvedCommentCount !== nextProps.unresolvedCommentCount) return false;
429
+ if (prevProps.isCopied !== nextProps.isCopied) return false;
430
+ if (prevProps.isPinned !== nextProps.isPinned) return false;
431
+ if (prevProps.leftOffset !== nextProps.leftOffset) return false;
432
+ if (prevProps.rightOffset !== nextProps.rightOffset) return false;
433
+ return true;
434
+ });
435
+ MemoizedSpreadsheetCell.displayName = "MemoizedSpreadsheetCell";
429
436
 
430
437
  // src/components/SpreadsheetFilterDropdown.tsx
431
438
  import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
@@ -1987,16 +1994,31 @@ var SpreadsheetSettingsModal = ({
1987
1994
  SpreadsheetSettingsModal.displayName = "SpreadsheetSettingsModal";
1988
1995
 
1989
1996
  // src/components/CommentModals.tsx
1997
+ import { useState as useState6, useEffect as useEffect4 } from "react";
1990
1998
  import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1991
1999
  function AddCommentModal({
1992
2000
  isOpen,
1993
- commentText,
1994
2001
  columnLabel,
1995
- onCommentTextChange,
1996
2002
  onAdd,
1997
2003
  onClose
1998
2004
  }) {
2005
+ const [commentText, setCommentText] = useState6("");
2006
+ useEffect4(() => {
2007
+ if (!isOpen) {
2008
+ setCommentText("");
2009
+ }
2010
+ }, [isOpen]);
1999
2011
  if (!isOpen) return null;
2012
+ const handleAdd = () => {
2013
+ if (commentText.trim()) {
2014
+ onAdd(commentText);
2015
+ setCommentText("");
2016
+ }
2017
+ };
2018
+ const handleClose = () => {
2019
+ setCommentText("");
2020
+ onClose();
2021
+ };
2000
2022
  return /* @__PURE__ */ jsx9("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ jsxs9("div", { className: "bg-white rounded-lg shadow-xl p-6 w-96 max-w-full mx-4", children: [
2001
2023
  /* @__PURE__ */ jsxs9("h3", { className: "text-lg font-semibold mb-4", children: [
2002
2024
  "Add Comment",
@@ -2006,9 +2028,10 @@ function AddCommentModal({
2006
2028
  "textarea",
2007
2029
  {
2008
2030
  value: commentText,
2009
- onChange: (e) => onCommentTextChange(e.target.value),
2031
+ onChange: (e) => setCommentText(e.target.value),
2010
2032
  placeholder: "Enter your comment...",
2011
- 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"
2033
+ 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",
2034
+ autoFocus: true
2012
2035
  }
2013
2036
  ),
2014
2037
  /* @__PURE__ */ jsxs9("div", { className: "flex justify-end gap-2 mt-4", children: [
@@ -2016,7 +2039,7 @@ function AddCommentModal({
2016
2039
  "button",
2017
2040
  {
2018
2041
  type: "button",
2019
- onClick: onClose,
2042
+ onClick: handleClose,
2020
2043
  className: "px-4 py-2 text-gray-600 hover:bg-gray-100 rounded-lg transition-colors",
2021
2044
  children: "Cancel"
2022
2045
  }
@@ -2025,7 +2048,7 @@ function AddCommentModal({
2025
2048
  "button",
2026
2049
  {
2027
2050
  type: "button",
2028
- onClick: onAdd,
2051
+ onClick: handleAdd,
2029
2052
  disabled: !commentText.trim(),
2030
2053
  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",
2031
2054
  children: "Add Comment"
@@ -2040,6 +2063,7 @@ function ViewCommentsModal({
2040
2063
  comments,
2041
2064
  columnLabel,
2042
2065
  onToggleResolved,
2066
+ onAddComment,
2043
2067
  onClose
2044
2068
  }) {
2045
2069
  if (!isOpen) return null;
@@ -2092,7 +2116,16 @@ function ViewCommentsModal({
2092
2116
  comment.id
2093
2117
  )),
2094
2118
  comments.length === 0 && /* @__PURE__ */ jsx9("p", { className: "text-center text-gray-500 py-8", children: "No comments for this cell." })
2095
- ] })
2119
+ ] }),
2120
+ onAddComment && /* @__PURE__ */ jsx9("div", { className: "mt-4 pt-4 border-t border-gray-200", children: /* @__PURE__ */ jsx9(
2121
+ "button",
2122
+ {
2123
+ type: "button",
2124
+ onClick: onAddComment,
2125
+ className: "w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center justify-center gap-2",
2126
+ children: /* @__PURE__ */ jsx9("span", { children: "+ Add Comment" })
2127
+ }
2128
+ ) })
2096
2129
  ] }) });
2097
2130
  }
2098
2131
  ViewCommentsModal.displayName = "ViewCommentsModal";
@@ -2152,7 +2185,7 @@ KeyboardShortcutsModal.displayName = "KeyboardShortcutsModal";
2152
2185
  import { Pagination } from "@xcelsior/design-system";
2153
2186
 
2154
2187
  // src/hooks/useSpreadsheetFiltering.ts
2155
- import { useCallback as useCallback3, useMemo as useMemo2, useState as useState6 } from "react";
2188
+ import { useCallback as useCallback3, useMemo as useMemo2, useState as useState7 } from "react";
2156
2189
  import { FilterChain, LazyArray } from "@xcelsior/utils";
2157
2190
  function useSpreadsheetFiltering({
2158
2191
  data,
@@ -2163,13 +2196,13 @@ function useSpreadsheetFiltering({
2163
2196
  controlledFilters,
2164
2197
  controlledSortConfig
2165
2198
  }) {
2166
- const [internalFilters, setInternalFilters] = useState6(
2199
+ const [internalFilters, setInternalFilters] = useState7(
2167
2200
  {}
2168
2201
  );
2169
- const [internalSortConfig, setInternalSortConfig] = useState6(
2202
+ const [internalSortConfig, setInternalSortConfig] = useState7(
2170
2203
  null
2171
2204
  );
2172
- const [activeFilterColumn, setActiveFilterColumn] = useState6(null);
2205
+ const [activeFilterColumn, setActiveFilterColumn] = useState7(null);
2173
2206
  const filters = controlledFilters ?? internalFilters;
2174
2207
  const sortConfig = controlledSortConfig !== void 0 ? controlledSortConfig : internalSortConfig;
2175
2208
  const applyTextCondition = useCallback3(
@@ -2444,15 +2477,14 @@ function useSpreadsheetFiltering({
2444
2477
  }
2445
2478
 
2446
2479
  // src/hooks/useSpreadsheetComments.ts
2447
- import { useCallback as useCallback4, useState as useState7 } from "react";
2480
+ import { useCallback as useCallback4, useState as useState8 } from "react";
2448
2481
  function useSpreadsheetComments({
2449
2482
  externalCellComments,
2450
2483
  onAddCellComment
2451
2484
  } = {}) {
2452
- const [cellCommentsInternal, setCellCommentsInternal] = useState7([]);
2453
- const [commentModalCell, setCommentModalCell] = useState7(null);
2454
- const [commentText, setCommentText] = useState7("");
2455
- const [viewCommentsCell, setViewCommentsCell] = useState7(null);
2485
+ const [cellCommentsInternal, setCellCommentsInternal] = useState8([]);
2486
+ const [commentModalCell, setCommentModalCell] = useState8(null);
2487
+ const [viewCommentsCell, setViewCommentsCell] = useState8(null);
2456
2488
  const cellComments = externalCellComments || cellCommentsInternal;
2457
2489
  const getCellComments = useCallback4(
2458
2490
  (rowId, columnId) => {
@@ -2475,10 +2507,10 @@ function useSpreadsheetComments({
2475
2507
  [cellComments]
2476
2508
  );
2477
2509
  const handleAddCellComment = useCallback4(
2478
- (rowId, columnId) => {
2479
- if (!commentText.trim()) return;
2510
+ (rowId, columnId, text) => {
2511
+ if (!text.trim()) return;
2480
2512
  if (onAddCellComment) {
2481
- onAddCellComment(rowId, columnId, commentText);
2513
+ onAddCellComment(rowId, columnId, text);
2482
2514
  } else {
2483
2515
  setCellCommentsInternal((prev) => [
2484
2516
  ...prev,
@@ -2486,16 +2518,15 @@ function useSpreadsheetComments({
2486
2518
  id: `comment-${Date.now()}`,
2487
2519
  rowId,
2488
2520
  columnId,
2489
- text: commentText,
2521
+ text,
2490
2522
  timestamp: /* @__PURE__ */ new Date(),
2491
2523
  resolved: false
2492
2524
  }
2493
2525
  ]);
2494
2526
  }
2495
- setCommentText("");
2496
2527
  setCommentModalCell(null);
2497
2528
  },
2498
- [commentText, onAddCellComment]
2529
+ [onAddCellComment]
2499
2530
  );
2500
2531
  const handleToggleCommentResolved = useCallback4((commentId) => {
2501
2532
  setCellCommentsInternal(
@@ -2510,8 +2541,6 @@ function useSpreadsheetComments({
2510
2541
  // Add comment modal state
2511
2542
  commentModalCell,
2512
2543
  setCommentModalCell,
2513
- commentText,
2514
- setCommentText,
2515
2544
  // View comments modal state
2516
2545
  viewCommentsCell,
2517
2546
  setViewCommentsCell,
@@ -2524,16 +2553,16 @@ function useSpreadsheetComments({
2524
2553
  }
2525
2554
 
2526
2555
  // src/hooks/useSpreadsheetUndoRedo.ts
2527
- import { useCallback as useCallback5, useState as useState8 } from "react";
2556
+ import { useCallback as useCallback5, useState as useState9 } from "react";
2528
2557
  function useSpreadsheetUndoRedo({
2529
2558
  enabled = true,
2530
2559
  maxStackSize = 50,
2531
2560
  autoSave = true
2532
2561
  }) {
2533
- const [undoStack, setUndoStack] = useState8([]);
2534
- const [redoStack, setRedoStack] = useState8([]);
2535
- const [hasUnsavedChanges, setHasUnsavedChanges] = useState8(false);
2536
- const [saveStatus, setSaveStatus] = useState8("saved");
2562
+ const [undoStack, setUndoStack] = useState9([]);
2563
+ const [redoStack, setRedoStack] = useState9([]);
2564
+ const [hasUnsavedChanges, setHasUnsavedChanges] = useState9(false);
2565
+ const [saveStatus, setSaveStatus] = useState9("saved");
2537
2566
  const pushToUndoStack = useCallback5(
2538
2567
  (snapshot) => {
2539
2568
  if (!enabled) return;
@@ -2623,7 +2652,7 @@ function useSpreadsheetUndoRedo({
2623
2652
  }
2624
2653
 
2625
2654
  // src/hooks/useSpreadsheetKeyboardShortcuts.ts
2626
- import { useEffect as useEffect4, useState as useState9 } from "react";
2655
+ import { useEffect as useEffect5, useState as useState10 } from "react";
2627
2656
  function useSpreadsheetKeyboardShortcuts({
2628
2657
  onUndo,
2629
2658
  onRedo,
@@ -2635,10 +2664,10 @@ function useSpreadsheetKeyboardShortcuts({
2635
2664
  customShortcuts = [],
2636
2665
  enabled = true
2637
2666
  } = {}) {
2638
- const [showKeyboardShortcuts, setShowKeyboardShortcuts] = useState9(false);
2667
+ const [showKeyboardShortcuts, setShowKeyboardShortcuts] = useState10(false);
2639
2668
  const isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPod|iPad/.test(navigator.platform);
2640
2669
  const modifierKey = isMac ? "\u2318" : "Ctrl";
2641
- useEffect4(() => {
2670
+ useEffect5(() => {
2642
2671
  if (!enabled) return;
2643
2672
  const handleKeyDown = (event) => {
2644
2673
  if (event.key === "Escape") {
@@ -2855,8 +2884,6 @@ function Spreadsheet({
2855
2884
  cellHasComments,
2856
2885
  commentModalCell,
2857
2886
  setCommentModalCell,
2858
- commentText,
2859
- setCommentText,
2860
2887
  viewCommentsCell,
2861
2888
  setViewCommentsCell,
2862
2889
  handleAddCellComment,
@@ -2881,15 +2908,15 @@ function Spreadsheet({
2881
2908
  enabled: enableUndoRedo,
2882
2909
  autoSave
2883
2910
  });
2884
- const [selectedRows, setSelectedRows] = useState10(/* @__PURE__ */ new Set());
2885
- const [lastSelectedRow, setLastSelectedRow] = useState10(null);
2886
- const [focusedCell, setFocusedCell] = useState10(null);
2887
- const [editingCell, setEditingCell] = useState10(null);
2888
- const [editValue, setEditValue] = useState10("");
2889
- const [hoveredRow, setHoveredRow] = useState10(null);
2890
- const [internalCurrentPage, setInternalCurrentPage] = useState10(1);
2891
- const [internalPageSize, setInternalPageSize] = useState10(defaultPageSize);
2892
- const [zoom, setZoom] = useState10(defaultZoom);
2911
+ const [selectedRows, setSelectedRows] = useState11(/* @__PURE__ */ new Set());
2912
+ const [lastSelectedRow, setLastSelectedRow] = useState11(null);
2913
+ const [focusedCell, setFocusedCell] = useState11(null);
2914
+ const [editingCell, setEditingCell] = useState11(null);
2915
+ const [editValue, setEditValue] = useState11("");
2916
+ const [hoveredRow, setHoveredRow] = useState11(null);
2917
+ const [internalCurrentPage, setInternalCurrentPage] = useState11(1);
2918
+ const [internalPageSize, setInternalPageSize] = useState11(defaultPageSize);
2919
+ const [zoom, setZoom] = useState11(defaultZoom);
2893
2920
  const currentPage = controlledCurrentPage ?? internalCurrentPage;
2894
2921
  const pageSize = controlledPageSize ?? internalPageSize;
2895
2922
  const handlePageChange = useCallback6(
@@ -2913,8 +2940,8 @@ function Spreadsheet({
2913
2940
  },
2914
2941
  [controlledPageSize, controlledCurrentPage, onPageChange]
2915
2942
  );
2916
- const [showSettingsModal, setShowSettingsModal] = useState10(false);
2917
- const [spreadsheetSettings, setSpreadsheetSettings] = useState10({
2943
+ const [showSettingsModal, setShowSettingsModal] = useState11(false);
2944
+ const [spreadsheetSettings, setSpreadsheetSettings] = useState11({
2918
2945
  defaultPinnedColumns: [],
2919
2946
  defaultSort: null,
2920
2947
  defaultPageSize,
@@ -2925,7 +2952,7 @@ function Spreadsheet({
2925
2952
  pinRowIndex: false,
2926
2953
  rowIndexHighlightColor: void 0
2927
2954
  });
2928
- useEffect5(() => {
2955
+ useEffect6(() => {
2929
2956
  setSpreadsheetSettings((prev) => ({
2930
2957
  ...prev,
2931
2958
  defaultSort: sortConfig
@@ -3053,7 +3080,7 @@ function Spreadsheet({
3053
3080
  const tableRef = useRef3(null);
3054
3081
  const effectiveTotalItems = serverSide ? totalItems ?? data.length : filteredData.length;
3055
3082
  const totalPages = Math.max(1, Math.ceil(effectiveTotalItems / pageSize));
3056
- useEffect5(() => {
3083
+ useEffect6(() => {
3057
3084
  if (!serverSide && currentPage > totalPages) {
3058
3085
  setInternalCurrentPage(1);
3059
3086
  }
@@ -3346,52 +3373,9 @@ function Spreadsheet({
3346
3373
  left: 0
3347
3374
  }
3348
3375
  },
3349
- children: /* @__PURE__ */ jsxs11("div", { className: "relative", children: [
3350
- /* @__PURE__ */ jsx11("div", { className: "py-1 px-1", children: displayIndex }),
3351
- cellHasComments(
3352
- rowId,
3353
- ROW_INDEX_COLUMN_ID
3354
- ) && /* @__PURE__ */ jsxs11(
3355
- "button",
3356
- {
3357
- type: "button",
3358
- onClick: (e) => {
3359
- e.stopPropagation();
3360
- setViewCommentsCell({
3361
- rowId,
3362
- columnId: ROW_INDEX_COLUMN_ID
3363
- });
3364
- },
3365
- style: {
3366
- top: "5px",
3367
- right: "5px"
3368
- },
3369
- className: "absolute p-0.5 hover:bg-gray-100 rounded z-10",
3370
- title: `${getCellUnresolvedCommentCount(rowId, ROW_INDEX_COLUMN_ID)} unresolved comment(s)`,
3371
- children: [
3372
- /* @__PURE__ */ jsx11(
3373
- FaComment,
3374
- {
3375
- className: cn(
3376
- "h-2.5 w-2.5",
3377
- getCellUnresolvedCommentCount(
3378
- rowId,
3379
- ROW_INDEX_COLUMN_ID
3380
- ) > 0 ? "text-amber-500" : "text-gray-400"
3381
- )
3382
- }
3383
- ),
3384
- getCellUnresolvedCommentCount(
3385
- rowId,
3386
- ROW_INDEX_COLUMN_ID
3387
- ) > 0 && /* @__PURE__ */ jsx11("span", { className: "absolute -top-1 -right-1 bg-amber-500 text-white text-[6px] rounded-full w-2.5 h-2.5 flex items-center justify-center", children: getCellUnresolvedCommentCount(
3388
- rowId,
3389
- ROW_INDEX_COLUMN_ID
3390
- ) })
3391
- ]
3392
- }
3393
- ),
3394
- /* @__PURE__ */ jsxs11("div", { className: "absolute inset-x-0 bottom-0 opacity-0 group-hover:opacity-100 flex items-center justify-center gap-0.5 transition-opacity bg-white/90 py-0.5 border-t border-gray-100", children: [
3376
+ children: /* @__PURE__ */ jsxs11("div", { className: "relative flex items-center justify-center", children: [
3377
+ /* @__PURE__ */ jsx11("span", { children: displayIndex }),
3378
+ /* @__PURE__ */ jsxs11("div", { className: "absolute right-0 flex items-center gap-0.5", children: [
3395
3379
  onRowClone && /* @__PURE__ */ jsx11(
3396
3380
  "button",
3397
3381
  {
@@ -3400,7 +3384,7 @@ function Spreadsheet({
3400
3384
  e.stopPropagation();
3401
3385
  handleRowClone(row, rowId);
3402
3386
  },
3403
- className: "p-0.5 hover:bg-gray-200 rounded",
3387
+ className: "opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded",
3404
3388
  title: "Duplicate row",
3405
3389
  children: /* @__PURE__ */ jsx11(HiDuplicate, { className: "h-2.5 w-2.5 text-gray-500" })
3406
3390
  }
@@ -3415,7 +3399,7 @@ function Spreadsheet({
3415
3399
  rowId
3416
3400
  );
3417
3401
  },
3418
- className: "p-0.5 hover:bg-gray-200 rounded",
3402
+ className: "opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded",
3419
3403
  title: "Highlight row",
3420
3404
  children: /* @__PURE__ */ jsx11(
3421
3405
  AiFillHighlight,
@@ -3428,7 +3412,37 @@ function Spreadsheet({
3428
3412
  )
3429
3413
  }
3430
3414
  ),
3431
- enableComments && /* @__PURE__ */ jsx11(
3415
+ enableComments && (cellHasComments(
3416
+ rowId,
3417
+ ROW_INDEX_COLUMN_ID
3418
+ ) ? /* @__PURE__ */ jsxs11(
3419
+ "button",
3420
+ {
3421
+ type: "button",
3422
+ onClick: (e) => {
3423
+ e.stopPropagation();
3424
+ setViewCommentsCell({
3425
+ rowId,
3426
+ columnId: ROW_INDEX_COLUMN_ID
3427
+ });
3428
+ },
3429
+ className: "p-0.5 bg-amber-100 hover:bg-amber-200 rounded transition-colors flex items-center gap-0.5",
3430
+ title: `${getCellUnresolvedCommentCount(rowId, ROW_INDEX_COLUMN_ID)} comment(s) - click to view`,
3431
+ children: [
3432
+ /* @__PURE__ */ jsx11(FaComment, { className: "h-2.5 w-2.5 text-amber-500" }),
3433
+ getCellUnresolvedCommentCount(
3434
+ rowId,
3435
+ ROW_INDEX_COLUMN_ID
3436
+ ) > 0 && /* @__PURE__ */ jsx11("span", { className: "text-[9px] font-medium text-amber-600", children: getCellUnresolvedCommentCount(
3437
+ rowId,
3438
+ ROW_INDEX_COLUMN_ID
3439
+ ) > 99 ? "99+" : getCellUnresolvedCommentCount(
3440
+ rowId,
3441
+ ROW_INDEX_COLUMN_ID
3442
+ ) })
3443
+ ]
3444
+ }
3445
+ ) : /* @__PURE__ */ jsx11(
3432
3446
  "button",
3433
3447
  {
3434
3448
  type: "button",
@@ -3439,11 +3453,11 @@ function Spreadsheet({
3439
3453
  columnId: ROW_INDEX_COLUMN_ID
3440
3454
  });
3441
3455
  },
3442
- className: "p-0.5 hover:bg-gray-200 rounded",
3456
+ className: "opacity-0 group-hover:opacity-100 transition-opacity p-0.5 bg-gray-100 hover:bg-gray-200 rounded",
3443
3457
  title: "Add comment",
3444
3458
  children: /* @__PURE__ */ jsx11(FaRegComment, { className: "h-2.5 w-2.5 text-gray-500" })
3445
3459
  }
3446
- ),
3460
+ )),
3447
3461
  rowActions?.map((action) => {
3448
3462
  if (action.visible && !action.visible(row))
3449
3463
  return null;
@@ -3459,7 +3473,7 @@ function Spreadsheet({
3459
3473
  );
3460
3474
  },
3461
3475
  className: cn(
3462
- "p-0.5 hover:bg-gray-200 rounded",
3476
+ "opacity-0 group-hover:opacity-100 transition-opacity p-0.5 hover:bg-gray-200 rounded",
3463
3477
  action.className
3464
3478
  ),
3465
3479
  title: action.tooltip,
@@ -3480,7 +3494,7 @@ function Spreadsheet({
3480
3494
  const isColPinned = isColumnPinned(column.id);
3481
3495
  const colPinSide = getColumnPinSide(column.id);
3482
3496
  return /* @__PURE__ */ jsx11(
3483
- SpreadsheetCell,
3497
+ MemoizedSpreadsheetCell,
3484
3498
  {
3485
3499
  value: isEditing ? editValue : value,
3486
3500
  column,
@@ -3555,12 +3569,9 @@ function Spreadsheet({
3555
3569
  AddCommentModal,
3556
3570
  {
3557
3571
  isOpen: commentModalCell !== null,
3558
- commentText,
3559
3572
  columnLabel: commentModalCell ? commentModalCell.columnId === ROW_INDEX_COLUMN_ID ? "Row #" : columns.find((c) => c.id === commentModalCell.columnId)?.label : void 0,
3560
- onCommentTextChange: setCommentText,
3561
- onAdd: () => commentModalCell !== null && handleAddCellComment(commentModalCell.rowId, commentModalCell.columnId),
3573
+ onAdd: (text) => commentModalCell !== null && handleAddCellComment(commentModalCell.rowId, commentModalCell.columnId, text),
3562
3574
  onClose: () => {
3563
- setCommentText("");
3564
3575
  setCommentModalCell(null);
3565
3576
  }
3566
3577
  }
@@ -3572,6 +3583,11 @@ function Spreadsheet({
3572
3583
  comments: viewCommentsCell !== null ? getCellComments(viewCommentsCell.rowId, viewCommentsCell.columnId) : [],
3573
3584
  columnLabel: viewCommentsCell ? viewCommentsCell.columnId === ROW_INDEX_COLUMN_ID ? "Row #" : columns.find((c) => c.id === viewCommentsCell.columnId)?.label : void 0,
3574
3585
  onToggleResolved: handleToggleCommentResolved,
3586
+ onAddComment: viewCommentsCell !== null ? () => {
3587
+ const cell = viewCommentsCell;
3588
+ setViewCommentsCell(null);
3589
+ setCommentModalCell(cell);
3590
+ } : void 0,
3575
3591
  onClose: () => setViewCommentsCell(null)
3576
3592
  }
3577
3593
  ),
@@ -3640,7 +3656,7 @@ function Spreadsheet({
3640
3656
  Spreadsheet.displayName = "Spreadsheet";
3641
3657
  export {
3642
3658
  Spreadsheet,
3643
- SpreadsheetCell,
3659
+ MemoizedSpreadsheetCell as SpreadsheetCell,
3644
3660
  SpreadsheetFilterDropdown,
3645
3661
  SpreadsheetHeader,
3646
3662
  SpreadsheetSettingsModal,