simple-table-core 0.1.5 → 0.1.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.
Files changed (47) hide show
  1. package/package.json +5 -1
  2. package/.storybook/main.ts +0 -18
  3. package/.storybook/preview.ts +0 -14
  4. package/assets/table-example.png +0 -0
  5. package/rollup.config.js +0 -27
  6. package/src/components/Animate.tsx +0 -69
  7. package/src/components/SimpleTable/SimpleTable.tsx +0 -165
  8. package/src/components/SimpleTable/TableBody.tsx +0 -79
  9. package/src/components/SimpleTable/TableCell.tsx +0 -51
  10. package/src/components/SimpleTable/TableFooter.tsx +0 -61
  11. package/src/components/SimpleTable/TableHeader.tsx +0 -60
  12. package/src/components/SimpleTable/TableHeaderCell.tsx +0 -129
  13. package/src/components/SimpleTable/TableLastColumnCell.tsx +0 -17
  14. package/src/components/SimpleTable/TableRowSeparator.tsx +0 -5
  15. package/src/consts/SampleData.ts +0 -101
  16. package/src/helpers/calculateBoundingBoxes.ts +0 -29
  17. package/src/helpers/shuffleArray.ts +0 -6
  18. package/src/hooks/usePrevious.ts +0 -15
  19. package/src/hooks/useSelection.ts +0 -106
  20. package/src/hooks/useTableHeaderCell.ts +0 -76
  21. package/src/icons/AngleLeftIcon.tsx +0 -15
  22. package/src/icons/AngleRightIcon.tsx +0 -15
  23. package/src/index.tsx +0 -3
  24. package/src/react-app-env.d.ts +0 -1
  25. package/src/stories/SimpleTable.stories.ts +0 -16
  26. package/src/stories/SimpleTableExample.tsx +0 -17
  27. package/src/stories/assets/accessibility.png +0 -0
  28. package/src/stories/assets/accessibility.svg +0 -1
  29. package/src/stories/assets/addon-library.png +0 -0
  30. package/src/stories/assets/assets.png +0 -0
  31. package/src/stories/assets/avif-test-image.avif +0 -0
  32. package/src/stories/assets/context.png +0 -0
  33. package/src/stories/assets/discord.svg +0 -1
  34. package/src/stories/assets/docs.png +0 -0
  35. package/src/stories/assets/figma-plugin.png +0 -0
  36. package/src/stories/assets/github.svg +0 -1
  37. package/src/stories/assets/share.png +0 -0
  38. package/src/stories/assets/styling.png +0 -0
  39. package/src/stories/assets/testing.png +0 -0
  40. package/src/stories/assets/theming.png +0 -0
  41. package/src/stories/assets/tutorials.svg +0 -1
  42. package/src/stories/assets/youtube.svg +0 -1
  43. package/src/styles/simple-table.css +0 -242
  44. package/src/types/HeaderObject.ts +0 -10
  45. package/src/utils/performanceUtils.ts +0 -17
  46. package/src/utils/sortUtils.ts +0 -30
  47. package/tsconfig.json +0 -22
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "simple-table-core",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "files": [
7
+ "dist"
8
+ ],
5
9
  "dependencies": {
6
10
  "react": "^18.3.1"
7
11
  },
