@gridkitjs/react 0.0.1 → 0.2.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 CHANGED
@@ -1,12 +1,12 @@
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';
4
- export { ColumnResizeEvent, ColumnSizeDefaults, ColumnSizingState } from '@gridkitjs/core';
3
+ import { ColumnDefinition as ColumnDefinition$1, ColumnSizingState, ColumnOrderState, ColumnSizeDefaults, ColumnResizeEvent, ColumnOrderEvent, ResolvedColumn as ResolvedColumn$1 } from '@gridkitjs/core';
4
+ export { CellTemplateContext, ColumnResizeEvent, ColumnSizeDefaults, ColumnSizingState } from '@gridkitjs/core';
5
5
 
6
6
  /**
7
- * A column whose header may render arbitrary React content. @gridkitjs/core
8
- * stays framework-agnostic and so leaves that output type open; this is the
9
- * binding React consumers want, and the one they should import.
7
+ * A column whose header and cells may render arbitrary React content.
8
+ * @gridkitjs/core stays framework-agnostic and so leaves that output type open;
9
+ * this is the binding React consumers want, and the one they should import.
10
10
  */
11
11
  type ColumnDefinition<Row> = ColumnDefinition$1<Row, ReactNode>;
12
12
  /** A column paired with the width it renders at. */
@@ -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,77 +1,107 @@
1
1
  // src/DataGrid/DataGrid.tsx
2
- import { useMemo, useRef, useState as useState3 } from "react";
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
- return /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: "grid-header", children: columns.map((entry) => {
18
- const { column } = entry;
19
- const resizing = resize.activeColumnId === entry.id;
20
- return /* @__PURE__ */ jsxs(
21
- "th",
22
- {
23
- "data-gridkit-column": entry.id,
24
- className: resizing ? "header-cell is-resizing" : "header-cell",
25
- children: [
26
- entry.label,
27
- entry.resizable && /* @__PURE__ */ jsx(
28
- "span",
29
- {
30
- className: "header-resize-handle",
31
- role: "separator",
32
- "aria-orientation": "vertical",
33
- "aria-label": `Resize ${column.field}`,
34
- tabIndex: 0,
35
- onPointerDown: (event) => {
36
- resize.startResize(entry, event);
37
- },
38
- onDoubleClick: () => {
39
- resize.sizeToContent(entry);
40
- },
41
- onKeyDown: (event) => {
42
- if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
43
- return;
44
- event.preventDefault();
45
- resize.nudge(
46
- entry,
47
- event.key === "ArrowLeft" ? -KEYBOARD_STEP : KEYBOARD_STEP
48
- );
49
- },
50
- children: /* @__PURE__ */ jsxs(
51
- "svg",
52
- {
53
- className: "header-resize-grip",
54
- viewBox: "0 0 6 14",
55
- width: "6",
56
- height: "14",
57
- "aria-hidden": "true",
58
- children: [
59
- /* @__PURE__ */ jsx("circle", { cx: "1.5", cy: "4", r: "1" }),
60
- /* @__PURE__ */ jsx("circle", { cx: "1.5", cy: "7", r: "1" }),
61
- /* @__PURE__ */ jsx("circle", { cx: "1.5", cy: "10", r: "1" }),
62
- /* @__PURE__ */ jsx("circle", { cx: "4.5", cy: "4", r: "1" }),
63
- /* @__PURE__ */ jsx("circle", { cx: "4.5", cy: "7", r: "1" }),
64
- /* @__PURE__ */ jsx("circle", { cx: "4.5", cy: "10", r: "1" })
65
- ]
66
- }
67
- )
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
+ ].filter(Boolean).join(" "),
41
+ ...entry.reorderable && {
42
+ tabIndex: 0,
43
+ onPointerDown: (event) => {
44
+ drag.startDrag(entry, event);
45
+ },
46
+ onKeyDown: (event) => {
47
+ if (!event.ctrlKey) return;
48
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
49
+ return;
50
+ event.preventDefault();
51
+ drag.moveByKeyboard(
52
+ entry,
53
+ event.key === "ArrowLeft" ? -1 : 1
54
+ );
68
55
  }
69
- )
70
- ]
71
- },
72
- entry.id
73
- );
74
- }) }) });
56
+ },
57
+ children: [
58
+ entry.label,
59
+ entry.resizable && /* @__PURE__ */ jsx(
60
+ "span",
61
+ {
62
+ className: "header-resize-handle",
63
+ role: "separator",
64
+ "aria-orientation": "vertical",
65
+ "aria-label": `Resize ${column.field}`,
66
+ tabIndex: 0,
67
+ onPointerDown: (event) => {
68
+ resize.startResize(entry, event);
69
+ },
70
+ onDoubleClick: () => {
71
+ resize.sizeToContent(entry);
72
+ },
73
+ onKeyDown: (event) => {
74
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
75
+ return;
76
+ event.preventDefault();
77
+ resize.nudge(
78
+ entry,
79
+ event.key === "ArrowLeft" ? -KEYBOARD_STEP : KEYBOARD_STEP
80
+ );
81
+ }
82
+ }
83
+ )
84
+ ]
85
+ },
86
+ entry.id
87
+ );
88
+ }) }),
89
+ draggedEntry !== null && drag.ghostTransform !== null && createPortal(
90
+ /* @__PURE__ */ jsx(
91
+ "div",
92
+ {
93
+ className: "gridkit-data-grid header-cell drag-ghost",
94
+ style: {
95
+ width: draggedEntry.width,
96
+ transform: drag.ghostTransform
97
+ },
98
+ "aria-hidden": "true",
99
+ children: draggedEntry.label
100
+ }
101
+ ),
102
+ document.body
103
+ )
104
+ ] });
75
105
  }
