@gridkitjs/react 0.1.0 → 0.3.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/dist/index.d.ts +17 -2
- package/dist/index.js +237 -53
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { ColumnDefinition as ColumnDefinition$1, ColumnSizingState, ColumnSizeDefaults, ColumnResizeEvent, ResolvedColumn as ResolvedColumn$1 } from '@gridkitjs/core';
|
|
3
|
+
import { ColumnDefinition as ColumnDefinition$1, ColumnSizingState, ColumnOrderState, ColumnSizeDefaults, ColumnResizeEvent, ColumnOrderEvent, ResolvedColumn as ResolvedColumn$1 } from '@gridkitjs/core';
|
|
4
4
|
export { CellTemplateContext, ColumnResizeEvent, ColumnSizeDefaults, ColumnSizingState } from '@gridkitjs/core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -33,6 +33,11 @@ interface DataGridProps<Row> {
|
|
|
33
33
|
hoverable?: HoverableConfig | undefined;
|
|
34
34
|
/** Whether columns can be dragged wider, unless a column says otherwise. */
|
|
35
35
|
resizableColumns?: boolean | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Whether columns can be dragged into a new position, unless a column says
|
|
38
|
+
* otherwise. Turning it off leaves an order the user already made in place.
|
|
39
|
+
*/
|
|
40
|
+
reorderableColumns?: boolean | undefined;
|
|
36
41
|
/**
|
|
37
42
|
* Whether columns fill the grid's width or sit at their own. Defaults to
|
|
38
43
|
* `"fit"`, under which columns the user has sized keep their width and the
|
|
@@ -41,6 +46,11 @@ interface DataGridProps<Row> {
|
|
|
41
46
|
resizeMode?: ResizeMode | undefined;
|
|
42
47
|
/** Column widths to start from, keyed by column id. Uncontrolled. */
|
|
43
48
|
defaultColumnSizing?: ColumnSizingState | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Column ids in the order to start in. Uncontrolled, and partial: ids it
|
|
51
|
+
* omits keep their position among `columns` and follow those it lists.
|
|
52
|
+
*/
|
|
53
|
+
defaultColumnOrder?: ColumnOrderState | undefined;
|
|
44
54
|
/**
|
|
45
55
|
* Sizes applied to columns that do not set their own — the width they start
|
|
46
56
|
* at and the bounds they may be resized between. Distinct from
|
|
@@ -53,7 +63,12 @@ interface DataGridProps<Row> {
|
|
|
53
63
|
* the one to persist. Auto-fit does not call it; it reports user intent only.
|
|
54
64
|
*/
|
|
55
65
|
onColumnResize?: ((event: ColumnResizeEvent) => void) | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Called once when the user drops a column somewhere new. A drop that leaves
|
|
68
|
+
* the order as it was does not call it.
|
|
69
|
+
*/
|
|
70
|
+
onColumnOrderChange?: ((event: ColumnOrderEvent) => void) | undefined;
|
|
56
71
|
}
|
|
57
|
-
declare function DataGridComponent<Row>({ dataSource, columns, borders, hoverable, resizableColumns, resizeMode, defaultColumnSizing, columnSizeDefaults, onColumnResize, }: DataGridProps<Row>): react.JSX.Element;
|
|
72
|
+
declare function DataGridComponent<Row>({ dataSource, columns, borders, hoverable, resizableColumns, reorderableColumns, resizeMode, defaultColumnSizing, defaultColumnOrder, columnSizeDefaults, onColumnResize, onColumnOrderChange, }: DataGridProps<Row>): react.JSX.Element;
|
|
58
73
|
|
|
59
74
|
export { type ColumnDefinition, DataGridComponent, type DataGridProps, type ResizeMode, type ResolvedColumn };
|
package/dist/index.js
CHANGED
|
@@ -1,59 +1,109 @@
|
|
|
1
1
|
// src/DataGrid/DataGrid.tsx
|
|
2
|
-
import { useMemo, useRef, useState as
|
|
2
|
+
import { useMemo, useRef, useState as useState4 } from "react";
|
|
3
3
|
import {
|
|
4
|
+
applyColumnOrder,
|
|
4
5
|
defineColumnsFromRows,
|
|
5
6
|
fitColumnsToWidth,
|
|
7
|
+
moveColumnBefore,
|
|
6
8
|
resolveColumnWidths,
|
|
7
9
|
totalColumnWidth
|
|
8
10
|
} from "@gridkitjs/core";
|
|
9
11
|
|
|
10
12
|
// src/DataGrid/components/GridHeader.tsx
|
|
13
|
+
import { createPortal } from "react-dom";
|
|
11
14
|
import { KEYBOARD_STEP } from "@gridkitjs/core";
|
|
12
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
16
|
function GridHeader({
|
|
14
17
|
columns,
|
|
15
|
-
resize
|
|
18
|
+
resize,
|
|
19
|
+
drag
|
|
16
20
|
}) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
21
|
+
const { beforeId } = drag.dropTarget ?? {};
|
|
22
|
+
const draggedEntry = columns.find((entry) => entry.id === drag.draggedColumnId) ?? null;
|
|
23
|
+
return /* @__PURE__ */ jsxs("thead", { children: [
|
|
24
|
+
/* @__PURE__ */ jsx("tr", { className: "grid-header", children: columns.map((entry, index) => {
|
|
25
|
+
const { column } = entry;
|
|
26
|
+
const resizing = resize.activeColumnId === entry.id;
|
|
27
|
+
const dragging = drag.draggedColumnId === entry.id;
|
|
28
|
+
const dropBefore = beforeId !== void 0 && beforeId === entry.id;
|
|
29
|
+
const dropAfter = beforeId === null && index === columns.length - 1;
|
|
30
|
+
return /* @__PURE__ */ jsxs(
|
|
31
|
+
"th",
|
|
32
|
+
{
|
|
33
|
+
"data-gridkit-column": entry.id,
|
|
34
|
+
className: [
|
|
35
|
+
"header-cell",
|
|
36
|
+
resizing ? "is-resizing" : "",
|
|
37
|
+
dragging ? "is-dragging" : "",
|
|
38
|
+
dropBefore ? "is-drop-before" : "",
|
|
39
|
+
dropAfter ? "is-drop-after" : "",
|
|
40
|
+
column.wrap?.header ? "is-wrapped" : "",
|
|
41
|
+
column.headerClassName ?? ""
|
|
42
|
+
].filter(Boolean).join(" "),
|
|
43
|
+
...entry.reorderable && {
|
|
44
|
+
tabIndex: 0,
|
|
45
|
+
onPointerDown: (event) => {
|
|
46
|
+
drag.startDrag(entry, event);
|
|
47
|
+
},
|
|
48
|
+
onKeyDown: (event) => {
|
|
49
|
+
if (!event.ctrlKey) return;
|
|
50
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
|
|
51
|
+
return;
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
drag.moveByKeyboard(
|
|
54
|
+
entry,
|
|
55
|
+
event.key === "ArrowLeft" ? -1 : 1
|
|
56
|
+
);
|
|
50
57
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
},
|
|
59
|
+
children: [
|
|
60
|
+
entry.label,
|
|
61
|
+
entry.resizable && /* @__PURE__ */ jsx(
|
|
62
|
+
"span",
|
|
63
|
+
{
|
|
64
|
+
className: "header-resize-handle",
|
|
65
|
+
role: "separator",
|
|
66
|
+
"aria-orientation": "vertical",
|
|
67
|
+
"aria-label": `Resize ${column.field}`,
|
|
68
|
+
tabIndex: 0,
|
|
69
|
+
onPointerDown: (event) => {
|
|
70
|
+
resize.startResize(entry, event);
|
|
71
|
+
},
|
|
72
|
+
onDoubleClick: () => {
|
|
73
|
+
resize.sizeToContent(entry);
|
|
74
|
+
},
|
|
75
|
+
onKeyDown: (event) => {
|
|
76
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
|
|
77
|
+
return;
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
resize.nudge(
|
|
80
|
+
entry,
|
|
81
|
+
event.key === "ArrowLeft" ? -KEYBOARD_STEP : KEYBOARD_STEP
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
entry.id
|
|
89
|
+
);
|
|
90
|
+
}) }),
|
|
91
|
+
draggedEntry !== null && drag.ghostTransform !== null && createPortal(
|
|
92
|
+
/* @__PURE__ */ jsx(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
className: "gridkit-data-grid header-cell drag-ghost",
|
|
96
|
+
style: {
|
|
97
|
+
width: draggedEntry.width,
|
|
98
|
+
transform: drag.ghostTransform
|
|
99
|
+
},
|
|
100
|
+
"aria-hidden": "true",
|
|
101
|
+
children: draggedEntry.label
|
|
102
|
+
}
|
|
103
|
+
),
|
|
104
|
+
document.body
|
|
105
|
+
)
|
|
106
|
+
] });
|
|
57
107
|
}
|
|
58
108
|
|
|
59
109
|
// src/DataGrid/components/GridBody.tsx
|
|
@@ -71,7 +121,12 @@ function GridBody({
|
|
|
71
121
|
"td",
|
|
72
122
|
{
|
|
73
123
|
"data-gridkit-column": id,
|
|
74
|
-
className:
|
|
124
|
+
className: [
|
|
125
|
+
"grid-cell",
|
|
126
|
+
id === activeColumnId ? "is-resizing" : "",
|
|
127
|
+
column.wrap?.cells ? "is-wrapped" : "",
|
|
128
|
+
column.cellClassName ?? ""
|
|
129
|
+
].filter(Boolean).join(" "),
|
|
75
130
|
style: { textAlign: alignment },
|
|
76
131
|
children: column.cellTemplate ? column.cellTemplate({ value, row, rowIndex: index }) : value
|
|
77
132
|
},
|
|
@@ -80,9 +135,113 @@ function GridBody({
|
|
|
80
135
|
}) }, index)) });
|
|
81
136
|
}
|
|
82
137
|
|
|
138
|
+
// src/DataGrid/useColumnDrag.ts
|
|
139
|
+
import { useState } from "react";
|
|
140
|
+
import {
|
|
141
|
+
movesColumn,
|
|
142
|
+
resolveDropBefore
|
|
143
|
+
} from "@gridkitjs/core";
|
|
144
|
+
var DRAG_THRESHOLD = 4;
|
|
145
|
+
function headerAt(x, y) {
|
|
146
|
+
const element = document.elementFromPoint(x, y);
|
|
147
|
+
return element?.closest("th[data-gridkit-column]") ?? null;
|
|
148
|
+
}
|
|
149
|
+
function sideOf(element, x) {
|
|
150
|
+
const rect = element.getBoundingClientRect();
|
|
151
|
+
return x < rect.left + rect.width / 2 ? "before" : "after";
|
|
152
|
+
}
|
|
153
|
+
function useColumnDrag({
|
|
154
|
+
order,
|
|
155
|
+
onDrop
|
|
156
|
+
}) {
|
|
157
|
+
const [draggedColumnId, setDraggedColumnId] = useState(null);
|
|
158
|
+
const [dropTarget, setDropTarget] = useState(null);
|
|
159
|
+
const [ghostTransform, setGhostTransform] = useState(null);
|
|
160
|
+
function startDrag(entry, event) {
|
|
161
|
+
const header = event.currentTarget;
|
|
162
|
+
const { pointerId, clientX: startX } = event;
|
|
163
|
+
const grabX = startX - header.getBoundingClientRect().left;
|
|
164
|
+
let dragging = false;
|
|
165
|
+
let target = null;
|
|
166
|
+
function placeGhost(x, y) {
|
|
167
|
+
setGhostTransform(`translate(${String(x - grabX)}px, ${String(y)}px)`);
|
|
168
|
+
}
|
|
169
|
+
header.setPointerCapture(pointerId);
|
|
170
|
+
function move(moveEvent) {
|
|
171
|
+
const { clientX, clientY } = moveEvent;
|
|
172
|
+
if (!dragging) {
|
|
173
|
+
if (Math.abs(clientX - startX) < DRAG_THRESHOLD) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
dragging = true;
|
|
177
|
+
setDraggedColumnId(entry.id);
|
|
178
|
+
}
|
|
179
|
+
placeGhost(clientX, clientY);
|
|
180
|
+
const over = headerAt(clientX, clientY);
|
|
181
|
+
const overId = over?.getAttribute("data-gridkit-column");
|
|
182
|
+
const beforeId = over && overId ? resolveDropBefore(order, overId, sideOf(over, clientX)) : void 0;
|
|
183
|
+
target = beforeId !== void 0 && movesColumn(order, entry.id, beforeId) ? { kind: "column-order", beforeId } : null;
|
|
184
|
+
setDropTarget(target);
|
|
185
|
+
}
|
|
186
|
+
function stop() {
|
|
187
|
+
header.removeEventListener("pointermove", move);
|
|
188
|
+
header.removeEventListener("pointerup", end);
|
|
189
|
+
header.removeEventListener("pointercancel", cancel);
|
|
190
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
191
|
+
if (header.hasPointerCapture(pointerId)) {
|
|
192
|
+
header.releasePointerCapture(pointerId);
|
|
193
|
+
}
|
|
194
|
+
setGhostTransform(null);
|
|
195
|
+
setDraggedColumnId(null);
|
|
196
|
+
setDropTarget(null);
|
|
197
|
+
}
|
|
198
|
+
function end() {
|
|
199
|
+
const dropped = target;
|
|
200
|
+
stop();
|
|
201
|
+
if (dragging && dropped !== null) {
|
|
202
|
+
onDrop(dropped, entry.id);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function cancel() {
|
|
206
|
+
target = null;
|
|
207
|
+
stop();
|
|
208
|
+
}
|
|
209
|
+
function onKeyDown(keyEvent) {
|
|
210
|
+
if (keyEvent.key === "Escape") {
|
|
211
|
+
cancel();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
header.addEventListener("pointermove", move);
|
|
215
|
+
header.addEventListener("pointerup", end);
|
|
216
|
+
header.addEventListener("pointercancel", cancel);
|
|
217
|
+
window.addEventListener("keydown", onKeyDown);
|
|
218
|
+
}
|
|
219
|
+
function moveByKeyboard(entry, direction) {
|
|
220
|
+
const index = order.indexOf(entry.id);
|
|
221
|
+
if (index === -1) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const targetIndex = direction === -1 ? index - 1 : index + 2;
|
|
225
|
+
if (targetIndex < 0) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
onDrop(
|
|
229
|
+
{ kind: "column-order", beforeId: order[targetIndex] ?? null },
|
|
230
|
+
entry.id
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
draggedColumnId,
|
|
235
|
+
dropTarget,
|
|
236
|
+
ghostTransform,
|
|
237
|
+
startDrag,
|
|
238
|
+
moveByKeyboard
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
83
242
|
// src/DataGrid/useColumnResize.ts
|
|
84
243
|
import {
|
|
85
|
-
useState
|
|
244
|
+
useState as useState2
|
|
86
245
|
} from "react";
|
|
87
246
|
import {
|
|
88
247
|
applyColumnResize,
|
|
@@ -118,7 +277,7 @@ function useColumnResize({
|
|
|
118
277
|
columnSizeDefaults,
|
|
119
278
|
onColumnResize
|
|
120
279
|
}) {
|
|
121
|
-
const [activeColumnId, setActiveColumnId] =
|
|
280
|
+
const [activeColumnId, setActiveColumnId] = useState2(null);
|
|
122
281
|
function commit(base, columnId, width, phase) {
|
|
123
282
|
const next = { ...base, [columnId]: width };
|
|
124
283
|
setSizing(next);
|
|
@@ -211,9 +370,9 @@ function useColumnResize({
|
|
|
211
370
|
}
|
|
212
371
|
|
|
213
372
|
// src/DataGrid/useElementWidth.ts
|
|
214
|
-
import { useLayoutEffect, useState as
|
|
373
|
+
import { useLayoutEffect, useState as useState3 } from "react";
|
|
215
374
|
function useElementWidth(ref, enabled) {
|
|
216
|
-
const [width, setWidth] =
|
|
375
|
+
const [width, setWidth] = useState3(null);
|
|
217
376
|
useLayoutEffect(() => {
|
|
218
377
|
const element = ref.current;
|
|
219
378
|
if (element === null || !enabled) {
|
|
@@ -239,10 +398,13 @@ function DataGridComponent({
|
|
|
239
398
|
borders,
|
|
240
399
|
hoverable,
|
|
241
400
|
resizableColumns = false,
|
|
401
|
+
reorderableColumns = false,
|
|
242
402
|
resizeMode = "fit",
|
|
243
403
|
defaultColumnSizing,
|
|
404
|
+
defaultColumnOrder,
|
|
244
405
|
columnSizeDefaults,
|
|
245
|
-
onColumnResize
|
|
406
|
+
onColumnResize,
|
|
407
|
+
onColumnOrderChange
|
|
246
408
|
}) {
|
|
247
409
|
const hoverRows = hoverable?.rows ?? true;
|
|
248
410
|
const hoverColumns = hoverable?.columns ?? true;
|
|
@@ -250,28 +412,37 @@ function DataGridComponent({
|
|
|
250
412
|
const viewportRef = useRef(null);
|
|
251
413
|
const tableRef = useRef(null);
|
|
252
414
|
const viewportWidth = useElementWidth(viewportRef, resizeMode === "fit");
|
|
253
|
-
const [sizing, setSizing] =
|
|
415
|
+
const [sizing, setSizing] = useState4(
|
|
254
416
|
defaultColumnSizing ?? {}
|
|
255
417
|
);
|
|
418
|
+
const [order, setOrder] = useState4(
|
|
419
|
+
defaultColumnOrder ?? []
|
|
420
|
+
);
|
|
256
421
|
const definedColumns = useMemo(() => {
|
|
257
422
|
if (columns && columns.length !== 0) return columns;
|
|
258
423
|
if (dataSource && dataSource.length > 0)
|
|
259
424
|
return defineColumnsFromRows(dataSource);
|
|
260
425
|
return [];
|
|
261
426
|
}, [columns, dataSource]);
|
|
427
|
+
const orderedColumns = useMemo(
|
|
428
|
+
() => applyColumnOrder(definedColumns, order),
|
|
429
|
+
[definedColumns, order]
|
|
430
|
+
);
|
|
262
431
|
const resolved = useMemo(() => {
|
|
263
|
-
const widths = resolveColumnWidths(
|
|
432
|
+
const widths = resolveColumnWidths(orderedColumns, sizing, {
|
|
264
433
|
sizes: columnSizeDefaults,
|
|
265
|
-
resizable: resizableColumns
|
|
434
|
+
resizable: resizableColumns,
|
|
435
|
+
reorderable: reorderableColumns
|
|
266
436
|
});
|
|
267
437
|
return resizeMode === "fit" && viewportWidth !== null ? fitColumnsToWidth(widths, viewportWidth, columnSizeDefaults) : widths;
|
|
268
438
|
}, [
|
|
269
|
-
|
|
439
|
+
orderedColumns,
|
|
270
440
|
sizing,
|
|
271
441
|
resizeMode,
|
|
272
442
|
viewportWidth,
|
|
273
443
|
columnSizeDefaults,
|
|
274
|
-
resizableColumns
|
|
444
|
+
resizableColumns,
|
|
445
|
+
reorderableColumns
|
|
275
446
|
]);
|
|
276
447
|
const resize = useColumnResize({
|
|
277
448
|
tableRef,
|
|
@@ -280,6 +451,19 @@ function DataGridComponent({
|
|
|
280
451
|
columnSizeDefaults,
|
|
281
452
|
onColumnResize
|
|
282
453
|
});
|
|
454
|
+
const displayedIds = useMemo(
|
|
455
|
+
() => orderedColumns.map((column) => column.id ?? column.field),
|
|
456
|
+
[orderedColumns]
|
|
457
|
+
);
|
|
458
|
+
function handleDrop(target, movedId) {
|
|
459
|
+
const next = moveColumnBefore(displayedIds, movedId, target.beforeId);
|
|
460
|
+
if (next === displayedIds) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
setOrder(next);
|
|
464
|
+
onColumnOrderChange?.({ columnId: movedId, order: next });
|
|
465
|
+
}
|
|
466
|
+
const drag = useColumnDrag({ order: displayedIds, onDrop: handleDrop });
|
|
283
467
|
return /* @__PURE__ */ jsx3("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: /* @__PURE__ */ jsxs2(
|
|
284
468
|
"table",
|
|
285
469
|
{
|
|
@@ -294,7 +478,7 @@ function DataGridComponent({
|
|
|
294
478
|
].filter(Boolean).join(" "),
|
|
295
479
|
children: [
|
|
296
480
|
/* @__PURE__ */ jsx3("colgroup", { children: resolved.map((entry) => /* @__PURE__ */ jsx3("col", { style: { width: entry.width } }, entry.id)) }),
|
|
297
|
-
/* @__PURE__ */ jsx3(GridHeader, { columns: resolved, resize }),
|
|
481
|
+
/* @__PURE__ */ jsx3(GridHeader, { columns: resolved, resize, drag }),
|
|
298
482
|
/* @__PURE__ */ jsx3(
|
|
299
483
|
GridBody,
|
|
300
484
|
{
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/DataGrid/DataGrid.tsx","../src/DataGrid/components/GridHeader.tsx","../src/DataGrid/components/GridBody.tsx","../src/DataGrid/useColumnResize.ts","../src/DataGrid/measureColumnContent.ts","../src/DataGrid/useElementWidth.ts"],"sourcesContent":["import { useMemo, useRef, useState, type ReactNode } from \"react\";\nimport {\n defineColumnsFromRows,\n fitColumnsToWidth,\n resolveColumnWidths,\n totalColumnWidth,\n type ColumnDefinition as CoreColumnDefinition,\n type ResolvedColumn as CoreResolvedColumn,\n type ColumnResizeEvent,\n type ColumnSizeDefaults,\n type ColumnSizingState,\n} from \"@gridkitjs/core\";\nimport GridHeader from \"./components/GridHeader\";\nimport GridBody from \"./components/GridBody\";\nimport useColumnResize from \"./useColumnResize\";\nimport useElementWidth from \"./useElementWidth\";\n\n/**\n * A column whose header and cells may render arbitrary React content.\n * @gridkitjs/core stays framework-agnostic and so leaves that output type open;\n * this is the binding React consumers want, and the one they should import.\n */\nexport type ColumnDefinition<Row> = CoreColumnDefinition<Row, ReactNode>;\n\n/** A column paired with the width it renders at. */\nexport type ResolvedColumn<Row> = CoreResolvedColumn<Row, ReactNode>;\n\nexport type Borders = \"horizontal\" | \"vertical\" | \"all\" | \"none\";\n\n/**\n * How a column's width relates to the grid's.\n *\n * `\"fit\"` keeps the columns filling the grid: the space a column gives up is\n * handed to the others, and the space it takes comes out of them. `\"fixed\"`\n * lets every column keep its own width, so a resize moves one column and\n * nothing else, and the grid scrolls or leaves a gap accordingly.\n */\nexport type ResizeMode = \"fit\" | \"fixed\";\n\nexport interface HoverableConfig {\n rows?: boolean;\n columns?: boolean;\n cells?: boolean;\n}\n\nexport interface DataGridProps<Row> {\n columns?: readonly ColumnDefinition<Row>[] | undefined;\n dataSource?: readonly Row[] | undefined;\n borders?: Borders | undefined;\n hoverable?: HoverableConfig | undefined;\n /** Whether columns can be dragged wider, unless a column says otherwise. */\n resizableColumns?: boolean | undefined;\n /**\n * Whether columns fill the grid's width or sit at their own. Defaults to\n * `\"fit\"`, under which columns the user has sized keep their width and the\n * rest share what is left.\n */\n resizeMode?: ResizeMode | undefined;\n /** Column widths to start from, keyed by column id. Uncontrolled. */\n defaultColumnSizing?: ColumnSizingState | undefined;\n /**\n * Sizes applied to columns that do not set their own — the width they start\n * at and the bounds they may be resized between. Distinct from\n * `defaultColumnSizing`, which sets specific columns' starting widths.\n */\n columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;\n /**\n * Called as the user resizes a column. Fires continuously with\n * `phase: \"move\"` and once on release with `phase: \"end\"` — the latter being\n * the one to persist. Auto-fit does not call it; it reports user intent only.\n */\n onColumnResize?: ((event: ColumnResizeEvent) => void) | undefined;\n}\n\nexport function DataGridComponent<Row>({\n dataSource,\n columns,\n borders,\n hoverable,\n resizableColumns = false,\n resizeMode = \"fit\",\n defaultColumnSizing,\n columnSizeDefaults,\n onColumnResize,\n}: DataGridProps<Row>) {\n const hoverRows = hoverable?.rows ?? true;\n const hoverColumns = hoverable?.columns ?? true;\n const hoverCells = hoverable?.cells ?? true;\n\n const viewportRef = useRef<HTMLDivElement>(null);\n const tableRef = useRef<HTMLTableElement>(null);\n const viewportWidth = useElementWidth(viewportRef, resizeMode === \"fit\");\n const [sizing, setSizing] = useState<ColumnSizingState>(\n defaultColumnSizing ?? {},\n );\n\n const definedColumns = useMemo<readonly ColumnDefinition<Row>[]>(() => {\n if (columns && columns.length !== 0) return columns;\n if (dataSource && dataSource.length > 0)\n return defineColumnsFromRows(dataSource);\n return [];\n }, [columns, dataSource]);\n\n /**\n * Auto-fit is a derivation rather than a write back into `sizing`, so that a\n * `width` set in a column definition is never overwritten and the effect\n * cannot chase its own output. `\"fixed\"` is then simply the absence of it.\n */\n const resolved = useMemo(() => {\n const widths = resolveColumnWidths(definedColumns, sizing, {\n sizes: columnSizeDefaults,\n resizable: resizableColumns,\n });\n return resizeMode === \"fit\" && viewportWidth !== null\n ? fitColumnsToWidth(widths, viewportWidth, columnSizeDefaults)\n : widths;\n }, [\n definedColumns,\n sizing,\n resizeMode,\n viewportWidth,\n columnSizeDefaults,\n resizableColumns,\n ]);\n\n const resize = useColumnResize<Row>({\n tableRef,\n sizing,\n setSizing,\n columnSizeDefaults,\n onColumnResize,\n });\n\n return (\n <div className=\"gridkit-data-grid-viewport\" ref={viewportRef}>\n <table\n ref={tableRef}\n // Widths are only honoured exactly when the table is as wide as its\n // columns; at `100%` the fixed layout redistributes the difference.\n style={{ width: totalColumnWidth(resolved) }}\n className={[\n \"gridkit-data-grid\",\n borders ? `borders-${borders}` : \"\",\n hoverRows ? \"\" : \"no-hover-rows\",\n hoverColumns ? \"\" : \"no-hover-columns\",\n hoverCells ? \"\" : \"no-hover-cells\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n <colgroup>\n {resolved.map((entry) => (\n <col key={entry.id} style={{ width: entry.width }} />\n ))}\n </colgroup>\n <GridHeader<Row> columns={resolved} resize={resize} />\n <GridBody<Row>\n columns={resolved}\n dataSource={dataSource}\n activeColumnId={resize.activeColumnId}\n />\n </table>\n </div>\n );\n}\n","import { KEYBOARD_STEP } from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport type { ColumnResizeApi } from \"../useColumnResize\";\n\ninterface GridHeaderProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n resize: ColumnResizeApi<Row>;\n}\n\nexport default function GridHeader<Row>({\n columns,\n resize,\n}: GridHeaderProps<Row>) {\n return (\n <thead>\n <tr className=\"grid-header\">\n {columns.map((entry) => {\n const { column } = entry;\n const resizing = resize.activeColumnId === entry.id;\n\n return (\n <th\n key={entry.id}\n data-gridkit-column={entry.id}\n className={resizing ? \"header-cell is-resizing\" : \"header-cell\"}\n >\n {entry.label}\n {entry.resizable && (\n <span\n className=\"header-resize-handle\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={`Resize ${column.field}`}\n tabIndex={0}\n onPointerDown={(event) => {\n resize.startResize(entry, event);\n }}\n onDoubleClick={() => {\n resize.sizeToContent(entry);\n }}\n onKeyDown={(event) => {\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\")\n return;\n event.preventDefault();\n resize.nudge(\n entry,\n event.key === \"ArrowLeft\"\n ? -KEYBOARD_STEP\n : KEYBOARD_STEP,\n );\n }}\n />\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n );\n}\n","import { accessDotted } from \"@gridkitjs/core\";\nimport { type ReactNode } from \"react\";\nimport type { ResolvedColumn } from \"../DataGrid\";\n\ninterface GridBodyProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n dataSource?: readonly Row[] | undefined;\n /** The column being resized, so its cells outline with its header. */\n activeColumnId: string | null;\n}\n\nexport default function GridBody<Row>({\n columns,\n dataSource,\n activeColumnId,\n}: GridBodyProps<Row>) {\n return (\n <tbody className=\"grid-body\">\n {dataSource?.map((row, index) => (\n <tr key={index} className=\"grid-row\">\n {columns.map(({ id, column, alignment }) => {\n // Resolved either way, so a template that only formats the value\n // never has to walk the field path a second time.\n const value = accessDotted(row, column.field);\n\n return (\n <td\n key={id}\n data-gridkit-column={id}\n className={\n id === activeColumnId ? \"grid-cell is-resizing\" : \"grid-cell\"\n }\n style={{ textAlign: alignment }}\n >\n {column.cellTemplate\n ? column.cellTemplate({ value, row, rowIndex: index })\n : (value as ReactNode)}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n );\n}\n","import {\n useState,\n type Dispatch,\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n type SetStateAction,\n} from \"react\";\nimport {\n applyColumnResize,\n beginColumnResize,\n clampColumnWidth,\n resolveColumnConstraints,\n sizeColumnToContent,\n type ColumnResizeEvent,\n type ColumnSizeDefaults,\n type ColumnSizingState,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"./DataGrid\";\nimport measureColumnContent from \"./measureColumnContent\";\n\ninterface UseColumnResizeOptions {\n tableRef: RefObject<HTMLTableElement | null>;\n sizing: ColumnSizingState;\n setSizing: Dispatch<SetStateAction<ColumnSizingState>>;\n columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;\n onColumnResize?: ((event: ColumnResizeEvent) => void) | undefined;\n}\n\nexport interface ColumnResizeApi<Row> {\n /** The column being dragged, for as long as the drag lasts. */\n activeColumnId: string | null;\n startResize: (\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n sizeToContent: (entry: ResolvedColumn<Row>) => void;\n nudge: (entry: ResolvedColumn<Row>, delta: number) => void;\n}\n\n/**\n * Turns pointer and keyboard input into column widths. Every width it produces\n * comes from `@gridkitjs/core`; this hook only supplies the coordinates.\n */\nexport default function useColumnResize<Row>({\n tableRef,\n sizing,\n setSizing,\n columnSizeDefaults,\n onColumnResize,\n}: UseColumnResizeOptions): ColumnResizeApi<Row> {\n const [activeColumnId, setActiveColumnId] = useState<string | null>(null);\n\n function commit(\n base: ColumnSizingState,\n columnId: string,\n width: number,\n phase: \"move\" | \"end\",\n ): void {\n const next = { ...base, [columnId]: width };\n setSizing(next);\n onColumnResize?.({ columnId, width, sizing: next, phase });\n }\n\n function startResize(\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n const handle = event.currentTarget;\n const { pointerId } = event;\n const session = beginColumnResize(\n entry.column,\n entry.width,\n event.clientX,\n columnSizeDefaults,\n );\n /**\n * Only the dragged column can change while the drag lasts, so the state as\n * it was when the drag opened stays a correct base to merge into — no ref\n * mirror is needed to dodge a stale closure.\n */\n const base = sizing;\n let width = session.startWidth;\n\n // Otherwise the drag selects the header text it started on.\n event.preventDefault();\n event.stopPropagation();\n handle.setPointerCapture(pointerId);\n setActiveColumnId(session.columnId);\n\n function move(moveEvent: PointerEvent): void {\n width = applyColumnResize(session, moveEvent.clientX);\n commit(base, session.columnId, width, \"move\");\n }\n\n function stop(): void {\n handle.removeEventListener(\"pointermove\", move);\n handle.removeEventListener(\"pointerup\", end);\n handle.removeEventListener(\"pointercancel\", cancel);\n window.removeEventListener(\"keydown\", onKeyDown);\n if (handle.hasPointerCapture(pointerId)) {\n handle.releasePointerCapture(pointerId);\n }\n setActiveColumnId(null);\n }\n\n function end(): void {\n stop();\n commit(base, session.columnId, width, \"end\");\n }\n\n /**\n * Escape puts back the state the drag started from, which correctly covers\n * a column that had no stored width at all — merging `startWidth` back in\n * would instead leave it pinned and hidden from auto-fit.\n */\n function cancel(): void {\n stop();\n setSizing(base);\n onColumnResize?.({\n columnId: session.columnId,\n width: session.startWidth,\n sizing: base,\n phase: \"end\",\n });\n }\n\n function onKeyDown(keyEvent: KeyboardEvent): void {\n if (keyEvent.key === \"Escape\") {\n cancel();\n }\n }\n\n handle.addEventListener(\"pointermove\", move);\n handle.addEventListener(\"pointerup\", end);\n handle.addEventListener(\"pointercancel\", cancel);\n window.addEventListener(\"keydown\", onKeyDown);\n }\n\n function sizeToContent(entry: ResolvedColumn<Row>): void {\n const table = tableRef.current;\n if (table === null) {\n return;\n }\n\n const measured = measureColumnContent(table, entry.id);\n if (measured === null) {\n return;\n }\n\n commit(\n sizing,\n entry.id,\n sizeColumnToContent(\n measured,\n resolveColumnConstraints(entry.column, columnSizeDefaults),\n ),\n \"end\",\n );\n }\n\n function nudge(entry: ResolvedColumn<Row>, delta: number): void {\n commit(\n sizing,\n entry.id,\n clampColumnWidth(\n entry.width + delta,\n resolveColumnConstraints(entry.column, columnSizeDefaults),\n ),\n \"end\",\n );\n }\n\n // Deliberately a new object each render: the handlers close over `sizing` to\n // merge into, and a stable identity would need either `sizing` in a\n // `useCallback` dep list (no gain) or the ref mirror avoided above.\n return { activeColumnId, startResize, sizeToContent, nudge };\n}\n","/**\n * The width the widest cell in `columnId` needs to show its content in full,\n * or `null` when the column has no cells.\n *\n * Measured with a `Range` over each cell's contents rather than the cell's own\n * `scrollWidth`. A range shrink-wraps what is actually laid out, so a column\n * far wider than its content reports the content width and can be sized *down*;\n * `scrollWidth` never reports less than the cell it is read from and so can\n * only ever grow a column.\n *\n * Only rendered rows are measured — once paging or virtualisation lands, that\n * means the visible ones.\n */\nexport default function measureColumnContent(\n table: HTMLTableElement,\n columnId: string,\n): number | null {\n const cells = table.querySelectorAll<HTMLElement>(\n `[data-gridkit-column=\"${CSS.escape(columnId)}\"]`,\n );\n const range = document.createRange();\n let widest: number | null = null;\n\n for (const cell of cells) {\n range.selectNodeContents(cell);\n const style = getComputedStyle(cell);\n // The range covers the content box only, so the cell's own spacing has to\n // be added back or the column would clip by exactly its padding.\n const width =\n range.getBoundingClientRect().width +\n parseFloat(style.paddingLeft) +\n parseFloat(style.paddingRight) +\n parseFloat(style.borderLeftWidth) +\n parseFloat(style.borderRightWidth);\n\n if (widest === null || width > widest) {\n widest = width;\n }\n }\n\n return widest;\n}\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\n\n/**\n * The inner width of `ref`'s element, tracked as it changes.\n *\n * A layout effect rather than an effect so the first measurement lands before\n * paint — otherwise columns show at their natural width for a frame and then\n * visibly jump once auto-fit runs. Server rendering would want the usual\n * isomorphic-layout-effect shim here.\n *\n * Reads `clientWidth` rather than the observer entry's `contentRect` so the\n * first measurement and every later one come from the same, already-rounded,\n * source.\n *\n * @param enabled Whether to observe at all. A caller that does not read the\n * width passes `false` rather than paying a re-render of the whole grid on\n * every frame of a window resize.\n */\nexport default function useElementWidth(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean,\n): number | null {\n const [width, setWidth] = useState<number | null>(null);\n\n useLayoutEffect(() => {\n const element = ref.current;\n if (element === null || !enabled) {\n return undefined;\n }\n\n setWidth(element.clientWidth);\n\n const observer = new ResizeObserver(() => {\n setWidth(element.clientWidth);\n });\n observer.observe(element);\n\n return () => {\n observer.disconnect();\n };\n }, [ref, enabled]);\n\n return width;\n}\n"],"mappings":"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","names":["useState","jsx","useState","jsx","jsxs","useState"]}
|
|
1
|
+
{"version":3,"sources":["../src/DataGrid/DataGrid.tsx","../src/DataGrid/components/GridHeader.tsx","../src/DataGrid/components/GridBody.tsx","../src/DataGrid/useColumnDrag.ts","../src/DataGrid/useColumnResize.ts","../src/DataGrid/measureColumnContent.ts","../src/DataGrid/useElementWidth.ts"],"sourcesContent":["import { useMemo, useRef, useState, type ReactNode } from \"react\";\nimport {\n applyColumnOrder,\n defineColumnsFromRows,\n fitColumnsToWidth,\n moveColumnBefore,\n resolveColumnWidths,\n totalColumnWidth,\n type ColumnDefinition as CoreColumnDefinition,\n type ResolvedColumn as CoreResolvedColumn,\n type ColumnOrderEvent,\n type ColumnOrderState,\n type ColumnResizeEvent,\n type ColumnSizeDefaults,\n type ColumnSizingState,\n} from \"@gridkitjs/core\";\nimport GridHeader from \"./components/GridHeader\";\nimport GridBody from \"./components/GridBody\";\nimport useColumnDrag, { type DropTarget } from \"./useColumnDrag\";\nimport useColumnResize from \"./useColumnResize\";\nimport useElementWidth from \"./useElementWidth\";\n\n/**\n * A column whose header and cells may render arbitrary React content.\n * @gridkitjs/core stays framework-agnostic and so leaves that output type open;\n * this is the binding React consumers want, and the one they should import.\n */\nexport type ColumnDefinition<Row> = CoreColumnDefinition<Row, ReactNode>;\n\n/** A column paired with the width it renders at. */\nexport type ResolvedColumn<Row> = CoreResolvedColumn<Row, ReactNode>;\n\nexport type Borders = \"horizontal\" | \"vertical\" | \"all\" | \"none\";\n\n/**\n * How a column's width relates to the grid's.\n *\n * `\"fit\"` keeps the columns filling the grid: the space a column gives up is\n * handed to the others, and the space it takes comes out of them. `\"fixed\"`\n * lets every column keep its own width, so a resize moves one column and\n * nothing else, and the grid scrolls or leaves a gap accordingly.\n */\nexport type ResizeMode = \"fit\" | \"fixed\";\n\nexport interface HoverableConfig {\n rows?: boolean;\n columns?: boolean;\n cells?: boolean;\n}\n\nexport interface DataGridProps<Row> {\n columns?: readonly ColumnDefinition<Row>[] | undefined;\n dataSource?: readonly Row[] | undefined;\n borders?: Borders | undefined;\n hoverable?: HoverableConfig | undefined;\n /** Whether columns can be dragged wider, unless a column says otherwise. */\n resizableColumns?: boolean | undefined;\n /**\n * Whether columns can be dragged into a new position, unless a column says\n * otherwise. Turning it off leaves an order the user already made in place.\n */\n reorderableColumns?: boolean | undefined;\n /**\n * Whether columns fill the grid's width or sit at their own. Defaults to\n * `\"fit\"`, under which columns the user has sized keep their width and the\n * rest share what is left.\n */\n resizeMode?: ResizeMode | undefined;\n /** Column widths to start from, keyed by column id. Uncontrolled. */\n defaultColumnSizing?: ColumnSizingState | undefined;\n /**\n * Column ids in the order to start in. Uncontrolled, and partial: ids it\n * omits keep their position among `columns` and follow those it lists.\n */\n defaultColumnOrder?: ColumnOrderState | undefined;\n /**\n * Sizes applied to columns that do not set their own — the width they start\n * at and the bounds they may be resized between. Distinct from\n * `defaultColumnSizing`, which sets specific columns' starting widths.\n */\n columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;\n /**\n * Called as the user resizes a column. Fires continuously with\n * `phase: \"move\"` and once on release with `phase: \"end\"` — the latter being\n * the one to persist. Auto-fit does not call it; it reports user intent only.\n */\n onColumnResize?: ((event: ColumnResizeEvent) => void) | undefined;\n /**\n * Called once when the user drops a column somewhere new. A drop that leaves\n * the order as it was does not call it.\n */\n onColumnOrderChange?: ((event: ColumnOrderEvent) => void) | undefined;\n}\n\nexport function DataGridComponent<Row>({\n dataSource,\n columns,\n borders,\n hoverable,\n resizableColumns = false,\n reorderableColumns = false,\n resizeMode = \"fit\",\n defaultColumnSizing,\n defaultColumnOrder,\n columnSizeDefaults,\n onColumnResize,\n onColumnOrderChange,\n}: DataGridProps<Row>) {\n const hoverRows = hoverable?.rows ?? true;\n const hoverColumns = hoverable?.columns ?? true;\n const hoverCells = hoverable?.cells ?? true;\n\n const viewportRef = useRef<HTMLDivElement>(null);\n const tableRef = useRef<HTMLTableElement>(null);\n const viewportWidth = useElementWidth(viewportRef, resizeMode === \"fit\");\n const [sizing, setSizing] = useState<ColumnSizingState>(\n defaultColumnSizing ?? {},\n );\n const [order, setOrder] = useState<ColumnOrderState>(\n defaultColumnOrder ?? [],\n );\n\n const definedColumns = useMemo<readonly ColumnDefinition<Row>[]>(() => {\n if (columns && columns.length !== 0) return columns;\n if (dataSource && dataSource.length > 0)\n return defineColumnsFromRows(dataSource);\n return [];\n }, [columns, dataSource]);\n\n /**\n * Ahead of sizing, so everything downstream reads one already-ordered list\n * and no part of the grid has to know a reorder happened.\n */\n const orderedColumns = useMemo(\n () => applyColumnOrder(definedColumns, order),\n [definedColumns, order],\n );\n\n /**\n * Auto-fit is a derivation rather than a write back into `sizing`, so that a\n * `width` set in a column definition is never overwritten and the effect\n * cannot chase its own output. `\"fixed\"` is then simply the absence of it.\n */\n const resolved = useMemo(() => {\n const widths = resolveColumnWidths(orderedColumns, sizing, {\n sizes: columnSizeDefaults,\n resizable: resizableColumns,\n reorderable: reorderableColumns,\n });\n return resizeMode === \"fit\" && viewportWidth !== null\n ? fitColumnsToWidth(widths, viewportWidth, columnSizeDefaults)\n : widths;\n }, [\n orderedColumns,\n sizing,\n resizeMode,\n viewportWidth,\n columnSizeDefaults,\n resizableColumns,\n reorderableColumns,\n ]);\n\n const resize = useColumnResize<Row>({\n tableRef,\n sizing,\n setSizing,\n columnSizeDefaults,\n onColumnResize,\n });\n\n /**\n * The ids as displayed, which a drop is expressed against — the order state\n * starts empty and may name only some columns, so moving against it directly\n * would have nothing to rearrange.\n */\n const displayedIds = useMemo(\n () => orderedColumns.map((column) => column.id ?? column.field),\n [orderedColumns],\n );\n\n /**\n * The one place a drop is applied. A second drop zone — a grouping bar above\n * the header — turns this into a switch on `target.kind` and touches nothing\n * else.\n */\n function handleDrop(target: DropTarget, movedId: string): void {\n const next = moveColumnBefore(displayedIds, movedId, target.beforeId);\n // `moveColumnBefore` hands back the same reference for a move that changes\n // nothing, so a drop in place neither renders nor reports.\n if (next === displayedIds) {\n return;\n }\n setOrder(next);\n onColumnOrderChange?.({ columnId: movedId, order: next });\n }\n\n const drag = useColumnDrag<Row>({ order: displayedIds, onDrop: handleDrop });\n\n return (\n <div className=\"gridkit-data-grid-viewport\" ref={viewportRef}>\n <table\n ref={tableRef}\n // Widths are only honoured exactly when the table is as wide as its\n // columns; at `100%` the fixed layout redistributes the difference.\n style={{ width: totalColumnWidth(resolved) }}\n className={[\n \"gridkit-data-grid\",\n borders ? `borders-${borders}` : \"\",\n hoverRows ? \"\" : \"no-hover-rows\",\n hoverColumns ? \"\" : \"no-hover-columns\",\n hoverCells ? \"\" : \"no-hover-cells\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n <colgroup>\n {resolved.map((entry) => (\n <col key={entry.id} style={{ width: entry.width }} />\n ))}\n </colgroup>\n <GridHeader<Row> columns={resolved} resize={resize} drag={drag} />\n <GridBody<Row>\n columns={resolved}\n dataSource={dataSource}\n activeColumnId={resize.activeColumnId}\n />\n </table>\n </div>\n );\n}\n","import { createPortal } from \"react-dom\";\nimport { KEYBOARD_STEP } from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"../DataGrid\";\nimport type { ColumnDragApi } from \"../useColumnDrag\";\nimport type { ColumnResizeApi } from \"../useColumnResize\";\n\ninterface GridHeaderProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n resize: ColumnResizeApi<Row>;\n drag: ColumnDragApi<Row>;\n}\n\nexport default function GridHeader<Row>({\n columns,\n resize,\n drag,\n}: GridHeaderProps<Row>) {\n const { beforeId } = drag.dropTarget ?? {};\n const draggedEntry =\n columns.find((entry) => entry.id === drag.draggedColumnId) ?? null;\n\n return (\n <thead>\n <tr className=\"grid-header\">\n {columns.map((entry, index) => {\n const { column } = entry;\n const resizing = resize.activeColumnId === entry.id;\n const dragging = drag.draggedColumnId === entry.id;\n\n /**\n * Drawn on the gap's own edge, so the one gap between two columns is\n * marked once. No guard against the dragged column: the hook reports\n * only gaps that would move it.\n */\n const dropBefore = beforeId !== undefined && beforeId === entry.id;\n const dropAfter = beforeId === null && index === columns.length - 1;\n\n return (\n <th\n key={entry.id}\n data-gridkit-column={entry.id}\n className={[\n \"header-cell\",\n resizing ? \"is-resizing\" : \"\",\n dragging ? \"is-dragging\" : \"\",\n dropBefore ? \"is-drop-before\" : \"\",\n dropAfter ? \"is-drop-after\" : \"\",\n column.wrap?.header ? \"is-wrapped\" : \"\",\n column.headerClassName ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n {...(entry.reorderable && {\n tabIndex: 0,\n onPointerDown: (event) => {\n drag.startDrag(entry, event);\n },\n onKeyDown: (event) => {\n if (!event.ctrlKey) return;\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\")\n return;\n event.preventDefault();\n drag.moveByKeyboard(\n entry,\n event.key === \"ArrowLeft\" ? -1 : 1,\n );\n },\n })}\n >\n {entry.label}\n {entry.resizable && (\n <span\n className=\"header-resize-handle\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={`Resize ${column.field}`}\n tabIndex={0}\n onPointerDown={(event) => {\n resize.startResize(entry, event);\n }}\n onDoubleClick={() => {\n resize.sizeToContent(entry);\n }}\n onKeyDown={(event) => {\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\")\n return;\n event.preventDefault();\n resize.nudge(\n entry,\n event.key === \"ArrowLeft\"\n ? -KEYBOARD_STEP\n : KEYBOARD_STEP,\n );\n }}\n />\n )}\n </th>\n );\n })}\n </tr>\n {/*\n * Portalled to the body, and not only because a `div` cannot sit in a\n * `tr`: inside the viewport the overflow that makes the grid scroll\n * would clip it.\n */}\n {draggedEntry !== null &&\n drag.ghostTransform !== null &&\n createPortal(\n <div\n className=\"gridkit-data-grid header-cell drag-ghost\"\n style={{\n width: draggedEntry.width,\n transform: drag.ghostTransform,\n }}\n aria-hidden=\"true\"\n >\n {draggedEntry.label}\n </div>,\n document.body,\n )}\n </thead>\n );\n}\n","import { accessDotted } from \"@gridkitjs/core\";\nimport { type ReactNode } from \"react\";\nimport type { ResolvedColumn } from \"../DataGrid\";\n\ninterface GridBodyProps<Row> {\n columns: readonly ResolvedColumn<Row>[];\n dataSource?: readonly Row[] | undefined;\n /** The column being resized, so its cells outline with its header. */\n activeColumnId: string | null;\n}\n\nexport default function GridBody<Row>({\n columns,\n dataSource,\n activeColumnId,\n}: GridBodyProps<Row>) {\n return (\n <tbody className=\"grid-body\">\n {dataSource?.map((row, index) => (\n <tr key={index} className=\"grid-row\">\n {columns.map(({ id, column, alignment }) => {\n // Resolved either way, so a template that only formats the value\n // never has to walk the field path a second time.\n const value = accessDotted(row, column.field);\n\n return (\n <td\n key={id}\n data-gridkit-column={id}\n className={[\n \"grid-cell\",\n id === activeColumnId ? \"is-resizing\" : \"\",\n column.wrap?.cells ? \"is-wrapped\" : \"\",\n column.cellClassName ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{ textAlign: alignment }}\n >\n {column.cellTemplate\n ? column.cellTemplate({ value, row, rowIndex: index })\n : (value as ReactNode)}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n );\n}\n","import { useState, type PointerEvent as ReactPointerEvent } from \"react\";\nimport {\n movesColumn,\n resolveDropBefore,\n type ColumnOrderState,\n type DropSide,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"./DataGrid\";\n\n/**\n * How far the pointer travels before a press becomes a drag. Below it the\n * gesture is still a click, which is what leaves the header free to take one.\n */\nconst DRAG_THRESHOLD = 4;\n\n/**\n * Where a drop would land. A union rather than the bare id it holds today, so\n * a second drop zone adds a member instead of reshaping this state.\n */\nexport type DropTarget = { kind: \"column-order\"; beforeId: string | null };\n\ninterface UseColumnDragOptions {\n order: ColumnOrderState;\n onDrop: (target: DropTarget, movedId: string) => void;\n}\n\nexport interface ColumnDragApi<Row> {\n /** The column being dragged, for as long as the drag lasts. */\n draggedColumnId: string | null;\n /** Where it would land if released now. */\n dropTarget: DropTarget | null;\n /** Where the element trailing the pointer sits, as a CSS `transform`. */\n ghostTransform: string | null;\n startDrag: (\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n /** Moves a column one place left (`-1`) or right (`1`). */\n moveByKeyboard: (entry: ResolvedColumn<Row>, direction: -1 | 1) => void;\n}\n\n/**\n * The header under `(x, y)`. `closest` is what makes the whole cell the drop\n * zone: a hit on the label or the resize handle resolves to its header.\n */\nfunction headerAt(x: number, y: number): Element | null {\n const element = document.elementFromPoint(x, y);\n return element?.closest(\"th[data-gridkit-column]\") ?? null;\n}\n\n/** Which half of `element` `x` falls in. */\nfunction sideOf(element: Element, x: number): DropSide {\n const rect = element.getBoundingClientRect();\n return x < rect.left + rect.width / 2 ? \"before\" : \"after\";\n}\n\n/**\n * Turns a pointer drag over the header into a drop target, leaving `onDrop` to\n * apply it.\n *\n * Pointer events rather than HTML5 drag-and-drop: `dragenter`/`dragleave` fire\n * per descendant, so the header's text and resize handle would each report the\n * target leaving and re-entering as the pointer crossed them.\n */\nexport default function useColumnDrag<Row>({\n order,\n onDrop,\n}: UseColumnDragOptions): ColumnDragApi<Row> {\n const [draggedColumnId, setDraggedColumnId] = useState<string | null>(null);\n const [dropTarget, setDropTarget] = useState<DropTarget | null>(null);\n const [ghostTransform, setGhostTransform] = useState<string | null>(null);\n\n function startDrag(\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n const header = event.currentTarget;\n // Only the horizontal distance opens the drag: columns move along one\n // axis, so vertical travel says nothing about the user's intent.\n const { pointerId, clientX: startX } = event;\n const grabX = startX - header.getBoundingClientRect().left;\n let dragging = false;\n let target: DropTarget | null = null;\n\n /** Keeps the grab offset, so the pointer holds the spot it picked up. */\n function placeGhost(x: number, y: number): void {\n setGhostTransform(`translate(${String(x - grabX)}px, ${String(y)}px)`);\n }\n\n header.setPointerCapture(pointerId);\n\n function move(moveEvent: PointerEvent): void {\n const { clientX, clientY } = moveEvent;\n\n if (!dragging) {\n if (Math.abs(clientX - startX) < DRAG_THRESHOLD) {\n return;\n }\n dragging = true;\n setDraggedColumnId(entry.id);\n }\n\n placeGhost(clientX, clientY);\n\n // Hit-tested rather than read from the event's target, which pointer\n // capture pins to the header the drag opened on.\n const over = headerAt(clientX, clientY);\n const overId = over?.getAttribute(\"data-gridkit-column\");\n\n // The rect is read fresh each move, so a width changed mid-drag cannot\n // leave the midpoint stale.\n const beforeId =\n over && overId\n ? resolveDropBefore(order, overId, sideOf(over, clientX))\n : undefined;\n\n // A gap the column already sits in would promise a move that\n // `moveColumnBefore` then declines to make.\n target =\n beforeId !== undefined && movesColumn(order, entry.id, beforeId)\n ? { kind: \"column-order\", beforeId }\n : null;\n\n setDropTarget(target);\n }\n\n function stop(): void {\n header.removeEventListener(\"pointermove\", move);\n header.removeEventListener(\"pointerup\", end);\n header.removeEventListener(\"pointercancel\", cancel);\n window.removeEventListener(\"keydown\", onKeyDown);\n if (header.hasPointerCapture(pointerId)) {\n header.releasePointerCapture(pointerId);\n }\n setGhostTransform(null);\n setDraggedColumnId(null);\n setDropTarget(null);\n }\n\n function end(): void {\n const dropped = target;\n stop();\n if (dragging && dropped !== null) {\n onDrop(dropped, entry.id);\n }\n }\n\n /** Escape and a cancelled pointer both leave the order as it was. */\n function cancel(): void {\n target = null;\n stop();\n }\n\n function onKeyDown(keyEvent: KeyboardEvent): void {\n if (keyEvent.key === \"Escape\") {\n cancel();\n }\n }\n\n header.addEventListener(\"pointermove\", move);\n header.addEventListener(\"pointerup\", end);\n header.addEventListener(\"pointercancel\", cancel);\n window.addEventListener(\"keydown\", onKeyDown);\n }\n\n function moveByKeyboard(entry: ResolvedColumn<Row>, direction: -1 | 1): void {\n const index = order.indexOf(entry.id);\n if (index === -1) {\n return;\n }\n\n /**\n * Moving right lands in front of the id two along: the gap immediately\n * after a column is the one it already sits in.\n */\n const targetIndex = direction === -1 ? index - 1 : index + 2;\n if (targetIndex < 0) {\n return;\n }\n\n onDrop(\n { kind: \"column-order\", beforeId: order[targetIndex] ?? null },\n entry.id,\n );\n }\n\n // A new object each render, as `useColumnResize` returns: the handlers close\n // over `order`, and a stable identity would buy nothing.\n return {\n draggedColumnId,\n dropTarget,\n ghostTransform,\n startDrag,\n moveByKeyboard,\n };\n}\n","import {\n useState,\n type Dispatch,\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n type SetStateAction,\n} from \"react\";\nimport {\n applyColumnResize,\n beginColumnResize,\n clampColumnWidth,\n resolveColumnConstraints,\n sizeColumnToContent,\n type ColumnResizeEvent,\n type ColumnSizeDefaults,\n type ColumnSizingState,\n} from \"@gridkitjs/core\";\nimport type { ResolvedColumn } from \"./DataGrid\";\nimport measureColumnContent from \"./measureColumnContent\";\n\ninterface UseColumnResizeOptions {\n tableRef: RefObject<HTMLTableElement | null>;\n sizing: ColumnSizingState;\n setSizing: Dispatch<SetStateAction<ColumnSizingState>>;\n columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;\n onColumnResize?: ((event: ColumnResizeEvent) => void) | undefined;\n}\n\nexport interface ColumnResizeApi<Row> {\n /** The column being dragged, for as long as the drag lasts. */\n activeColumnId: string | null;\n startResize: (\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ) => void;\n sizeToContent: (entry: ResolvedColumn<Row>) => void;\n nudge: (entry: ResolvedColumn<Row>, delta: number) => void;\n}\n\n/**\n * Turns pointer and keyboard input into column widths. Every width it produces\n * comes from `@gridkitjs/core`; this hook only supplies the coordinates.\n */\nexport default function useColumnResize<Row>({\n tableRef,\n sizing,\n setSizing,\n columnSizeDefaults,\n onColumnResize,\n}: UseColumnResizeOptions): ColumnResizeApi<Row> {\n const [activeColumnId, setActiveColumnId] = useState<string | null>(null);\n\n function commit(\n base: ColumnSizingState,\n columnId: string,\n width: number,\n phase: \"move\" | \"end\",\n ): void {\n const next = { ...base, [columnId]: width };\n setSizing(next);\n onColumnResize?.({ columnId, width, sizing: next, phase });\n }\n\n function startResize(\n entry: ResolvedColumn<Row>,\n event: ReactPointerEvent<HTMLElement>,\n ): void {\n const handle = event.currentTarget;\n const { pointerId } = event;\n const session = beginColumnResize(\n entry.column,\n entry.width,\n event.clientX,\n columnSizeDefaults,\n );\n /**\n * Only the dragged column can change while the drag lasts, so the state as\n * it was when the drag opened stays a correct base to merge into — no ref\n * mirror is needed to dodge a stale closure.\n */\n const base = sizing;\n let width = session.startWidth;\n\n // Otherwise the drag selects the header text it started on.\n event.preventDefault();\n event.stopPropagation();\n handle.setPointerCapture(pointerId);\n setActiveColumnId(session.columnId);\n\n function move(moveEvent: PointerEvent): void {\n width = applyColumnResize(session, moveEvent.clientX);\n commit(base, session.columnId, width, \"move\");\n }\n\n function stop(): void {\n handle.removeEventListener(\"pointermove\", move);\n handle.removeEventListener(\"pointerup\", end);\n handle.removeEventListener(\"pointercancel\", cancel);\n window.removeEventListener(\"keydown\", onKeyDown);\n if (handle.hasPointerCapture(pointerId)) {\n handle.releasePointerCapture(pointerId);\n }\n setActiveColumnId(null);\n }\n\n function end(): void {\n stop();\n commit(base, session.columnId, width, \"end\");\n }\n\n /**\n * Escape puts back the state the drag started from, which correctly covers\n * a column that had no stored width at all — merging `startWidth` back in\n * would instead leave it pinned and hidden from auto-fit.\n */\n function cancel(): void {\n stop();\n setSizing(base);\n onColumnResize?.({\n columnId: session.columnId,\n width: session.startWidth,\n sizing: base,\n phase: \"end\",\n });\n }\n\n function onKeyDown(keyEvent: KeyboardEvent): void {\n if (keyEvent.key === \"Escape\") {\n cancel();\n }\n }\n\n handle.addEventListener(\"pointermove\", move);\n handle.addEventListener(\"pointerup\", end);\n handle.addEventListener(\"pointercancel\", cancel);\n window.addEventListener(\"keydown\", onKeyDown);\n }\n\n function sizeToContent(entry: ResolvedColumn<Row>): void {\n const table = tableRef.current;\n if (table === null) {\n return;\n }\n\n const measured = measureColumnContent(table, entry.id);\n if (measured === null) {\n return;\n }\n\n commit(\n sizing,\n entry.id,\n sizeColumnToContent(\n measured,\n resolveColumnConstraints(entry.column, columnSizeDefaults),\n ),\n \"end\",\n );\n }\n\n function nudge(entry: ResolvedColumn<Row>, delta: number): void {\n commit(\n sizing,\n entry.id,\n clampColumnWidth(\n entry.width + delta,\n resolveColumnConstraints(entry.column, columnSizeDefaults),\n ),\n \"end\",\n );\n }\n\n // Deliberately a new object each render: the handlers close over `sizing` to\n // merge into, and a stable identity would need either `sizing` in a\n // `useCallback` dep list (no gain) or the ref mirror avoided above.\n return { activeColumnId, startResize, sizeToContent, nudge };\n}\n","/**\n * The width the widest cell in `columnId` needs to show its content in full,\n * or `null` when the column has no cells.\n *\n * Measured with a `Range` over each cell's contents rather than the cell's own\n * `scrollWidth`. A range shrink-wraps what is actually laid out, so a column\n * far wider than its content reports the content width and can be sized *down*;\n * `scrollWidth` never reports less than the cell it is read from and so can\n * only ever grow a column.\n *\n * Only rendered rows are measured — once paging or virtualisation lands, that\n * means the visible ones.\n */\nexport default function measureColumnContent(\n table: HTMLTableElement,\n columnId: string,\n): number | null {\n const cells = table.querySelectorAll<HTMLElement>(\n `[data-gridkit-column=\"${CSS.escape(columnId)}\"]`,\n );\n const range = document.createRange();\n let widest: number | null = null;\n\n for (const cell of cells) {\n range.selectNodeContents(cell);\n const style = getComputedStyle(cell);\n // The range covers the content box only, so the cell's own spacing has to\n // be added back or the column would clip by exactly its padding.\n const width =\n range.getBoundingClientRect().width +\n parseFloat(style.paddingLeft) +\n parseFloat(style.paddingRight) +\n parseFloat(style.borderLeftWidth) +\n parseFloat(style.borderRightWidth);\n\n if (widest === null || width > widest) {\n widest = width;\n }\n }\n\n return widest;\n}\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\n\n/**\n * The inner width of `ref`'s element, tracked as it changes.\n *\n * A layout effect rather than an effect so the first measurement lands before\n * paint — otherwise columns show at their natural width for a frame and then\n * visibly jump once auto-fit runs. Server rendering would want the usual\n * isomorphic-layout-effect shim here.\n *\n * Reads `clientWidth` rather than the observer entry's `contentRect` so the\n * first measurement and every later one come from the same, already-rounded,\n * source.\n *\n * @param enabled Whether to observe at all. A caller that does not read the\n * width passes `false` rather than paying a re-render of the whole grid on\n * every frame of a window resize.\n */\nexport default function useElementWidth(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean,\n): number | null {\n const [width, setWidth] = useState<number | null>(null);\n\n useLayoutEffect(() => {\n const element = ref.current;\n if (element === null || !enabled) {\n return undefined;\n }\n\n setWidth(element.clientWidth);\n\n const observer = new ResizeObserver(() => {\n setWidth(element.clientWidth);\n });\n observer.observe(element);\n\n return () => {\n observer.disconnect();\n };\n }, [ref, enabled]);\n\n return width;\n}\n"],"mappings":"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","names":["useState","jsx","useState","useState","useState","jsx","jsxs","useState"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gridkitjs/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "React data-grid components built on @gridkitjs/core.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Blagoja Blazhevski",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"react-dom": "^19.0.0"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@gridkitjs/core": "0.
|
|
43
|
+
"@gridkitjs/core": "0.3.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/react": "^19.2.18",
|