@particle-academy/fancy-sheets 0.4.0 → 0.4.1

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.d.cts CHANGED
@@ -130,6 +130,8 @@ interface SpreadsheetContextValue {
130
130
  getColumnWidth: (col: number) => number;
131
131
  isCellSelected: (address: string) => boolean;
132
132
  isCellActive: (address: string) => boolean;
133
+ /** @internal drag-to-select state */
134
+ _isDragging: React.RefObject<boolean>;
133
135
  }
134
136
 
135
137
  interface SpreadsheetGridProps {
package/dist/index.d.ts CHANGED
@@ -130,6 +130,8 @@ interface SpreadsheetContextValue {
130
130
  getColumnWidth: (col: number) => number;
131
131
  isCellSelected: (address: string) => boolean;
132
132
  isCellActive: (address: string) => boolean;
133
+ /** @internal drag-to-select state */
134
+ _isDragging: React.RefObject<boolean>;
133
135
  }
134
136
 
135
137
  interface SpreadsheetGridProps {
package/dist/index.js CHANGED
@@ -1599,9 +1599,10 @@ function ColumnResizeHandle({ colIndex }) {
1599
1599
  }
1600
1600
  ColumnResizeHandle.displayName = "ColumnResizeHandle";
1601
1601
  function ColumnHeaders() {
1602
- const { columnCount, rowCount, rowHeight, getColumnWidth, selection, selectRange } = useSpreadsheet();
1603
- const handleColumnClick = useCallback(
1602
+ const { columnCount, rowCount, rowHeight, getColumnWidth, selection, selectRange, _isDragging } = useSpreadsheet();
1603
+ const handleColumnMouseDown = useCallback(
1604
1604
  (colIdx, e) => {
1605
+ if (e.button !== 0) return;
1605
1606
  if (e.shiftKey) {
1606
1607
  const activeCol = parseAddress(selection.activeCell).col;
1607
1608
  const minCol = Math.min(activeCol, colIdx);
@@ -1610,9 +1611,24 @@ function ColumnHeaders() {
1610
1611
  } else {
1611
1612
  selectRange(toAddress(0, colIdx), toAddress(rowCount - 1, colIdx));
1612
1613
  }
1614
+ _isDragging.current = true;
1613
1615
  },
1614
- [rowCount, selectRange, selection.activeCell]
1616
+ [rowCount, selectRange, selection.activeCell, _isDragging]
1615
1617
  );
1618
+ const handleColumnMouseEnter = useCallback(
1619
+ (colIdx) => {
1620
+ if (_isDragging.current) {
1621
+ const activeCol = parseAddress(selection.activeCell).col;
1622
+ const minCol = Math.min(activeCol, colIdx);
1623
+ const maxCol = Math.max(activeCol, colIdx);
1624
+ selectRange(toAddress(0, minCol), toAddress(rowCount - 1, maxCol));
1625
+ }
1626
+ },
1627
+ [rowCount, selection.activeCell, selectRange, _isDragging]
1628
+ );
1629
+ const handleMouseUp = useCallback(() => {
1630
+ _isDragging.current = false;
1631
+ }, [_isDragging]);
1616
1632
  return /* @__PURE__ */ jsxs(
1617
1633
  "div",
1618
1634
  {
@@ -1632,7 +1648,9 @@ function ColumnHeaders() {
1632
1648
  {
1633
1649
  className: "relative flex shrink-0 cursor-pointer items-center justify-center border-r border-zinc-300 text-[11px] font-medium text-zinc-500 select-none hover:bg-zinc-200 dark:border-zinc-600 dark:text-zinc-400 dark:hover:bg-zinc-700",
1634
1650
  style: { width: getColumnWidth(i), minWidth: getColumnWidth(i) },
1635
- onClick: (e) => handleColumnClick(i, e),
1651
+ onMouseDown: (e) => handleColumnMouseDown(i, e),
1652
+ onMouseEnter: () => handleColumnMouseEnter(i),
1653
+ onMouseUp: handleMouseUp,
1636
1654
  children: [
1637
1655
  columnToLetter(i),
1638
1656
  /* @__PURE__ */ jsx(ColumnResizeHandle, { colIndex: i })
@@ -1646,9 +1664,10 @@ function ColumnHeaders() {
1646
1664
  }
1647
1665
  ColumnHeaders.displayName = "ColumnHeaders";
1648
1666
  function RowHeader({ rowIndex }) {
1649
- const { rowHeight, columnCount, selection, selectRange, extendSelection } = useSpreadsheet();
1650
- const handleClick = useCallback(
1667
+ const { rowHeight, columnCount, selection, selectRange, _isDragging } = useSpreadsheet();
1668
+ const handleMouseDown = useCallback(
1651
1669
  (e) => {
1670
+ if (e.button !== 0) return;
1652
1671
  if (e.shiftKey) {
1653
1672
  const activeRow = parseAddress(selection.activeCell).row;
1654
1673
  const minRow = Math.min(activeRow, rowIndex);
@@ -1657,16 +1676,30 @@ function RowHeader({ rowIndex }) {
1657
1676
  } else {
1658
1677
  selectRange(toAddress(rowIndex, 0), toAddress(rowIndex, columnCount - 1));
1659
1678
  }
1679
+ _isDragging.current = true;
1660
1680
  },
1661
- [rowIndex, columnCount, selectRange, selection.activeCell]
1681
+ [rowIndex, columnCount, selectRange, selection.activeCell, _isDragging]
1662
1682
  );
1683
+ const handleMouseEnter = useCallback(() => {
1684
+ if (_isDragging.current) {
1685
+ const activeRow = parseAddress(selection.activeCell).row;
1686
+ const minRow = Math.min(activeRow, rowIndex);
1687
+ const maxRow = Math.max(activeRow, rowIndex);
1688
+ selectRange(toAddress(minRow, 0), toAddress(maxRow, columnCount - 1));
1689
+ }
1690
+ }, [rowIndex, columnCount, selection.activeCell, selectRange, _isDragging]);
1691
+ const handleMouseUp = useCallback(() => {
1692
+ _isDragging.current = false;
1693
+ }, [_isDragging]);
1663
1694
  return /* @__PURE__ */ jsx(
1664
1695
  "div",
1665
1696
  {
1666
1697
  "data-fancy-sheets-row-header": "",
1667
1698
  className: "flex shrink-0 cursor-pointer items-center justify-center border-r border-b border-zinc-300 bg-zinc-100 text-[11px] font-medium text-zinc-500 select-none hover:bg-zinc-200 dark:border-zinc-600 dark:bg-zinc-800 dark:text-zinc-400 dark:hover:bg-zinc-700",
1668
1699
  style: { width: 48, minWidth: 48, height: rowHeight },
1669
- onClick: handleClick,
1700
+ onMouseDown: handleMouseDown,
1701
+ onMouseEnter: handleMouseEnter,
1702
+ onMouseUp: handleMouseUp,
1670
1703
  children: rowIndex + 1
1671
1704
  }
1672
1705
  );
@@ -1729,7 +1762,8 @@ var Cell = memo(function Cell2({ address, row, col }) {
1729
1762
  rowHeight,
1730
1763
  getColumnWidth,
1731
1764
  isCellSelected,
1732
- isCellActive
1765
+ isCellActive,
1766
+ _isDragging
1733
1767
  } = useSpreadsheet();
1734
1768
  const cell = activeSheet.cells[address];
1735
1769
  const isActive = isCellActive(address);
@@ -1739,6 +1773,7 @@ var Cell = memo(function Cell2({ address, row, col }) {
1739
1773
  const width = getColumnWidth(col);
1740
1774
  const handleMouseDown = useCallback(
1741
1775
  (e) => {
1776
+ if (e.button !== 0) return;
1742
1777
  if (e.shiftKey) {
1743
1778
  extendSelection(address);
1744
1779
  } else if (e.ctrlKey || e.metaKey) {
@@ -1746,9 +1781,18 @@ var Cell = memo(function Cell2({ address, row, col }) {
1746
1781
  } else {
1747
1782
  setSelection(address);
1748
1783
  }
1784
+ _isDragging.current = true;
1749
1785
  },
1750
- [address, setSelection, extendSelection, addSelection]
1786
+ [address, setSelection, extendSelection, addSelection, _isDragging]
1751
1787
  );
1788
+ const handleMouseEnter = useCallback(() => {
1789
+ if (_isDragging.current) {
1790
+ extendSelection(address);
1791
+ }
1792
+ }, [address, extendSelection, _isDragging]);
1793
+ const handleMouseUp = useCallback(() => {
1794
+ _isDragging.current = false;
1795
+ }, [_isDragging]);
1752
1796
  const handleDoubleClick = useCallback(() => {
1753
1797
  if (readOnly) return;
1754
1798
  startEdit();
@@ -1765,12 +1809,14 @@ var Cell = memo(function Cell2({ address, row, col }) {
1765
1809
  "data-active": isActive || void 0,
1766
1810
  role: "gridcell",
1767
1811
  className: cn(
1768
- "relative flex items-center truncate border-r border-b border-zinc-200 bg-white px-1.5 text-[13px] dark:border-zinc-700 dark:bg-zinc-900",
1812
+ "relative flex items-center truncate border-r border-b border-zinc-200 bg-white px-1.5 text-[13px] select-none dark:border-zinc-700 dark:bg-zinc-900",
1769
1813
  isActive && "ring-2 ring-inset ring-blue-500",
1770
1814
  isSelected && !isActive && "bg-blue-50 dark:bg-blue-950/40"
1771
1815
  ),
1772
1816
  style: { width, minWidth: width, height: rowHeight, ...formatStyle },
1773
1817
  onMouseDown: handleMouseDown,
1818
+ onMouseEnter: handleMouseEnter,
1819
+ onMouseUp: handleMouseUp,
1774
1820
  onDoubleClick: handleDoubleClick,
1775
1821
  children: !isEditing && /* @__PURE__ */ jsx("span", { className: "truncate", children: displayValue })
1776
1822
  }
@@ -1912,6 +1958,7 @@ function SpreadsheetGrid({ className }) {
1912
1958
  setCellValue,
1913
1959
  setFrozenRows,
1914
1960
  setFrozenCols,
1961
+ extendSelection,
1915
1962
  undo,
1916
1963
  redo
1917
1964
  } = useSpreadsheet();
@@ -2409,6 +2456,7 @@ function SpreadsheetRoot({
2409
2456
  (address) => state.selection.activeCell === address,
2410
2457
  [state.selection.activeCell]
2411
2458
  );
2459
+ const isDraggingRef = useRef(false);
2412
2460
  const ctx = useMemo(
2413
2461
  () => ({
2414
2462
  workbook: state.workbook,
@@ -2426,7 +2474,8 @@ function SpreadsheetRoot({
2426
2474
  canRedo: state.redoStack.length > 0,
2427
2475
  getColumnWidth,
2428
2476
  isCellSelected,
2429
- isCellActive
2477
+ isCellActive,
2478
+ _isDragging: isDraggingRef
2430
2479
  }),
2431
2480
  [state, activeSheet, columnCount, rowCount, defaultColumnWidth, rowHeight, readOnly, actions, getColumnWidth, isCellSelected, isCellActive]
2432
2481
  );