76
106
 
77
107
  // src/DataGrid/components/GridBody.tsx
@@ -83,21 +113,128 @@ function GridBody({
83
113
  dataSource,
84
114
  activeColumnId
85
115
  }) {
86
- return /* @__PURE__ */ jsx2("tbody", { className: "grid-body", children: dataSource?.map((row, index) => /* @__PURE__ */ jsx2("tr", { className: "grid-row", children: columns.map(({ id, column, alignment }) => /* @__PURE__ */ jsx2(
87
- "td",
88
- {
89
- "data-gridkit-column": id,
90
- className: id === activeColumnId ? "grid-cell is-resizing" : "grid-cell",
91
- style: { textAlign: alignment },
92
- children: accessDotted(row, column.field)
93
- },
94
- id
95
- )) }, index)) });
116
+ return /* @__PURE__ */ jsx2("tbody", { className: "grid-body", children: dataSource?.map((row, index) => /* @__PURE__ */ jsx2("tr", { className: "grid-row", children: columns.map(({ id, column, alignment }) => {
117
+ const value = accessDotted(row, column.field);
118
+ return /* @__PURE__ */ jsx2(
119
+ "td",
120
+ {
121
+ "data-gridkit-column": id,
122
+ className: id === activeColumnId ? "grid-cell is-resizing" : "grid-cell",
123
+ style: { textAlign: alignment },
124
+ children: column.cellTemplate ? column.cellTemplate({ value, row, rowIndex: index }) : value
125
+ },
126
+ id
127
+ );
128
+ }) }, index)) });
129
+ }
130
+
131
+ // src/DataGrid/useColumnDrag.ts
132
+ import { useState } from "react";
133
+ import {
134
+ movesColumn,
135
+ resolveDropBefore
136
+ } from "@gridkitjs/core";
137
+ var DRAG_THRESHOLD = 4;
138
+ function headerAt(x, y) {
139
+ const element = document.elementFromPoint(x, y);
140
+ return element?.closest("th[data-gridkit-column]") ?? null;
141
+ }
142
+ function sideOf(element, x) {
143
+ const rect = element.getBoundingClientRect();
144
+ return x < rect.left + rect.width / 2 ? "before" : "after";
145
+ }
146
+ function useColumnDrag({
147
+ order,
148
+ onDrop
149
+ }) {
150
+ const [draggedColumnId, setDraggedColumnId] = useState(null);
151
+ const [dropTarget, setDropTarget] = useState(null);
152
+ const [ghostTransform, setGhostTransform] = useState(null);
153
+ function startDrag(entry, event) {
154
+ const header = event.currentTarget;
155
+ const { pointerId, clientX: startX } = event;
156
+ const grabX = startX - header.getBoundingClientRect().left;
157
+ let dragging = false;
158
+ let target = null;
159
+ function placeGhost(x, y) {
160
+ setGhostTransform(`translate(${String(x - grabX)}px, ${String(y)}px)`);
161
+ }
162
+ header.setPointerCapture(pointerId);
163
+ function move(moveEvent) {
164
+ const { clientX, clientY } = moveEvent;
165
+ if (!dragging) {
166
+ if (Math.abs(clientX - startX) < DRAG_THRESHOLD) {
167
+ return;
168
+ }
169
+ dragging = true;
170
+ setDraggedColumnId(entry.id);
171
+ }
172
+ placeGhost(clientX, clientY);
173
+ const over = headerAt(clientX, clientY);
174
+ const overId = over?.getAttribute("data-gridkit-column");
175
+ const beforeId = over && overId ? resolveDropBefore(order, overId, sideOf(over, clientX)) : void 0;
176
+ target = beforeId !== void 0 && movesColumn(order, entry.id, beforeId) ? { kind: "column-order", beforeId } : null;
177
+ setDropTarget(target);
178
+ }
179
+ function stop() {
180
+ header.removeEventListener("pointermove", move);
181
+ header.removeEventListener("pointerup", end);
182
+ header.removeEventListener("pointercancel", cancel);
183
+ window.removeEventListener("keydown", onKeyDown);
184
+ if (header.hasPointerCapture(pointerId)) {
185
+ header.releasePointerCapture(pointerId);
186
+ }
187
+ setGhostTransform(null);
188
+ setDraggedColumnId(null);
189
+ setDropTarget(null);
190
+ }
191
+ function end() {
192
+ const dropped = target;
193
+ stop();
194
+ if (dragging && dropped !== null) {
195
+ onDrop(dropped, entry.id);
196
+ }
197
+ }
198
+ function cancel() {
199
+ target = null;
200
+ stop();
201
+ }
202
+ function onKeyDown(keyEvent) {
203
+ if (keyEvent.key === "Escape") {
204
+ cancel();
205
+ }
206
+ }
207
+ header.addEventListener("pointermove", move);
208
+ header.addEventListener("pointerup", end);
209
+ header.addEventListener("pointercancel", cancel);
210
+ window.addEventListener("keydown", onKeyDown);
211
+ }
212
+ function moveByKeyboard(entry, direction) {
213
+ const index = order.indexOf(entry.id);
214
+ if (index === -1) {
215
+ return;
216
+ }
217
+ const targetIndex = direction === -1 ? index - 1 : index + 2;
218
+ if (targetIndex < 0) {
219
+ return;
220
+ }
221
+ onDrop(
222
+ { kind: "column-order", beforeId: order[targetIndex] ?? null },
223
+ entry.id
224
+ );
225
+ }
226
+ return {
227
+ draggedColumnId,
228
+ dropTarget,
229
+ ghostTransform,
230
+ startDrag,
231
+ moveByKeyboard
232
+ };
96
233
  }