@@ -1,18 +0,0 @@
1
- import type { StorybookConfig } from "@storybook/react-webpack5";
2
-
3
- const config: StorybookConfig = {
4
- stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
5
- addons: [
6
- "@storybook/preset-create-react-app",
7
- "@storybook/addon-onboarding",
8
- "@storybook/addon-links",
9
- "@storybook/addon-essentials",
10
- "@chromatic-com/storybook",
11
- "@storybook/addon-interactions",
12
- ],
13
- framework: {
14
- name: "@storybook/react-webpack5",
15
- options: {},
16
- },
17
- };
18
- export default config;
@@ -1,14 +0,0 @@
1
- import type { Preview } from "@storybook/react";
2
-
3
- const preview: Preview = {
4
- parameters: {
5
- controls: {
6
- matchers: {
7
- color: /(background|color)$/i,
8
- date: /Date$/i,
9
- },
10
- },
11
- },
12
- };
13
-
14
- export default preview;
Binary file
package/rollup.config.js DELETED
@@ -1,27 +0,0 @@
1
- import babel from "@rollup/plugin-babel";
2
- import resolve from "@rollup/plugin-node-resolve";
3
- import postcss from "rollup-plugin-postcss";
4
- import typescript from "@rollup/plugin-typescript";
5
- import { terser } from "rollup-plugin-terser";
6
-
7
- export default {
8
- input: "src/index.tsx",
9
- output: {
10
- file: "dist/index.js",
11
- format: "esm",
12
- },
13
- plugins: [
14
- postcss({
15
- plugins: [],
16
- minimize: true,
17
- }),
18
- babel({
19
- exclude: "node_modules/**",
20
- presets: ["@babel/preset-react"],
21
- }),
22
- resolve(),
23
- typescript(),
24
- terser(),
25
- ],
26
- external: ["react", "react/jsx-runtime"],
27
- };
@@ -1,69 +0,0 @@
1
- import React, { useState, useLayoutEffect, useEffect } from "react";
2
- import usePrevious from "../hooks/usePrevious";
3
- import calculateBoundingBoxes from "../helpers/calculateBoundingBoxes";
4
-
5
- interface AnimateProps {
6
- allowHorizontalAnimate?: boolean;
7
- children: any;
8
- pause?: boolean;
9
- }
10
-
11
- const Animate = ({
12
- allowHorizontalAnimate = true,
13
- children,
14
- pause,
15
- }: AnimateProps) => {
16
- const [boundingBox, setBoundingBox] = useState<any>({});
17
- const [prevBoundingBox, setPrevBoundingBox] = useState<any>({});
18
- const prevChildren = usePrevious(children);
19
-
20
- useLayoutEffect(() => {
21
- const newBoundingBox = calculateBoundingBoxes(children);
22
- setBoundingBox(newBoundingBox);
23
- }, [children]);
24
-
25
- useLayoutEffect(() => {
26
- const prevBoundingBox = calculateBoundingBoxes(prevChildren);
27
- setPrevBoundingBox(prevBoundingBox);
28
- }, [prevChildren]);
29
-
30
- useEffect(() => {
31
- if (pause) return;
32
- const hasPrevBoundingBox = Object.keys(prevBoundingBox).length;
33
-
34
- if (hasPrevBoundingBox) {
35
- React.Children.forEach(children, (child) => {
36
- const domNode = child.ref.current;
37
- const firstBox = prevBoundingBox[child.key];
38
- const lastBox = boundingBox[child.key];
39
-
40
- const changeInX = firstBox.left - lastBox.left;
41
- const changeInY = !allowHorizontalAnimate
42
- ? firstBox.top - lastBox.top
43
- : 0;
44
-
45
- const absoluteChangeInX = Math.abs(changeInX);
46
- const absoluteChangeInY = Math.abs(changeInY);
47
-
48
- if (absoluteChangeInX > 10 || absoluteChangeInY > 10) {
49
- requestAnimationFrame(() => {
50
- // Before the DOM paints, invert child to old position
51
- domNode.style.transform = `translate(${changeInX}px, ${changeInY}px)`;
52
- domNode.style.transition = "transform 0s";
53
-
54
- requestAnimationFrame(() => {
55
- // After the previous frame, remove
56
- // the transition to play the animation
57
- domNode.style.transform = "";
58
- domNode.style.transition = "transform 500ms";
59
- });
60
- });
61
- }
62
- });
63
- }
64
- }, [boundingBox, prevBoundingBox, children, pause, allowHorizontalAnimate]);
65
-
66
- return children;
67
- };
68
-
69
- export default Animate;
@@ -1,165 +0,0 @@
1
- import {
2
- useState,
3
- useRef,
4
- useEffect,
5
- useReducer,
6
- ReactNode,
7
- useMemo,
8
- } from "react";
9
- import useSelection from "../../hooks/useSelection";
10
- import TableHeader from "./TableHeader";
11
- import { onSort } from "../../utils/sortUtils";
12
- import TableBody from "./TableBody";
13
- import HeaderObject from "../../types/HeaderObject";
14
- import TableFooter from "./TableFooter";
15
- import AngleLeftIcon from "../../icons/AngleLeftIcon";
16
- import AngleRightIcon from "../../icons/AngleRightIcon";
17
- import "../../styles/simple-table.css";
18
-
19
- interface SpreadsheetProps {
20
- defaultHeaders: HeaderObject[];
21
- enableColumnResizing?: boolean;
22
- height?: string;
23
- hideFooter?: boolean;
24
- nextIcon?: ReactNode;
25
- prevIcon?: ReactNode;
26
- rows: { [key: string]: string | number | boolean | undefined | null }[];
27
- rowsPerPage?: number;
28
- shouldPaginate?: boolean;
29
- }
30
-
31
- const SimpleTable = ({
32
- defaultHeaders,
33
- enableColumnResizing = true,
34
- height,
35
- hideFooter = false,
36
- nextIcon = <AngleRightIcon />,
37
- prevIcon = <AngleLeftIcon />,
38
- rows,
39
- rowsPerPage = 10,
40
- shouldPaginate = true,
41
- }: SpreadsheetProps) => {
42
- const [isWidthDragging, setIsWidthDragging] = useState(false);
43
- const headersRef = useRef(defaultHeaders);
44
- const [sortedRows, setSortedRows] = useState(rows);
45
- const [sortConfig, setSortConfig] = useState<{
46
- key: HeaderObject;
47
- direction: string;
48
- } | null>(null);
49
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
50
-
51
- const [currentPage, setCurrentPage] = useState(1);
52
-
53
- const tableRef = useRef<HTMLDivElement>(null);
54
-
55
- const shouldDisplayLastColumnCell = useMemo(() => {
56
- if (!tableRef.current) return false;
57
- const totalColumnWidth = headersRef.current.reduce(
58
- (acc, header) => acc + header.width,
59
- 0
60
- );
61
- return totalColumnWidth < tableRef.current.clientWidth;
62
- }, []);
63
-
64
- const {
65
- handleMouseDown,
66
- handleMouseOver,
67
- handleMouseUp,
68
- isSelected,
69
- getBorderClass,
70
- isTopLeftCell,
71
- setSelectedCells,
72
- } = useSelection(sortedRows, headersRef.current);
73
-
74
- const handleSort = (columnIndex: number) => {
75
- const { sortedData, newSortConfig } = onSort(
76
- headersRef.current,
77
- sortedRows,
78
- sortConfig,
79
- columnIndex
80
- );
81
- setSortedRows(sortedData);
82
- setSortConfig(newSortConfig);
83
- };
84
-
85
- const onTableHeaderDragEnd = (newHeaders: HeaderObject[]) => {
86
- headersRef.current = newHeaders;
87
- forceUpdate();
88
- };
89
-
90
- useEffect(() => {
91
- const handleClickOutside = (event: MouseEvent) => {
92
- const target = event.target as HTMLElement;
93
- if (!target.closest(".st-table-cell")) {
94
- setSelectedCells([]);
95
- }
96
- };
97
-
98
- document.addEventListener("mousedown", handleClickOutside);
99
- return () => {
100
- document.removeEventListener("mousedown", handleClickOutside);
101
- };
102
- }, [setSelectedCells]);
103
-
104
- const currentRows = shouldPaginate
105
- ? sortedRows.slice(
106
- (currentPage - 1) * rowsPerPage,
107
- currentPage * rowsPerPage
108
- )
109
- : sortedRows;
110
-
111
- return (
112
- <div
113
- ref={tableRef}
114
- className="st-table-wrapper"
115
- style={height ? { height } : {}}
116
- >
117
- <div
118
- className="st-table"
119
- onMouseUp={handleMouseUp}
120
- onMouseLeave={handleMouseUp}
121
- style={{
122
- gridTemplateColumns: `${headersRef.current
123
- ?.map((header) => `${header.width}px`)
124
- .join(" ")} 1fr`,
125
- }}
126
- >
127
- <TableHeader
128
- enableColumnResizing={enableColumnResizing}
129
- forceUpdate={forceUpdate}
130
- headersRef={headersRef}
131
- isWidthDragging={isWidthDragging}
132
- onSort={handleSort}
133
- onTableHeaderDragEnd={onTableHeaderDragEnd}
134
- setIsWidthDragging={setIsWidthDragging}
135
- shouldDisplayLastColumnCell={shouldDisplayLastColumnCell}
136
- />
137
- <TableBody
138
- getBorderClass={getBorderClass}
139
- handleMouseDown={handleMouseDown}
140
- handleMouseOver={handleMouseOver}
141
- headers={headersRef.current}
142
- isSelected={isSelected}
143
- isTopLeftCell={isTopLeftCell}
144
- isWidthDragging={isWidthDragging}
145
- shouldDisplayLastColumnCell={shouldDisplayLastColumnCell}
146
- shouldPaginate={shouldPaginate}
147
- sortedRows={currentRows}
148
- />
149
- </div>
150
- {shouldPaginate && (
151
- <TableFooter
152
- currentPage={currentPage}
153
- hideFooter={hideFooter}
154
- onPageChange={setCurrentPage}
155
- rowsPerPage={rowsPerPage}
156
- totalRows={sortedRows.length}
157
- nextIcon={nextIcon}
158
- prevIcon={prevIcon}
159
- />
160
- )}
161
- </div>
162
- );
163
- };
164
-
165
- export default SimpleTable;
@@ -1,79 +0,0 @@
1
- import { createRef, Fragment } from "react";
2
- import TableCell from "./TableCell";
3
- import Animate from "../Animate";
4
- import HeaderObject from "../../types/HeaderObject";
5
- import TableLastColumnCell from "./TableLastColumnCell";
6
- import TableRowSeparator from "./TableRowSeparator";
7
-
8
- interface TableBodyProps {
9
- getBorderClass: (rowIndex: number, columnIndex: number) => string;
10
- handleMouseDown: (rowIndex: number, columnIndex: number) => void;
11
- handleMouseOver: (rowIndex: number, columnIndex: number) => void;
12
- headers: HeaderObject[];
13
- isSelected: (rowIndex: number, columnIndex: number) => boolean;
14
- isTopLeftCell: (rowIndex: number, columnIndex: number) => boolean;
15
- isWidthDragging: boolean;
16
- shouldDisplayLastColumnCell: boolean;
17
- shouldPaginate: boolean;
18
- sortedRows: { [key: string]: any }[];
19
- }
20
-
21
- const TableBody = ({
22
- getBorderClass,
23
- handleMouseDown,
24
- handleMouseOver,
25
- headers,
26
- isSelected,
27
- isTopLeftCell,
28
- isWidthDragging,
29
- shouldDisplayLastColumnCell,
30
- shouldPaginate,
31
- sortedRows,
32
- }: TableBodyProps & { shouldDisplayLastColumnCell: boolean }) => {
33
- return (
34
- <>
35
- {sortedRows.map((row, rowIndex) => {
36
- return (
37
- <Fragment key={row.id}>
38
- <Animate
39
- allowHorizontalAnimate={shouldPaginate}
40
- pause={isWidthDragging}
41
- >
42
- {headers.map((header, columnIndex) => {
43
- let content = row[header.accessor];
44
-
45
- if (header.cellRenderer) {
46
- content = header.cellRenderer(row);
47
- }
48
-
49
- return (
50
- <TableCell
51
- borderClass={getBorderClass(rowIndex, columnIndex)}
52
- colIndex={columnIndex}
53
- content={content}
54
- isSelected={isSelected(rowIndex, columnIndex)}
55
- isTopLeftCell={isTopLeftCell(rowIndex, columnIndex)}
56
- key={header.accessor}
57
- onMouseDown={() => handleMouseDown(rowIndex, columnIndex)}
58
- onMouseOver={() => handleMouseOver(rowIndex, columnIndex)}
59
- ref={createRef()}
60
- rowIndex={rowIndex}
61
- isLastRow={rowIndex === sortedRows.length - 1}
62
- />
63
- );
64
- })}
65
- <TableLastColumnCell
66
- isLastRow={rowIndex === sortedRows.length - 1}
67
- ref={createRef()}
68
- visible={shouldDisplayLastColumnCell}
69
- />
70
- </Animate>
71
- {rowIndex !== sortedRows.length - 1 && <TableRowSeparator />}
72
- </Fragment>
73
- );
74
- })}
75
- </>
76
- );
77
- };
78
-
79
- export default TableBody;
@@ -1,51 +0,0 @@
1
- import { forwardRef, LegacyRef } from "react";
2
-
3
- interface TableCellProps {
4
- rowIndex: number;
5
- colIndex: number;
6
- content: any;
7
- isSelected: boolean;
8
- isTopLeftCell: boolean;
9
- borderClass: string;
10
- onMouseDown: (rowIndex: number, colIndex: number) => void;
11
- onMouseOver: (rowIndex: number, colIndex: number) => void;
12
- isLastRow: boolean;
13
- }
14
-
15
- const TableCell = forwardRef(
16
- (
17
- {
18
- rowIndex,
19
- colIndex,
20
- content,
21
- isSelected,
22
- isTopLeftCell,
23
- borderClass,
24
- onMouseDown,
25
- onMouseOver,
26
- isLastRow,
27
- }: TableCellProps,
28
- ref: LegacyRef<HTMLTableCellElement>
29
- ) => {
30
- const isOddRow = rowIndex % 2 === 0;
31
- return (
32
- <div
33
- onMouseDown={() => onMouseDown(rowIndex, colIndex)}
34
- onMouseOver={() => onMouseOver(rowIndex, colIndex)}
35
- ref={ref}
36
- className={`st-table-cell ${
37
- isSelected
38
- ? isTopLeftCell
39
- ? `st-table-cell-selected-first-cell ${borderClass}`
40
- : `st-table-cell-selected ${borderClass}`
41
- : ""
42
- } ${isLastRow ? "st-table-cell-last-row" : ""}
43
- ${isOddRow ? "st-table-cell-odd-row" : ""}`}
44
- >
45
- {content}
46
- </div>
47
- );
48
- }
49
- );
50
-
51
- export default TableCell;
@@ -1,61 +0,0 @@
1
- import { ReactNode } from "react";
2
-
3
- interface TableFooterProps {
4
- currentPage: number;
5
- hideFooter?: boolean;
6
- nextIcon?: ReactNode;
7
- onPageChange: (page: number) => void;
8
- prevIcon?: ReactNode;
9
- rowsPerPage: number;
10
- totalRows: number;
11
- }
12
-
13
- const TableFooter = ({
14
- currentPage,
15
- hideFooter,
16
- nextIcon,
17
- onPageChange,
18
- prevIcon,
19
- rowsPerPage,
20
- totalRows,
21
- }: TableFooterProps) => {
22
- const totalPages = Math.ceil(totalRows / rowsPerPage);
23
-
24
- const handlePageChange = (page: number) => {
25
- if (page >= 1 && page <= totalPages) {
26
- onPageChange(page);
27
- }
28
- };
29
-
30
- if (hideFooter) return null;
31
-
32
- return (
33
- <div className="st-footer">
34
- <button
35
- className="st-next-prev-btn"
36
- onClick={() => handlePageChange(currentPage - 1)}
37
- disabled={currentPage === 1}
38
- >
39
- {prevIcon}
40
- </button>
41
- <button
42
- className="st-next-prev-btn"
43
- onClick={() => handlePageChange(currentPage + 1)}
44
- disabled={currentPage === totalPages}
45
- >
46
- {nextIcon}
47
- </button>
48
- {Array.from({ length: totalPages }, (_, index) => (
49
- <button
50
- key={index}
51
- onClick={() => handlePageChange(index + 1)}
52
- className={`st-page-btn ${currentPage === index + 1 ? "active" : ""}`}
53
- >
54
- {index + 1}
55
- </button>
56
- ))}
57
- </div>
58
- );
59
- };
60
-
61
- export default TableFooter;
@@ -1,60 +0,0 @@
1
- import { createRef, Dispatch, SetStateAction, useRef } from "react";
2
- import Animate from "../Animate";
3
- import TableHeaderCell from "./TableHeaderCell";
4
- import HeaderObject from "../../types/HeaderObject";
5
- import TableLastColumnCell from "./TableLastColumnCell";
6
- import TableRowSeparator from "./TableRowSeparator";
7
-
8
- interface TableHeaderProps {
9
- enableColumnResizing: boolean;
10
- forceUpdate: () => void;
11
- headersRef: React.RefObject<HeaderObject[]>;
12
- isWidthDragging: boolean;
13
- onSort: (columnIndex: number) => void;
14
- onTableHeaderDragEnd: (newHeaders: HeaderObject[]) => void;
15
- setIsWidthDragging: Dispatch<SetStateAction<boolean>>;
16
- shouldDisplayLastColumnCell: boolean;
17
- }
18
-
19
- const TableHeader = ({
20
- enableColumnResizing,
21
- forceUpdate,
22
- headersRef,
23
- isWidthDragging,
24
- onSort,
25
- onTableHeaderDragEnd,
26
- setIsWidthDragging,
27
- shouldDisplayLastColumnCell,
28
- }: TableHeaderProps) => {
29
- const draggedHeaderRef = useRef<HeaderObject | null>(null);
30
- const hoveredHeaderRef = useRef<HeaderObject | null>(null);
31
-
32
- return (
33
- <>
34
- <Animate pause={isWidthDragging}>
35
- {headersRef.current?.map((header, index) => (
36
- <TableHeaderCell
37
- draggedHeaderRef={draggedHeaderRef}
38
- enableColumnResizing={enableColumnResizing}
39
- forceUpdate={forceUpdate}
40
- headersRef={headersRef}
41
- hoveredHeaderRef={hoveredHeaderRef}
42
- index={index}
43
- key={header.accessor}
44
- onSort={onSort}
45
- onTableHeaderDragEnd={onTableHeaderDragEnd}
46
- ref={createRef()}
47
- setIsWidthDragging={setIsWidthDragging}
48
- />
49
- ))}
50
- <TableLastColumnCell
51
- ref={createRef()}
52
- visible={shouldDisplayLastColumnCell}
53
- />
54
- </Animate>
55
- <TableRowSeparator />
56
- </>
57
- );
58
- };
59
-
60
- export default TableHeader;
@@ -1,129 +0,0 @@
1
- import { forwardRef, useRef, SetStateAction, Dispatch, useState } from "react";
2
- import useTableHeaderCell from "../../hooks/useTableHeaderCell";
3
- import { throttle } from "../../utils/performanceUtils";
4
- import HeaderObject from "../../types/HeaderObject";
5
-
6
- interface TableHeaderCellProps {
7
- draggedHeaderRef: React.MutableRefObject<HeaderObject | null>;
8
- enableColumnResizing: boolean;
9
- forceUpdate: () => void;
10
- headersRef: React.RefObject<HeaderObject[]>;
11
- hoveredHeaderRef: React.MutableRefObject<HeaderObject | null>;
12
- index: number;
13
- onSort: (columnIndex: number) => void;
14
- onTableHeaderDragEnd: (newHeaders: HeaderObject[]) => void;
15
- setIsWidthDragging: Dispatch<SetStateAction<boolean>>;
16
- }
17
-
18
- const TableHeaderCell = forwardRef<HTMLDivElement, TableHeaderCellProps>(
19
- (
20
- {
21
- draggedHeaderRef,
22
- enableColumnResizing,
23
- forceUpdate,
24
- headersRef,
25
- hoveredHeaderRef,
26
- index,
27
- onSort,
28
- onTableHeaderDragEnd,
29
- setIsWidthDragging,
30
- },
31
- ref
32
- ) => {
33
- const prevDraggingPosition = useRef({ pageX: 0, pageY: 0 });
34
- const [isDragging, setIsDragging] = useState(false);
35
-
36
- const header = headersRef.current?.[index];
37
-
38
- const { handleDragStart, handleDragOver, handleDragEnd } =
39
- useTableHeaderCell({
40
- draggedHeaderRef,
41
- headersRef,
42
- hoveredHeaderRef,
43
- onTableHeaderDragEnd,
44
- });
45
-
46
- const handleDragStartWrapper = (header: HeaderObject) => {
47
- setIsDragging(true);
48
- handleDragStart(header);
49
- };
50
-
51
- const handleDragEndWrapper = () => {
52
- setIsDragging(false);
53
- handleDragEnd();
54
- };
55
-
56
- // Throttle the handleDragOver function
57
- const throttledHandleDragOver = useRef(
58
- throttle((header: HeaderObject) => {
59
- handleDragOver(header);
60
- }, 100)
61
- ).current;
62
-
63
- const handleResizeStart = (e: React.MouseEvent) => {
64
- setIsWidthDragging(true);
65
- e.preventDefault();
66
- const startX = e.clientX;
67
- if (!header) return;
68
- const startWidth = header.width;
69
-
70
- const throttledMouseMove = throttle((e: MouseEvent) => {
71
- const newWidth = Math.max(startWidth + (e.clientX - startX), 10); // Ensure a minimum width
72
- if (!header) return;
73
- headersRef.current[index].width = newWidth;
74
- forceUpdate();
75
- }, 10); // Adjust the throttle delay as needed
76
-
77
- const handleMouseUp = () => {
78
- document.removeEventListener("mousemove", throttledMouseMove);
79
- document.removeEventListener("mouseup", handleMouseUp);
80
- setIsWidthDragging(false);
81
- };
82
-
83
- document.addEventListener("mousemove", throttledMouseMove);
84
- document.addEventListener("mouseup", handleMouseUp);
85
- };
86
-
87
- if (!header) return null;
88
-
89
- return (
90
- <div
91
- className={`st-table-header-cell ${
92
- header === hoveredHeaderRef.current ? "st-hovered" : ""
93
- } ${isDragging ? "st-dragging" : ""}`}
94
- ref={ref}
95
- style={{ width: header.width }}
96
- >
97
- <div
98
- className="st-table-header-label"
99
- draggable
100
- onClick={() => onSort(index)}
101
- onDragStart={() => handleDragStartWrapper(header)}
102
- onDragOver={(event) => {
103
- const { pageX, pageY } = event;
104
- if (
105
- pageX === prevDraggingPosition.current.pageX &&
106
- pageY === prevDraggingPosition.current.pageY
107
- ) {
108
- return;
109
- }
110
- prevDraggingPosition.current = { pageX, pageY };
111
- event.preventDefault();
112
- throttledHandleDragOver(header, event);
113
- }}
114
- onDragEnd={handleDragEndWrapper}
115
- >
116
- {header?.label}
117
- </div>
118
- {enableColumnResizing && (
119
- <div
120
- className="st-table-header-resize-handle"
121
- onMouseDown={handleResizeStart}
122
- />
123
- )}
124
- </div>
125
- );
126
- }
127
- );
128
-
129
- export default TableHeaderCell;