flexitablesort 1.0.0
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/LICENSE +21 -0
- package/README.md +124 -0
- package/dist/Components/BodyRow.d.ts +9 -0
- package/dist/Components/ColumnCell.d.ts +10 -0
- package/dist/Components/DragHandle.d.ts +8 -0
- package/dist/Components/Draggable.d.ts +11 -0
- package/dist/Components/RowCell.d.ts +12 -0
- package/dist/Components/TableBody.d.ts +8 -0
- package/dist/Components/TableContainer/index.d.ts +23 -0
- package/dist/Components/TableContainer/styles.d.ts +1 -0
- package/dist/Components/TableContainer/useTable.d.ts +89 -0
- package/dist/Components/TableHeader.d.ts +8 -0
- package/dist/Components/index.d.ts +9 -0
- package/dist/Components/utils.d.ts +3 -0
- package/dist/hooks/useAutoScroll.d.ts +14 -0
- package/dist/hooks/useDragContextEvents.d.ts +4 -0
- package/dist/index.cjs.js +15 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +885 -0
- package/package.json +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sami Odeh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# flexitablesort
|
|
2
|
+
|
|
3
|
+
Drag-and-drop row and column reordering for React tables. Smooth animations, auto-scroll, virtual scrolling support, and zero external UI dependencies.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install flexitablesort
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Peer dependencies: `react` and `react-dom` >= 17.0.0
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```jsx
|
|
16
|
+
import {
|
|
17
|
+
TableContainer, TableHeader, ColumnCell,
|
|
18
|
+
TableBody, BodyRow, RowCell,
|
|
19
|
+
} from "flexitablesort";
|
|
20
|
+
|
|
21
|
+
function MyTable() {
|
|
22
|
+
const [rows, setRows] = useState(data);
|
|
23
|
+
const [cols, setCols] = useState(columns);
|
|
24
|
+
|
|
25
|
+
const handleDragEnd = ({ sourceIndex, targetIndex, dragType }) => {
|
|
26
|
+
if (dragType === "row") {
|
|
27
|
+
const next = [...rows];
|
|
28
|
+
const [moved] = next.splice(sourceIndex, 1);
|
|
29
|
+
next.splice(targetIndex, 0, moved);
|
|
30
|
+
setRows(next);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<TableContainer onDragEnd={handleDragEnd}>
|
|
36
|
+
<TableHeader>
|
|
37
|
+
{cols.map((col, i) => (
|
|
38
|
+
<ColumnCell key={col.id} id={col.id} index={i} width={150}>
|
|
39
|
+
{col.title}
|
|
40
|
+
</ColumnCell>
|
|
41
|
+
))}
|
|
42
|
+
</TableHeader>
|
|
43
|
+
<TableBody>
|
|
44
|
+
{rows.map((row, ri) => (
|
|
45
|
+
<BodyRow key={row.id} id={row.id} index={ri}>
|
|
46
|
+
{cols.map((col, ci) => (
|
|
47
|
+
<RowCell key={col.id} index={ci} width={150}>
|
|
48
|
+
{row[col.id]}
|
|
49
|
+
</RowCell>
|
|
50
|
+
))}
|
|
51
|
+
</BodyRow>
|
|
52
|
+
))}
|
|
53
|
+
</TableBody>
|
|
54
|
+
</TableContainer>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Features
|
|
60
|
+
|
|
61
|
+
- **Row & column drag** — reorder independently, automatic direction detection
|
|
62
|
+
- **Smooth animations** — direct DOM transforms, no React re-renders during drag
|
|
63
|
+
- **Auto-scroll** — scrolls when dragging near edges with acceleration
|
|
64
|
+
- **Drag range constraints** — lock specific rows/columns via `options`
|
|
65
|
+
- **DragHandle** — restrict drag to a grip icon instead of the whole row
|
|
66
|
+
- **Virtual scrolling** — works with `@tanstack/react-virtual` for 100k+ rows
|
|
67
|
+
- **Fully styleable** — every component accepts `className` and `style`
|
|
68
|
+
- **Event delegation** — single mousedown listener regardless of row count
|
|
69
|
+
- **TypeScript** — full type definitions included
|
|
70
|
+
|
|
71
|
+
## Components
|
|
72
|
+
|
|
73
|
+
| Component | Description |
|
|
74
|
+
|---|---|
|
|
75
|
+
| `TableContainer` | Root wrapper. Provides drag context. Accepts `onDragEnd`, `options`, `renderPlaceholder`. |
|
|
76
|
+
| `TableHeader` | Header row container. |
|
|
77
|
+
| `ColumnCell` | Draggable column header cell. Requires `id`, `index`. Optional `width`. |
|
|
78
|
+
| `TableBody` | Body container. Pass a `ref` for virtual scrolling. |
|
|
79
|
+
| `BodyRow` | Draggable row. Requires `id`, `index`. |
|
|
80
|
+
| `RowCell` | Cell within a row. Requires `index`. Optional `width`. |
|
|
81
|
+
| `DragHandle` | Wrap inside ColumnCell/BodyRow to restrict drag to this element only. |
|
|
82
|
+
|
|
83
|
+
## Options
|
|
84
|
+
|
|
85
|
+
```jsx
|
|
86
|
+
<TableContainer
|
|
87
|
+
onDragEnd={handleDragEnd}
|
|
88
|
+
options={{
|
|
89
|
+
columnDragRange: { start: 1 }, // column 0 is locked
|
|
90
|
+
rowDragRange: { start: 2, end: 95 }, // rows 0-1 and 96+ are locked
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## DragHandle
|
|
96
|
+
|
|
97
|
+
```jsx
|
|
98
|
+
import { DragHandle } from "flexitablesort";
|
|
99
|
+
|
|
100
|
+
<ColumnCell id={col.id} index={i} width={150}>
|
|
101
|
+
<DragHandle><GripIcon /></DragHandle>
|
|
102
|
+
{col.title}
|
|
103
|
+
</ColumnCell>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
When a `DragHandle` is inside a `ColumnCell` or `BodyRow`, only clicking the handle starts a drag.
|
|
107
|
+
|
|
108
|
+
## Types
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
interface DragEndResult {
|
|
112
|
+
sourceIndex: number;
|
|
113
|
+
targetIndex: number;
|
|
114
|
+
dragType: "row" | "column";
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Browser Support
|
|
119
|
+
|
|
120
|
+
Tested on Chrome, Firefox, and Safari (desktop). Mobile touch events are supported but not extensively tested across devices.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { default as React, CSSProperties, ReactNode } from 'react';
|
|
2
|
+
interface BodyRowProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
style?: CSSProperties;
|
|
5
|
+
className?: string;
|
|
6
|
+
[propName: string]: any;
|
|
7
|
+
}
|
|
8
|
+
declare const BodyRow: React.FC<BodyRowProps>;
|
|
9
|
+
export default BodyRow;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
interface ColumnCellProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
width?: number;
|
|
5
|
+
style?: React.CSSProperties;
|
|
6
|
+
className?: string;
|
|
7
|
+
[propName: string]: any;
|
|
8
|
+
}
|
|
9
|
+
declare const ColumnCell: React.FC<ColumnCellProps>;
|
|
10
|
+
export default ColumnCell;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React, CSSProperties, ReactNode } from 'react';
|
|
2
|
+
export interface DraggableProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
id: number | string;
|
|
5
|
+
index: number;
|
|
6
|
+
type: string;
|
|
7
|
+
styles: CSSProperties;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const Draggable: React.FC<DraggableProps>;
|
|
11
|
+
export default Draggable;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
interface RowCellProps {
|
|
3
|
+
children?: React.ReactNode;
|
|
4
|
+
width?: number;
|
|
5
|
+
index: number;
|
|
6
|
+
isClone?: true;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
className?: string;
|
|
9
|
+
[propName: string]: any;
|
|
10
|
+
}
|
|
11
|
+
declare const RowCell: React.FC<RowCellProps>;
|
|
12
|
+
export default RowCell;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
interface TableBodyProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
style?: React.CSSProperties;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const TableBody: React.ForwardRefExoticComponent<TableBodyProps & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
export default TableBody;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
interface Range {
|
|
3
|
+
start?: number;
|
|
4
|
+
end?: number;
|
|
5
|
+
}
|
|
6
|
+
interface DragEndResult {
|
|
7
|
+
sourceIndex: number;
|
|
8
|
+
targetIndex: number;
|
|
9
|
+
dragType: "row" | "column";
|
|
10
|
+
}
|
|
11
|
+
interface TableProviderProps {
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
className?: string;
|
|
14
|
+
style?: React.CSSProperties;
|
|
15
|
+
onDragEnd?: (result: DragEndResult) => void;
|
|
16
|
+
renderPlaceholder?: () => ReactNode;
|
|
17
|
+
options?: {
|
|
18
|
+
columnDragRange: Range;
|
|
19
|
+
rowDragRange: Range;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
declare const TableProvider: React.ForwardRefExoticComponent<TableProviderProps & React.RefAttributes<HTMLDivElement>>;
|
|
23
|
+
export default TableProvider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const Styles: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Dispatch, ReactElement } from 'react';
|
|
2
|
+
interface DraggedState {
|
|
3
|
+
initial: {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
};
|
|
7
|
+
translate: {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
};
|
|
11
|
+
isDragging: boolean;
|
|
12
|
+
draggedID: string | null;
|
|
13
|
+
targetIndex: number | null;
|
|
14
|
+
sourceIndex: number | null;
|
|
15
|
+
}
|
|
16
|
+
interface RectState {
|
|
17
|
+
draggedItemWidth: number;
|
|
18
|
+
draggedItemHeight: number;
|
|
19
|
+
}
|
|
20
|
+
interface TableDimensions {
|
|
21
|
+
height: number;
|
|
22
|
+
width: number;
|
|
23
|
+
}
|
|
24
|
+
interface Refs {
|
|
25
|
+
tableRef: HTMLDivElement | null;
|
|
26
|
+
bodyRef: HTMLDivElement | null;
|
|
27
|
+
headerRef: HTMLDivElement | null;
|
|
28
|
+
cloneRef: HTMLDivElement | null;
|
|
29
|
+
placeholderRef: HTMLDivElement | null;
|
|
30
|
+
}
|
|
31
|
+
interface DragRange {
|
|
32
|
+
start?: number | undefined;
|
|
33
|
+
end?: number | undefined;
|
|
34
|
+
}
|
|
35
|
+
interface Options {
|
|
36
|
+
columnDragRange: DragRange;
|
|
37
|
+
rowDragRange: DragRange;
|
|
38
|
+
defaultSizing: number;
|
|
39
|
+
}
|
|
40
|
+
interface TableState {
|
|
41
|
+
clone: ReactElement | null;
|
|
42
|
+
dragged: DraggedState;
|
|
43
|
+
dragType: string | null;
|
|
44
|
+
rect: RectState;
|
|
45
|
+
tableDimensions: TableDimensions;
|
|
46
|
+
refs: Refs;
|
|
47
|
+
bodyScrollBarWidth: number;
|
|
48
|
+
options: Options;
|
|
49
|
+
widths: number[];
|
|
50
|
+
columnIds: string[];
|
|
51
|
+
}
|
|
52
|
+
type TableAction = {
|
|
53
|
+
type: "setClone";
|
|
54
|
+
value: ReactElement | null;
|
|
55
|
+
} | {
|
|
56
|
+
type: "setDragged";
|
|
57
|
+
value: Partial<DraggedState>;
|
|
58
|
+
} | {
|
|
59
|
+
type: "setDragType";
|
|
60
|
+
value: string | null;
|
|
61
|
+
} | {
|
|
62
|
+
type: "setRect";
|
|
63
|
+
value: Partial<RectState>;
|
|
64
|
+
} | {
|
|
65
|
+
type: "setTableDimensions";
|
|
66
|
+
value: TableDimensions;
|
|
67
|
+
} | {
|
|
68
|
+
type: "setRefs";
|
|
69
|
+
value: Partial<Refs>;
|
|
70
|
+
} | {
|
|
71
|
+
type: "setBodyScrollBarWidth";
|
|
72
|
+
value: number;
|
|
73
|
+
} | {
|
|
74
|
+
type: "setOptions";
|
|
75
|
+
value: Partial<Options>;
|
|
76
|
+
} | {
|
|
77
|
+
type: "setWidths";
|
|
78
|
+
value: number[];
|
|
79
|
+
} | {
|
|
80
|
+
type: "setColumnIds";
|
|
81
|
+
value: string[];
|
|
82
|
+
};
|
|
83
|
+
interface TableContextType {
|
|
84
|
+
state: TableState;
|
|
85
|
+
dispatch: Dispatch<TableAction>;
|
|
86
|
+
}
|
|
87
|
+
export declare const TableContext: import('react').Context<TableContextType | undefined>;
|
|
88
|
+
export declare const useTable: () => TableContextType;
|
|
89
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
interface TableHeaderProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
style?: React.CSSProperties;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const TableHeader: React.ForwardRefExoticComponent<TableHeaderProps & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
export default TableHeader;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { default as TableContainer } from './TableContainer';
|
|
2
|
+
import { default as TableHeader } from './TableHeader';
|
|
3
|
+
import { default as ColumnCell } from './ColumnCell';
|
|
4
|
+
import { default as TableBody } from './TableBody';
|
|
5
|
+
import { default as BodyRow } from './BodyRow';
|
|
6
|
+
import { default as RowCell } from './RowCell';
|
|
7
|
+
import { default as DragHandle } from './DragHandle';
|
|
8
|
+
export { useTable } from './TableContainer/useTable';
|
|
9
|
+
export { TableContainer, TableHeader, ColumnCell, TableBody, BodyRow, RowCell, DragHandle };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MutableRefObject } from 'react';
|
|
2
|
+
interface Refs {
|
|
3
|
+
bodyRef: MutableRefObject<HTMLDivElement> | null;
|
|
4
|
+
headerRef: MutableRefObject<HTMLDivElement> | null;
|
|
5
|
+
}
|
|
6
|
+
declare const useAutoScroll: (refs: Refs) => {
|
|
7
|
+
startAutoScroll: (speed: number, ref: HTMLDivElement, dir: "horizontal" | "vertical") => void;
|
|
8
|
+
stopAutoScroll: () => void;
|
|
9
|
+
isAutoScrollingHorizontal: import('react').RefObject<boolean>;
|
|
10
|
+
isAutoScrollingVertical: import('react').RefObject<boolean>;
|
|
11
|
+
BodyScrollHandle: import('react').UIEventHandler<HTMLDivElement>;
|
|
12
|
+
HeaderScrollHandle: import('react').UIEventHandler<HTMLDivElement>;
|
|
13
|
+
};
|
|
14
|
+
export default useAutoScroll;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`react`);c=s(c);let l=require(`styled-components`);l=s(l);let u=require(`react/jsx-runtime`),d=require(`react-dom`),f=require(`classnames`);f=s(f);var p=l.default.div`
|
|
2
|
+
height: 100%;
|
|
3
|
+
|
|
4
|
+
&, & .table, & .header, & .thead, & .body, & .ibody,
|
|
5
|
+
& .draggable, & .tr, & .th, & .td {
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
margin: 0;
|
|
8
|
+
padding: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&.is-dragging, &.is-dragging * {
|
|
12
|
+
user-select: none !important;
|
|
13
|
+
-webkit-user-select: none !important;
|
|
14
|
+
}
|
|
15
|
+
`,m=(0,c.createContext)(void 0),h=()=>{let e=(0,c.useContext)(m);if(e===void 0)throw Error(`useTable must be used within a TableProvider`);return e},g=e=>{let t=(0,c.useRef)(!1),n=(0,c.useRef)(!1),r=(0,c.useRef)(0),i=(0,c.useRef)(null),a=(0,c.useCallback)((e,o,s)=>{let c=s===`vertical`,l=c?o.scrollHeight-o.clientHeight:o.scrollWidth-o.clientWidth;c?o.scrollTop+=e:o.scrollLeft+=e,c&&(o.scrollTop>=l||o.scrollTop<=0)||!c&&(o.scrollLeft>=l||o.scrollLeft<=0)?i.current!==null&&cancelAnimationFrame(i.current):n.current||t.current?(i.current=requestAnimationFrame(()=>a(e+r.current,o,s)),r.current+=e/1e3):i.current!==null&&cancelAnimationFrame(i.current)},[]);return{startAutoScroll:(0,c.useCallback)((e,i,o)=>{let s=o===`vertical`;!n.current&&!t.current&&(s?n.current=!0:t.current=!0,r.current=0,a(e,i,o))},[a]),stopAutoScroll:(0,c.useCallback)(()=>{n.current=!1,t.current=!1,i.current!==null&&cancelAnimationFrame(i.current)},[]),isAutoScrollingHorizontal:t,isAutoScrollingVertical:n,BodyScrollHandle:(0,c.useCallback)(t=>{e.headerRef?.current&&t.currentTarget&&(e.headerRef.current.scrollLeft=t.currentTarget.scrollLeft)},[e]),HeaderScrollHandle:(0,c.useCallback)(t=>{e.bodyRef?.current&&t.currentTarget&&(e.bodyRef.current.scrollLeft=t.currentTarget.scrollLeft)},[e])}},_=(e,t)=>{let n=e,r=0,i=t.length-1;for(;r<i;){let e=Math.floor((r+i)/2),a=t[e];if(a.itemTop<=n&&n<=a.itemBottom)return n<a.itemTop+a.height/2?+a.index:+a.index+1;n<a.itemTop?i=e-1:r=e+1}return+t[r].index},v=(e,t)=>{let n=e,r=0,i=t.length-1;for(;r<i;){let e=Math.floor((r+i)/2),a=t[e];if(a.itemLeft<=n&&n<=a.itemRight)return n<a.itemLeft+a.width/2?+a.index:+a.index+1;n<a.itemLeft?i=e-1:r=e+1}return+t[r].index},y=(e,t,n)=>t!==void 0&&e<t||n!==void 0&&e>n,b=`all 450ms cubic-bezier(0.2, 0, 0, 1)`,x=(e,t,n,r,i,a)=>{let{startAutoScroll:o,stopAutoScroll:s,isAutoScrollingHorizontal:l,isAutoScrollingVertical:u}=g(e),d=(0,c.useRef)(null),f=(0,c.useRef)(null),p=(0,c.useRef)(null),m=(0,c.useRef)({x:0,y:0}),h=(0,c.useRef)(null),y=(0,c.useRef)(null),x=(0,c.useRef)({width:0,height:0}),S=(0,c.useCallback)(()=>{let t=e.bodyRef.current;if(!t)return null;let n=t.scrollTop,r=t.getBoundingClientRect().top,a=t.querySelectorAll(`.draggable[data-type="row"]`),o=[];for(let e=0;e<a.length;e++){let t=a[e];if(t.dataset.index===void 0)continue;let i=t.getBoundingClientRect(),s=i.top-r+n;o.push({height:i.height,itemTop:s,itemBottom:s+i.height,index:t.dataset.index})}let s=i.rowDragRange.start,c=i.rowDragRange.end;return(s||c)&&(o=o.filter(e=>(!s||e.index>=s)&&(!c||e.index<c))),o},[e.bodyRef,i.rowDragRange]),C=(0,c.useCallback)(()=>{let t=e.headerRef.current;if(!t||!t.children[0])return null;let n=Array.from(t.children[0].children).map(e=>{let t=e.getBoundingClientRect();return{left:t.left,width:t.width,itemLeft:t.left,itemRight:t.left+t.width,index:e.dataset.index}}).filter(e=>e.index!==void 0),r=i.columnDragRange?.start,a=i.columnDragRange?.end;return(r!==void 0||a!==void 0)&&(n=n.filter(e=>{let t=+e.index;return(r===void 0||t>=r)&&(a===void 0||t<a)})),n},[e.headerRef,i.columnDragRange]),w=(0,c.useCallback)((t,n,r,i)=>{let a=e.placeholderRef?.current;if(!a||!t){a&&(a.style.display=`none`);return}let o=x.current,s=t.getBoundingClientRect();a.style.display=`block`;let c=n<r;if(i===`row`){let e=c?s.top+s.height-o.height:s.top;a.style.top=`${e}px`,a.style.left=`${s.left}px`,a.style.width=`${s.width}px`,a.style.height=`${o.height}px`}else{let t=(e.tableRef?.current)?.getBoundingClientRect(),n=c?s.left+s.width-o.width:s.left;a.style.top=`${t?.top??s.top}px`,a.style.left=`${n}px`,a.style.width=`${o.width}px`,a.style.height=`${t?.height??s.height}px`}},[e.placeholderRef,e.tableRef]),T=(0,c.useCallback)((t,n,r)=>{if(t===null||n===null)return;let i=x.current,a=null;if(r===`row`){let r=e.bodyRef.current;if(!r)return;let o=r.querySelectorAll(`.draggable[data-type="row"]`);for(let e=0;e<o.length;e++){let r=o[e],s=+r.dataset.index,c=r.firstElementChild;if(!c)continue;let l=``;s>t&&s<=n?l=`translateY(-${i.height}px)`:s<t&&s>=n&&(l=`translateY(${i.height}px)`),c.style.transform=l,c.style.transition=s===t?`none`:b,s===n?(r.setAttribute(`data-drop-target`,`true`),a=r):r.removeAttribute(`data-drop-target`)}}else if(r===`column`){let r=e.headerRef.current;if(r){let e=r.querySelectorAll(`.draggable[data-type="column"]`);for(let r=0;r<e.length;r++){let o=e[r],s=+o.dataset.index,c=o.firstElementChild;if(!c)continue;let l=``;s>t&&s<=n?l=`translateX(-${i.width}px)`:s<t&&s>=n&&(l=`translateX(${i.width}px)`),c.style.transform=l,c.style.transition=s===t?`none`:b,s===n?(o.setAttribute(`data-drop-target`,`true`),a=o):o.removeAttribute(`data-drop-target`)}}let o=e.bodyRef.current;if(o){let e=o.querySelectorAll(`.td[data-col-index]`);for(let r=0;r<e.length;r++){let a=e[r],o=+a.dataset.colIndex,s=``;o>t&&o<=n?s=`translateX(-${i.width}px)`:o<t&&o>=n&&(s=`translateX(${i.width}px)`),a.style.transform=s,a.style.transition=b}}}w(a,t,n,r)},[e.bodyRef,e.headerRef,e.placeholderRef,w]),E=(0,c.useCallback)(()=>{let t=e.placeholderRef?.current;t&&(t.style.display=`none`);let n=e.bodyRef.current;if(n){let e=n.querySelectorAll(`.draggable`);for(let t=0;t<e.length;t++){e[t].removeAttribute(`data-drop-target`);let n=e[t].firstElementChild;n&&(n.style.transform=``,n.style.transition=``)}let t=n.querySelectorAll(`.td[data-col-index]`);for(let e=0;e<t.length;e++)t[e].style.transform=``,t[e].style.transition=``}let r=e.headerRef.current;if(r){let e=r.querySelectorAll(`.draggable`);for(let t=0;t<e.length;t++){e[t].removeAttribute(`data-drop-target`);let n=e[t].firstElementChild;n&&(n.style.transform=``,n.style.transition=``)}}},[e.bodyRef,e.headerRef]),D=(0,c.useCallback)(t=>{if(t.target!==t.currentTarget){let r=!1,i=(e=>{for(;e;){if(e.dataset?.dragHandle===`true`&&(r=!0),e.dataset?.contextid||e.dataset?.disabled===`true`)return null;if(e.dataset?.id)return e;e=e.parentNode}return null})(t.target);if(!i||!r&&i.querySelector(`[data-drag-handle]`))return;let a=i.dataset.id,o=+i.dataset.index,s=i.dataset.type;p.current=s,h.current=o,y.current=null;let c=s===`row`?e.bodyRef.current.scrollLeft:0,l=i.getBoundingClientRect();x.current={width:l.width,height:l.height};let u={x:0,y:0};t.type===`touchstart`?(u.x=t.touches[0].clientX,u.y=t.touches[0].clientY):(u.x=t.clientX-l.left-c,u.y=t.clientY-l.top),m.current=u;let g={x:l.left+c,y:l.top};s===`row`?d.current=S():d.current=C();let _=e.bodyRef.current;_&&(f.current=_.getBoundingClientRect());let v=e.cloneRef?.current;v&&(v.style.transform=`translate(${g.x}px, ${g.y}px)`),requestAnimationFrame(()=>{n({type:`dragStart`,value:{rect:{draggedItemHeight:l.height,draggedItemWidth:l.width},dragged:{initial:u,translate:g,draggedID:a,isDragging:!0,sourceIndex:o},dragType:s}}),requestAnimationFrame(()=>{let t=e.cloneRef?.current,n=e.bodyRef.current;if(t&&n){if(s===`row`)t.scrollLeft=n.scrollLeft;else if(s===`column`){let e=t.querySelector(`.clone-body`);e&&(e.scrollTop=n.scrollTop)}}})})}},[n,e,S,C]),O=(0,c.useCallback)(()=>{let t=y.current,r=h.current,i=p.current;d.current=null,f.current=null;let o=e.cloneRef?.current;o&&(o.style.transform=`translate(0px, 0px)`,o.scrollLeft=0),E(),a&&r!==null&&t!==null&&i&&a({sourceIndex:r,targetIndex:t,dragType:i}),n({type:`dragEnd`,value:{targetIndex:t,sourceIndex:r}}),s(),p.current=null,h.current=null,y.current=null},[n,s,e.cloneRef,E,a]),k=(0,c.useCallback)(()=>{d.current=null,f.current=null;let e=h.current,t=y.current,n=p.current;e!==null&&t!==null&&T(e,t,n)},[T]),A=(0,c.useCallback)(t=>{t.stopPropagation();let n=m.current,i,a;t.type===`touchmove`?(i=t.touches[0].clientX-n.x,a=t.touches[0].clientY-n.y):(i=t.clientX-n.x,a=t.clientY-n.y);let c=e.cloneRef?.current;if(c){c.style.transform=`translate(${i}px, ${a}px)`;let t=e.bodyRef.current;if(t){if(p.current===`row`)c.scrollLeft=t.scrollLeft;else if(p.current===`column`){let e=c.querySelector(`.clone-body`);e&&(e.scrollTop=t.scrollTop)}}}u.current=!1,l.current=!1;let g=e.bodyRef.current;if(!g)return;let{clientY:b,clientX:x}=t,w=f.current;w||(w=g.getBoundingClientRect(),f.current=w);let{top:E,bottom:D,left:O,right:k}=w,A=0,j=p.current||r;if(j===`row`){let e=g.scrollTop,t=w.top,n=d.current;n||(n=S(),d.current=n),n&&n.length>0&&(A=_(b-t+e,n)),b<E+30?(o(-5,g,`vertical`),d.current=null):b>D-30?(o(5,g,`vertical`),d.current=null):s()}else{let e=d.current;e||(e=C(),d.current=e),e&&e.length>0&&(A=v(x,e)),x<O+30?(o(-5,g,`horizontal`),d.current=null):x>k-30?(o(5,g,`horizontal`),d.current=null):s()}A!==y.current&&(y.current=A,requestAnimationFrame(()=>{T(h.current,A,j)}))},[r,l,u,e.bodyRef,e.cloneRef,S,C,o,s,T]),j=(0,c.useCallback)(()=>{d.current=null,f.current=null;let t=e.cloneRef?.current;t&&(t.style.transform=`translate(0px, 0px)`,t.scrollLeft=0),E(),n({type:`dragEnd`,value:{targetIndex:null,sourceIndex:null}}),s(),p.current=null,h.current=null,y.current=null},[n,s,e.cloneRef,E]),M=(0,c.useCallback)(e=>{e.key===`Escape`&&j()},[j]);return(0,c.useEffect)(()=>{if(t.isDragging){let t=e.bodyRef.current;return window.addEventListener(`mousemove`,A,{passive:!0}),window.addEventListener(`touchmove`,A,!1),window.addEventListener(`touchend`,O,!1),window.addEventListener(`mouseup`,O,!1),window.addEventListener(`keydown`,M),t?.addEventListener(`scroll`,k,{passive:!0}),()=>{window.removeEventListener(`mousemove`,A),window.removeEventListener(`touchmove`,A,!1),window.removeEventListener(`touchend`,O,!1),window.removeEventListener(`mouseup`,O,!1),window.removeEventListener(`keydown`,M),t?.removeEventListener(`scroll`,k)}}},[t.isDragging,A,O,j,M,k,e.bodyRef]),{dragStart:D}},S={columnDragRange:{start:void 0,end:void 0},rowDragRange:{start:void 0,end:void 0},defaultSizing:50};function C(e,t){switch(t.type){case`setClone`:return{...e,clone:t.value};case`setDragged`:return{...e,dragged:{...e.dragged,...t.value}};case`setDragType`:return{...e,dragType:t.value};case`setRect`:return{...e,rect:t.value};case`setTableDimensions`:return{...e,tableDimensions:t.value};case`setTableRef`:return{...e,refs:{...e.refs,tableRef:t.value}};case`setBodyRef`:return{...e,refs:{...e.refs,bodyRef:t.value}};case`setHeaderRef`:return{...e,refs:{...e.refs,headerRef:t.value}};case`setCloneRef`:return{...e,refs:{...e.refs,cloneRef:t.value}};case`setPlaceholderRef`:return{...e,refs:{...e.refs,placeholderRef:t.value}};case`setBodyScrollBarWidth`:return{...e,bodyScrollBarWidth:t.value};case`setWidths`:return{...e,widths:t.value};case`setColumnIds`:return{...e,columnIds:t.value};case`setOptions`:return{...e,options:t.value??S};case`dragStart`:return{...e,rect:t.value.rect,dragged:{...e.dragged,...t.value.dragged},dragType:t.value.dragType};case`dragEnd`:return{...e,clone:null,dragged:{initial:{x:0,y:0},translate:{x:0,y:0},isDragging:!1,draggedID:null,targetIndex:t.value?.targetIndex??null,sourceIndex:t.value?.sourceIndex??null},dragType:null,rect:{draggedItemWidth:0,draggedItemHeight:0}};default:throw Error(`Unhandled action type: ${t.type}`)}}var w={clone:null,dragged:{initial:{x:0,y:0},translate:{x:0,y:0},isDragging:!1,draggedID:null,targetIndex:null,sourceIndex:null},dragType:null,rect:{draggedItemWidth:0,draggedItemHeight:0},tableDimensions:{height:0,width:0},refs:{tableRef:null,bodyRef:null,headerRef:null,cloneRef:null,placeholderRef:null},bodyScrollBarWidth:0,options:S,widths:[],columnIds:[]},T={position:`relative`,display:`flex`,flexFlow:`column`},E={position:`fixed`,pointerEvents:`none`,zIndex:3,top:0,left:0,display:`none`},D=(0,c.forwardRef)(({children:e,className:t,style:n,options:r,onDragEnd:i,renderPlaceholder:a},o)=>{let s=(0,c.useRef)(null),l=(0,c.useRef)(null),d=(0,c.useRef)(null);(0,c.useImperativeHandle)(o,()=>s.current,[]);let[f,h]=(0,c.useReducer)(C,w),g=(0,c.useMemo)(()=>({state:f,dispatch:h}),[f]);(0,c.useEffect)(()=>{h({type:`setTableRef`,value:s}),h({type:`setCloneRef`,value:l}),h({type:`setPlaceholderRef`,value:d})},[s]),(0,c.useEffect)(()=>{let e=()=>{s.current&&h({type:`setTableDimensions`,value:{height:s.current.offsetHeight,width:s.current.offsetWidth}})};return e(),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`resize`,e)}},[s]),(0,c.useEffect)(()=>{h({type:`setOptions`,value:r})},[r]);let{dragStart:_}=x(f.refs,f.dragged,h,f.dragType,f.options,i),v=(0,c.useMemo)(()=>({position:`fixed`,zIndex:`5`,pointerEvents:`none`,top:0,left:0,display:`flex`,flexDirection:`column`,height:f.dragType===`row`?f.rect.draggedItemHeight:`${f.tableDimensions.height-20}px`,width:f.dragType===`column`?`${f.rect.draggedItemWidth}px`:`${f.tableDimensions.width-20}px`,overflow:`hidden`,boxShadow:f.dragged.isDragging?`0 0 10px 0 rgba(0, 0, 0, 0.1)`:`none`}),[f.dragType,f.dragged.isDragging,f.rect.draggedItemHeight,f.rect.draggedItemWidth,f.tableDimensions.height,f.tableDimensions.width]);return(0,u.jsx)(m.Provider,{value:g,children:(0,u.jsxs)(p,{className:f.dragged.isDragging?`is-dragging`:``,children:[(0,u.jsx)(`div`,{id:`portalroot`,style:v,ref:l,children:f.clone}),a&&(0,u.jsx)(`div`,{ref:d,style:E,children:a()}),(0,u.jsx)(`div`,{"data-contextid":`context`,ref:s,onMouseDown:_,onTouchStart:_,style:{...T,...n},className:`table ${t??``}`,children:e})]})})});D.displayName=`TableProvider`;var O=(0,c.forwardRef)(({children:e,style:t,className:n},r)=>{let i=(0,c.useRef)(null),a=r||i,{state:o,dispatch:s}=h();(0,c.useEffect)(()=>{s({type:`setHeaderRef`,value:a})},[s,a]);let{HeaderScrollHandle:l}=g(o.refs),d={display:`flex`,flex:`1 0 auto`},f=(0,c.useMemo)(()=>({overflow:`hidden`,display:`flex`,paddingRight:`${o.bodyScrollBarWidth}px`,userSelect:o.dragged.isDragging?`none`:`auto`,...t}),[o.bodyScrollBarWidth,o.dragged.isDragging,t]);return(0,c.useEffect)(()=>{a.current&&s({type:`setWidths`,value:Array.from(a.current.querySelectorAll(`.th`)).map(e=>{let t=e.getAttribute(`data-width`);return t?parseInt(t,10):null})})},[e,s,a]),(0,c.useEffect)(()=>{a.current&&s({type:`setColumnIds`,value:Array.from(a.current.querySelectorAll(`.draggable`)).map(e=>e.getAttribute(`data-id`))})},[e,s,a]),(0,u.jsx)(`div`,{className:`header ${n??``}`,children:(0,u.jsx)(`div`,{className:`thead`,style:f,"data-droppableid":`header`,onScroll:l,ref:a,children:(0,u.jsx)(`div`,{style:d,className:`tr`,children:e})})})});O.displayName=`TableHeader`;var k=(0,c.memo)(({children:e,id:t,index:n,type:r,styles:i={}})=>{let{state:a,dispatch:o}=h(),s=(0,c.useMemo)(()=>String(t)===String(a.dragged.draggedID)&&a.dragged.isDragging,[t,a.dragged.draggedID,a.dragged.isDragging]),l=(0,c.useMemo)(()=>r===`row`?y(n,a.options.rowDragRange.start,a.options.rowDragRange.end):y(n,a.options.columnDragRange.start,a.options.columnDragRange.end),[n,a.options.columnDragRange.end,a.options.columnDragRange.start,a.options.rowDragRange.end,a.options.rowDragRange.start,r]),d=(0,c.useRef)(null),f=(0,c.useRef)(!1);(0,c.useEffect)(()=>{d.current&&(f.current=!!d.current.querySelector(`[data-drag-handle]`))});let p=(0,c.useMemo)(()=>({cursor:s?`-webkit-grabbing`:l||f.current?`auto`:`-webkit-grab`,zIndex:s?2:1,opacity:s?0:1,pointerEvents:s?`none`:`auto`,display:`flex`}),[l,s]),m=t=>{l||requestAnimationFrame(()=>{o({type:`setClone`,value:c.default.cloneElement(e)})})};return(0,u.jsx)(`div`,{className:`draggable`,"data-id":t,"data-index":n,"data-type":r,onMouseDown:m,"data-disabled":l?`true`:`false`,style:i,children:(0,u.jsx)(`div`,{ref:d,style:p,children:e})})});k.displayName=`Draggable`;var A=(0,c.memo)(({children:e,width:t,style:n,className:r,...i})=>{let{state:a}=h(),o=(0,c.useMemo)(()=>t??a.options.defaultSizing,[t,a.options.defaultSizing]),s=(0,c.useMemo)(()=>({width:`${o}px`,flex:`${o} 0 auto`}),[o]);return(0,u.jsx)(k,{...i,styles:s,type:`column`,children:(0,u.jsx)(`div`,{className:`th ${r??``}`,"data-width":t,style:{width:`100%`,...n},children:e})})});A.displayName=`ColumnCell`;var j=(0,c.forwardRef)(({children:e,style:t,className:n},r)=>{let i=(0,c.useRef)(null);(0,c.useImperativeHandle)(r,()=>i.current,[]);let{state:a,dispatch:o}=h(),s=(0,c.useMemo)(()=>{if(a.dragged.sourceIndex===null)return null;let t=e=>{let n=[];return c.default.Children.forEach(e,e=>{c.default.isValidElement(e)&&(e.props.id!==void 0&&e.props.index!==void 0&&e.props.children?n.push(e):e.props.children&&n.push(...t(e.props.children)))}),n};return t(e).map(e=>{let t=c.default.Children.toArray(e.props.children).filter(e=>c.default.isValidElement(e)&&String(e.props.index)===String(a.dragged.sourceIndex)).map(e=>c.default.cloneElement(e,{isClone:!0}));return c.default.cloneElement(e,{...e.props,children:t})})},[e,a.dragged.sourceIndex]);(0,c.useEffect)(()=>{o({type:`setBodyRef`,value:i})},[o,i]);let{BodyScrollHandle:l}=g(a.refs),f=(0,c.useMemo)(()=>({overflowX:`auto`,overflowY:`auto`,flex:1,userSelect:a.dragged.isDragging?`none`:`auto`,...t}),[a.dragged.isDragging,t]);(0,c.useEffect)(()=>{if(i.current){let e=i.current.clientWidth;o({type:`setBodyScrollBarWidth`,value:i.current.offsetWidth-e})}},[o,i]);let p=i.current?.scrollHeight??0;return(0,u.jsxs)(c.default.Fragment,{children:[a.dragType===`column`&&a.refs.cloneRef?.current&&(0,d.createPortal)((0,u.jsx)(`div`,{className:`body clone-body`,"data-droppableid":`body`,style:{overflow:`hidden`,flex:1},children:(0,u.jsx)(`div`,{className:`rbody`,style:{height:p,position:`relative`},children:s})}),a.refs.cloneRef.current),(0,u.jsx)(`div`,{className:`body ${n??``}`,style:M,children:(0,u.jsx)(`div`,{className:`ibody`,style:f,"data-droppableid":`body`,onScroll:l,ref:i,children:e})})]})}),M={display:`flex`,overflow:`hidden`,flex:1};j.displayName=`TableBody`;var N={display:`flex`,flex:`1 0 auto`,minHeight:`24px`},P=(0,c.memo)(({children:e,style:t,className:n,...r})=>{let i=(0,c.useMemo)(()=>t?{...N,...t}:N,[t]),a=(0,f.default)(`tr`,n);return(0,u.jsx)(k,{...r,type:`row`,children:(0,u.jsx)(`div`,{className:a,style:i,children:e})})});P.displayName=`BodyRow`;var F=(0,c.memo)(({children:e,style:t,className:n,isClone:r,...i})=>{let{index:a}=i,{state:o}=h(),s=(0,c.useMemo)(()=>o.columnIds[a]??``,[o.columnIds,a]),l=(0,c.useMemo)(()=>o.widths[a]??o.options.defaultSizing,[o.widths,a,o.options.defaultSizing]),d=(0,c.useMemo)(()=>r?!1:s===o.dragged.draggedID,[r,s,o.dragged.draggedID]),f=(0,c.useMemo)(()=>({display:`inline-flex`,opacity:d?0:1,width:`${l}px`,flex:`${l} 0 auto`,...t}),[d,l,t]);return(0,u.jsx)(`div`,{className:`td ${n??``}`,style:f,"data-col-index":a,children:e})});F.displayName=`RowCell`;var I=(0,c.memo)(({children:e,className:t,style:n})=>(0,u.jsx)(`div`,{"data-drag-handle":`true`,className:t,style:{cursor:`-webkit-grab`,display:`inline-flex`,alignItems:`center`,...n},children:e}));I.displayName=`DragHandle`,exports.BodyRow=P,exports.ColumnCell=A,exports.DragHandle=I,exports.RowCell=F,exports.TableBody=j,exports.TableContainer=D,exports.TableHeader=O,exports.useTable=h;
|
package/dist/index.d.ts
ADDED