97
234
 
98
235
  // src/DataGrid/useColumnResize.ts
99
236
  import {
100
- useState
237
+ useState as useState2
101
238
  } from "react";
102
239
  import {
103
240
  applyColumnResize,
@@ -133,7 +270,7 @@ function useColumnResize({
133
270
  columnSizeDefaults,
134
271
  onColumnResize
135
272
  }) {
136
- const [activeColumnId, setActiveColumnId] = useState(null);
273
+ const [activeColumnId, setActiveColumnId] = useState2(null);
137
274
  function commit(base, columnId, width, phase) {
138
275
  const next = { ...base, [columnId]: width };
139
276
  setSizing(next);
@@ -226,9 +363,9 @@ function useColumnResize({
226
363
  }
227
364
 
228
365
  // src/DataGrid/useElementWidth.ts
229
- import { useLayoutEffect, useState as useState2 } from "react";
366
+ import { useLayoutEffect, useState as useState3 } from "react";
230
367
  function useElementWidth(ref, enabled) {
231
- const [width, setWidth] = useState2(null);
368
+ const [width, setWidth] = useState3(null);
232
369
  useLayoutEffect(() => {
233
370
  const element = ref.current;
234
371
  if (element === null || !enabled) {
@@ -254,10 +391,13 @@ function DataGridComponent({
254
391
  borders,
255
392
  hoverable,
256
393
  resizableColumns = false,
394
+ reorderableColumns = false,
257
395
  resizeMode = "fit",
258
396
  defaultColumnSizing,
397
+ defaultColumnOrder,
259
398
  columnSizeDefaults,
260
- onColumnResize
399
+ onColumnResize,
400
+ onColumnOrderChange
261
401
  }) {
262
402
  const hoverRows = hoverable?.rows ?? true;
263
403
  const hoverColumns = hoverable?.columns ?? true;
@@ -265,28 +405,37 @@ function DataGridComponent({
265
405
  const viewportRef = useRef(null);
266
406
  const tableRef = useRef(null);
267
407
  const viewportWidth = useElementWidth(viewportRef, resizeMode === "fit");
268
- const [sizing, setSizing] = useState3(
408
+ const [sizing, setSizing] = useState4(
269
409
  defaultColumnSizing ?? {}
270
410
  );
411
+ const [order, setOrder] = useState4(
412
+ defaultColumnOrder ?? []
413
+ );
271
414
  const definedColumns = useMemo(() => {
272
415
  if (columns && columns.length !== 0) return columns;
273
416
  if (dataSource && dataSource.length > 0)
274
417
  return defineColumnsFromRows(dataSource);
275
418
  return [];
276
419
  }, [columns, dataSource]);
420
+ const orderedColumns = useMemo(
421
+ () => applyColumnOrder(definedColumns, order),
422
+ [definedColumns, order]
423
+ );
277
424
  const resolved = useMemo(() => {
278
- const widths = resolveColumnWidths(definedColumns, sizing, {
425
+ const widths = resolveColumnWidths(orderedColumns, sizing, {
279
426
  sizes: columnSizeDefaults,
280
- resizable: resizableColumns
427
+ resizable: resizableColumns,
428
+ reorderable: reorderableColumns
281
429
  });
282
430
  return resizeMode === "fit" && viewportWidth !== null ? fitColumnsToWidth(widths, viewportWidth, columnSizeDefaults) : widths;
283
431
  }, [
284
- definedColumns,
432
+ orderedColumns,
285
433
  sizing,
286
434
  resizeMode,
287
435
  viewportWidth,
288
436
  columnSizeDefaults,
289
- resizableColumns
437
+ resizableColumns,
438
+ reorderableColumns
290
439
  ]);
291
440
  const resize = useColumnResize({
292
441
  tableRef,
@@ -295,6 +444,19 @@ function DataGridComponent({
295
444
  columnSizeDefaults,
296
445
  onColumnResize
297
446
  });
447
+ const displayedIds = useMemo(
448
+ () => orderedColumns.map((column) => column.id ?? column.field),
449
+ [orderedColumns]
450
+ );
451
+ function handleDrop(target, movedId) {
452
+ const next = moveColumnBefore(displayedIds, movedId, target.beforeId);
453
+ if (next === displayedIds) {
454
+ return;
455
+ }
456
+ setOrder(next);
457
+ onColumnOrderChange?.({ columnId: movedId, order: next });
458
+ }
459
+ const drag = useColumnDrag({ order: displayedIds, onDrop: handleDrop });
298
460
  return /* @__PURE__ */ jsx3("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: /* @__PURE__ */ jsxs2(
299
461
  "table",
300
462
  {
@@ -309,7 +471,7 @@ function DataGridComponent({
309
471
  ].filter(Boolean).join(" "),
310
472
  children: [
311
473
  /* @__PURE__ */ jsx3("colgroup", { children: resolved.map((entry) => /* @__PURE__ */ jsx3("col", { style: { width: entry.width } }, entry.id)) }),
312
- /* @__PURE__ */ jsx3(GridHeader, { columns: resolved, resize }),
474
+ /* @__PURE__ */ jsx3(GridHeader, { columns: resolved, resize, drag }),
313
475
  /* @__PURE__ */ jsx3(
314
476
  GridBody,
315
477
  {
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 may render arbitrary React content. @gridkitjs/core\n * stays framework-agnostic and so leaves that output type open; this is the\n * 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 <svg\n className=\"header-resize-grip\"\n viewBox=\"0 0 6 14\"\n width=\"6\"\n height=\"14\"\n aria-hidden=\"true\"\n >\n <circle cx=\"1.5\" cy=\"4\" r=\"1\" />\n <circle cx=\"1.5\" cy=\"7\" r=\"1\" />\n <circle cx=\"1.5\" cy=\"10\" r=\"1\" />\n <circle cx=\"4.5\" cy=\"4\" r=\"1\" />\n <circle cx=\"4.5\" cy=\"7\" r=\"1\" />\n <circle cx=\"4.5\" cy=\"10\" r=\"1\" />\n </svg>\n </span>\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 <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 {accessDotted(row, column.field) as ReactNode}\n </td>\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 ]\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 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 { 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.0.1",
3
+ "version": "0.2.0",
4
4
  "description": "React data-grid components built on @gridkitjs/core.",
5
5
  "license": "MIT",
6
6
  "author": "Blagoja Blazhevski",
@@ -22,19 +22,12 @@
22
22
  "engines": {
23
23
  "node": ">=22"
24
24
  },
25
- "main": "./src/index.ts",
26
- "types": "./src/index.ts",
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
27
  "exports": {
28
- ".": "./src/index.ts"
29
- },
30
- "publishConfig": {
31
- "main": "./dist/index.js",
32
- "types": "./dist/index.d.ts",
33
- "exports": {
34
- ".": {
35
- "types": "./dist/index.d.ts",
36
- "import": "./dist/index.js"
37
- }
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.js"
38
31
  }
39
32
  },
40
33
  "files": [
@@ -42,18 +35,12 @@
42
35
  "LICENSE",
43
36
  "README.md"
44
37
  ],
45
- "scripts": {
46
- "build": "tsup",
47
- "typecheck": "tsc --noEmit",
48
- "lint": "eslint src",
49
- "test": "vitest run --passWithNoTests"
50
- },
51
38
  "peerDependencies": {
52
39
  "react": "^19.0.0",
53
40
  "react-dom": "^19.0.0"
54
41
  },
55
42
  "dependencies": {
56
- "@gridkitjs/core": "workspace:*"
43
+ "@gridkitjs/core": "0.2.0"
57
44
  },
58
45
  "devDependencies": {
59
46
  "@types/react": "^19.2.18",
@@ -63,5 +50,11 @@
63
50
  "tsup": "^8.5.1",
64
51
  "typescript": "^6.0.3",
65
52
  "vitest": "^4.1.10"
53
+ },
54
+ "scripts": {
55
+ "build": "tsup",
56
+ "typecheck": "tsc --noEmit",
57
+ "lint": "eslint src",
58
+ "test": "vitest run --passWithNoTests"
66
59
  }
67
- }
60
+ }