@homebound/beam 2.332.1 → 2.333.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.
@@ -1,4 +1,4 @@
1
- import { MutableRefObject } from "react";
1
+ import React, { MutableRefObject } from "react";
2
2
  import { DiscriminateUnion, GridRowKind } from "../index";
3
3
  import { GridTableApi } from "./GridTableApi";
4
4
  import { GridStyle, GridStyleDef, RowStyles } from "./TableStyles";
@@ -54,6 +54,8 @@ export type OnRowSelect<R extends Kinded> = {
54
54
  api: GridTableApi<R>;
55
55
  }) => void;
56
56
  };
57
+ type DragEventType = React.DragEvent<HTMLElement>;
58
+ export type OnRowDragEvent<R extends Kinded> = (draggedRow: GridDataRow<R>, event: DragEventType) => void;
57
59
  export interface GridTableProps<R extends Kinded, X> {
58
60
  id?: string;
59
61
  /**
@@ -129,6 +131,8 @@ export interface GridTableProps<R extends Kinded, X> {
129
131
  infiniteScroll?: InfiniteScroll;
130
132
  /** Callback for when a row is selected or unselected. */
131
133
  onRowSelect?: OnRowSelect<R>;
134
+ /** Drag & drop Callback. */
135
+ onRowDrop?: (draggedRow: GridDataRow<R>, droppedRow: GridDataRow<R>, indexOffset: number) => void;
132
136
  }
133
137
  /**
134
138
  * Renders data in our table layout.
@@ -151,3 +155,4 @@ export interface GridTableProps<R extends Kinded, X> {
151
155
  * https://docs.google.com/document/d/1DFnlkDubK4nG_GLf_hB8yp0flnSNt_3IBh5iOicuaFM/edit#heading=h.9m9cpwgeqfc9
152
156
  */
153
157
  export declare function GridTable<R extends Kinded, X extends Only<GridTableXss, X> = any>(props: GridTableProps<R, X>): import("@emotion/react/jsx-runtime").JSX.Element;
158
+ export {};
@@ -45,6 +45,7 @@ const hooks_1 = require("../../hooks");
45
45
  const useRenderCount_1 = require("../../hooks/useRenderCount");
46
46
  const utils_2 = require("../../utils");
47
47
  const Row_1 = require("./components/Row");
48
+ const RowState_1 = require("./utils/RowState");
48
49
  let runningInJest = false;
49
50
  /** Tells GridTable we're running in Jest, which forces as=virtual to be as=div, to work in jsdom. */
50
51
  function setRunningInJest() {
@@ -87,7 +88,7 @@ exports.setGridTableDefaults = setGridTableDefaults;
87
88
  */
88
89
  function GridTable(props) {
89
90
  var _a, _b, _c;
90
- const { id = "gridTable", as = "div", columns: _columns, rows, style: maybeStyle = defaults.style, rowStyles, stickyHeader = defaults.stickyHeader, stickyOffset = 0, xss, filter, filterMaxRows, fallbackMessage = "No rows found.", infoMessage, persistCollapse, resizeTarget, activeRowId, activeCellId, visibleColumnsStorageKey, infiniteScroll, onRowSelect, } = props;
91
+ const { id = "gridTable", as = "div", columns: _columns, rows, style: maybeStyle = defaults.style, rowStyles, stickyHeader = defaults.stickyHeader, stickyOffset = 0, xss, filter, filterMaxRows, fallbackMessage = "No rows found.", infoMessage, persistCollapse, resizeTarget, activeRowId, activeCellId, visibleColumnsStorageKey, infiniteScroll, onRowSelect, onRowDrop: droppedCallback, } = props;
91
92
  const columnsWithIds = (0, react_1.useMemo)(() => (0, columns_1.assignDefaultColumnIds)(_columns), [_columns]);
92
93
  // We only use this in as=virtual mode, but keep this here for rowLookup to use
93
94
  const virtuosoRef = (0, react_1.useRef)(null);
@@ -109,6 +110,12 @@ function GridTable(props) {
109
110
  // TODO: validate this eslint-disable. It was automatically ignored as part of https://app.shortcut.com/homebound-team/story/40033/enable-react-hooks-exhaustive-deps-for-react-projects
110
111
  // eslint-disable-next-line react-hooks/exhaustive-deps
111
112
  [props.api]);
113
+ const [draggedRow, _setDraggedRow] = (0, react_1.useState)(undefined);
114
+ const draggedRowRef = (0, react_1.useRef)(draggedRow);
115
+ const setDraggedRow = (row) => {
116
+ draggedRowRef.current = row;
117
+ _setDraggedRow(row);
118
+ };
112
119
  const style = (0, TableStyles_1.resolveStyles)(maybeStyle);
113
120
  const { tableState } = api;
114
121
  tableState.onRowSelect = onRowSelect;
@@ -140,6 +147,80 @@ function GridTable(props) {
140
147
  // Our column sizes use either `w` or `expandedWidth`, so see which columns are currently expanded
141
148
  const expandedColumnIds = (0, hooks_1.useComputed)(() => tableState.expandedColumnIds, [tableState]);
142
149
  const columnSizes = (0, useSetupColumnSizes_1.useSetupColumnSizes)(style, columns, resizeTarget !== null && resizeTarget !== void 0 ? resizeTarget : resizeRef, expandedColumnIds);
150
+ // allows us to unset children and grandchildren, etc.
151
+ function recursiveSetDraggedOver(rows, draggedOver) {
152
+ rows.forEach((r) => {
153
+ tableState.maybeSetRowDraggedOver(r.id, draggedOver);
154
+ if (r.children) {
155
+ recursiveSetDraggedOver(r.children, draggedOver);
156
+ }
157
+ });
158
+ }
159
+ function onDragStart(row, evt) {
160
+ if (!row.draggable || !droppedCallback) {
161
+ return;
162
+ }
163
+ evt.dataTransfer.effectAllowed = "move";
164
+ evt.dataTransfer.setData("text/plain", JSON.stringify({ row }));
165
+ setDraggedRow(row);
166
+ }
167
+ const onDragEnd = (row, evt) => {
168
+ if (!row.draggable || !droppedCallback) {
169
+ return;
170
+ }
171
+ evt.preventDefault();
172
+ recursiveSetDraggedOver(rows, RowState_1.DraggedOver.None);
173
+ };
174
+ const onDrop = (row, evt) => {
175
+ if (!row.draggable || !droppedCallback) {
176
+ return;
177
+ }
178
+ evt.preventDefault();
179
+ if (droppedCallback) {
180
+ recursiveSetDraggedOver(rows, RowState_1.DraggedOver.None);
181
+ try {
182
+ const draggedRowData = JSON.parse(evt.dataTransfer.getData("text/plain")).row;
183
+ if (draggedRowData.id === row.id) {
184
+ return;
185
+ }
186
+ const isBelow = (0, utils_1.isCursorBelowMidpoint)(evt.currentTarget, evt.clientY);
187
+ droppedCallback(draggedRowData, row, isBelow ? 1 : 0);
188
+ }
189
+ catch (e) {
190
+ console.error(e.message, e.stack);
191
+ }
192
+ }
193
+ };
194
+ const onDragEnter = (row, evt) => {
195
+ if (!row.draggable || !droppedCallback) {
196
+ return;
197
+ }
198
+ evt.preventDefault();
199
+ // set flags for css spacer
200
+ recursiveSetDraggedOver(rows, RowState_1.DraggedOver.None);
201
+ if (draggedRowRef.current) {
202
+ if (draggedRowRef.current.id === row.id) {
203
+ return;
204
+ }
205
+ // determine above or below
206
+ const isBelow = (0, utils_1.isCursorBelowMidpoint)(evt.currentTarget, evt.clientY);
207
+ tableState.maybeSetRowDraggedOver(row.id, isBelow ? RowState_1.DraggedOver.Below : RowState_1.DraggedOver.Above, draggedRowRef.current);
208
+ }
209
+ };
210
+ const onDragOver = (row, evt) => {
211
+ if (!row.draggable || !droppedCallback) {
212
+ return;
213
+ }
214
+ evt.preventDefault();
215
+ if (draggedRowRef.current) {
216
+ if (draggedRowRef.current.id === row.id) {
217
+ return;
218
+ }
219
+ // continuously determine above or below
220
+ const isBelow = (0, utils_1.isCursorBelowMidpoint)(evt.currentTarget, evt.clientY);
221
+ tableState.maybeSetRowDraggedOver(row.id, isBelow ? RowState_1.DraggedOver.Below : RowState_1.DraggedOver.Above, draggedRowRef.current);
222
+ }
223
+ };
143
224
  // Flatten, hide-if-filtered, hide-if-collapsed, and component-ize the sorted rows.
144
225
  const [tableHeadRows, visibleDataRows, keptSelectedRows, tooManyClientSideRows] = (0, hooks_1.useComputed)(() => {
145
226
  // Split out the header rows from the data rows so that we can put an `infoMessage` in between them (if needed).
@@ -152,7 +233,7 @@ function GridTable(props) {
152
233
  const hasExpandableHeader = visibleRows.some((rs) => rs.row.id === utils_1.EXPANDABLE_HEADER);
153
234
  // Get the flat list or rows from the header down...
154
235
  visibleRows.forEach((rs) => {
155
- const row = ((0, jsx_runtime_1.jsx)(Row_1.Row, { ...{
236
+ const row = ((0, jsx_runtime_1.jsx)(Row_1.Row, { onDragStart: onDragStart, onDragOver: onDragOver, onDragEnd: onDragEnd, onDrop: onDrop, onDragEnter: onDragEnter, ...{
156
237
  as,
157
238
  rs,
158
239
  style,
@@ -13,6 +13,11 @@ interface RowProps<R extends Kinded> {
13
13
  cellHighlight: boolean;
14
14
  omitRowHover: boolean;
15
15
  hasExpandableHeader: boolean;
16
+ onDragStart?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
17
+ onDragEnd?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
18
+ onDrop?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
19
+ onDragEnter?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
20
+ onDragOver?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
16
21
  }
17
22
  declare function RowImpl<R extends Kinded, S>(props: RowProps<R>): ReactElement;
18
23
  /**
@@ -64,5 +69,7 @@ export type GridDataRow<R extends Kinded> = {
64
69
  selectable?: false;
65
70
  /** Whether this row should infer its selected state based on its children's selected state */
66
71
  inferSelectedState?: false;
72
+ /** Whether this row is draggable, usually to allow drag & drop reordering of rows */
73
+ draggable?: boolean;
67
74
  } & IfAny<R, AnyObject, DiscriminateUnion<R, "kind", R["kind"]>>;
68
75
  export {};
@@ -6,6 +6,7 @@ const mobx_react_1 = require("mobx-react");
6
6
  const react_1 = require("react");
7
7
  const cell_1 = require("./cell");
8
8
  const KeptGroupRow_1 = require("./KeptGroupRow");
9
+ const RowState_1 = require("../utils/RowState");
9
10
  const sortRows_1 = require("../utils/sortRows");
10
11
  const TableState_1 = require("../utils/TableState");
11
12
  const utils_1 = require("../utils/utils");
@@ -14,7 +15,7 @@ const utils_2 = require("../../../utils");
14
15
  // We extract Row to its own mini-component primarily so we can React.memo'ize it.
15
16
  function RowImpl(props) {
16
17
  var _a, _b, _c;
17
- const { as, rs, style, rowStyles, columnSizes, getCount, cellHighlight, omitRowHover, hasExpandableHeader, ...others } = props;
18
+ const { as, rs, style, rowStyles, columnSizes, getCount, cellHighlight, omitRowHover, hasExpandableHeader, onDragStart, onDragEnd, onDrop, onDragEnter, onDragOver, ...others } = props;
18
19
  const { tableState } = (0, react_1.useContext)(TableState_1.TableStateContext);
19
20
  // We're wrapped in observer, so can access these without useComputeds
20
21
  const { api, visibleColumns: columns } = tableState;
@@ -32,6 +33,7 @@ function RowImpl(props) {
32
33
  const rowStyleCellCss = (0, utils_1.maybeApplyFunction)(row, rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.cellCss);
33
34
  const levelIndent = style.levels && ((_b = style.levels[level]) === null || _b === void 0 ? void 0 : _b.rowIndent);
34
35
  const rowCss = {
36
+ ...Css_1.Css.add("transition", "padding 0.5s ease-in-out").$,
35
37
  ...(!utils_1.reservedRowKinds.includes(row.kind) && style.nonHeaderRowCss),
36
38
  // Optionally include the row hover styles, by default they should be turned on.
37
39
  ...(showRowHoverColor && {
@@ -54,6 +56,8 @@ function RowImpl(props) {
54
56
  [`:hover > .${revealOnRowHoverClass} > *`]: Css_1.Css.visible.$,
55
57
  },
56
58
  ...(isLastKeptRow && Css_1.Css.addIn("&>*", style.keptLastRowCss).$),
59
+ ...(rs.isDraggedOver === RowState_1.DraggedOver.Above && Css_1.Css.add("paddingTop", "35px").$),
60
+ ...(rs.isDraggedOver === RowState_1.DraggedOver.Below && Css_1.Css.add("paddingBottom", "35px").$),
57
61
  };
58
62
  let currentColspan = 1;
59
63
  // Keep a running count of how many expanded columns are being shown.
@@ -61,7 +65,12 @@ function RowImpl(props) {
61
65
  let foundFirstContentColumn = false;
62
66
  let minStickyLeftOffset = 0;
63
67
  let expandColumnHidden = false;
64
- return ((0, jsx_runtime_1.jsx)(RowTag, { css: rowCss, ...others, "data-gridrow": true, ...getCount(row.id), children: isKeptGroupRow ? ((0, jsx_runtime_1.jsx)(KeptGroupRow_1.KeptGroupRow, { as: as, style: style, columnSizes: columnSizes, row: row, colSpan: columns.length })) : (columns.map((column, columnIndex) => {
68
+ // used to render the whole row when dragging with the handle
69
+ const ref = (0, react_1.useRef)(null);
70
+ return ((0, jsx_runtime_1.jsx)(RowTag, { css: rowCss, ...others, "data-gridrow": true, ...getCount(row.id),
71
+ // these events are necessary to get the dragged-over row for the drop event
72
+ // and spacer styling
73
+ onDrop: (evt) => onDrop === null || onDrop === void 0 ? void 0 : onDrop(row, evt), onDragEnter: (evt) => onDragEnter === null || onDragEnter === void 0 ? void 0 : onDragEnter(row, evt), onDragOver: (evt) => onDragOver === null || onDragOver === void 0 ? void 0 : onDragOver(row, evt), ref: ref, children: isKeptGroupRow ? ((0, jsx_runtime_1.jsx)(KeptGroupRow_1.KeptGroupRow, { as: as, style: style, columnSizes: columnSizes, row: row, colSpan: columns.length })) : (columns.map((column, columnIndex) => {
65
74
  var _a, _b, _c, _d;
66
75
  // If the expandable column was hidden, then we need to look at the previous column to format the `expandHeader` and 'header' kinds correctly.
67
76
  const maybeExpandedColumn = expandColumnHidden ? columns[columnIndex - 1] : column;
@@ -111,7 +120,14 @@ function RowImpl(props) {
111
120
  currentColspan -= 1;
112
121
  return null;
113
122
  }
114
- const maybeContent = (0, utils_1.applyRowFn)(column, row, rowApi, level, isExpanded);
123
+ const maybeContent = (0, utils_1.applyRowFn)(column, row, rowApi, level, isExpanded, {
124
+ rowRenderRef: ref,
125
+ onDragStart,
126
+ onDragEnd,
127
+ onDrop,
128
+ onDragEnter,
129
+ onDragOver,
130
+ });
115
131
  // Only use the `numExpandedColumns` as the `colspan` when rendering the "Expandable Header"
116
132
  currentColspan =
117
133
  (0, utils_1.isGridCellContent)(maybeContent) && typeof maybeContent.colspan === "number"
@@ -3,6 +3,11 @@ import { GridDataRow } from "../components/Row";
3
3
  import { GridRowApi } from "../GridTableApi";
4
4
  import { RowStates } from "./RowStates";
5
5
  import { SelectedState } from "./TableState";
6
+ export declare enum DraggedOver {
7
+ None = 0,
8
+ Above = 1,
9
+ Below = 2
10
+ }
6
11
  /**
7
12
  * A reactive/observable state of each GridDataRow's current behavior.
8
13
  *
@@ -22,6 +27,8 @@ export declare class RowState<R extends Kinded> {
22
27
  selected: boolean;
23
28
  /** Whether we are collapsed. */
24
29
  collapsed: boolean;
30
+ /** Whether we are dragged over. */
31
+ isDraggedOver: DraggedOver;
25
32
  /**
26
33
  * Whether our `row` had been in `props.rows`, but then removed _while being
27
34
  * selected_, i.e. potentially by server-side filters.
@@ -1,8 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RowState = void 0;
3
+ exports.RowState = exports.DraggedOver = void 0;
4
4
  const mobx_1 = require("mobx");
5
5
  const utils_1 = require("./utils");
6
+ var DraggedOver;
7
+ (function (DraggedOver) {
8
+ DraggedOver[DraggedOver["None"] = 0] = "None";
9
+ DraggedOver[DraggedOver["Above"] = 1] = "Above";
10
+ DraggedOver[DraggedOver["Below"] = 2] = "Below";
11
+ })(DraggedOver = exports.DraggedOver || (exports.DraggedOver = {}));
6
12
  /**
7
13
  * A reactive/observable state of each GridDataRow's current behavior.
8
14
  *
@@ -20,6 +26,8 @@ class RowState {
20
26
  this.selected = false;
21
27
  /** Whether we are collapsed. */
22
28
  this.collapsed = false;
29
+ /** Whether we are dragged over. */
30
+ this.isDraggedOver = DraggedOver.None;
23
31
  /**
24
32
  * Whether our `row` had been in `props.rows`, but then removed _while being
25
33
  * selected_, i.e. potentially by server-side filters.
@@ -1,6 +1,6 @@
1
1
  import { Kinded } from "../../..";
2
2
  import { GridDataRow } from "../components/Row";
3
- import { RowState } from "./RowState";
3
+ import { DraggedOver, RowState } from "./RowState";
4
4
  import { RowStorage } from "./RowStorage";
5
5
  import { TableState } from "./TableState";
6
6
  /**
@@ -36,4 +36,5 @@ export declare class RowStates<R extends Kinded> {
36
36
  private createHeaderRow;
37
37
  /** Create our synthetic "group row" for kept rows, that users never pass in, but we self-inject as needed. */
38
38
  private createKeptGroupRow;
39
+ maybeSetRowDraggedOver(id: string, draggedOver: DraggedOver, requireSameParentRow?: GridDataRow<R> | undefined): void;
39
40
  }
@@ -165,6 +165,27 @@ class RowStates {
165
165
  rs.children = [];
166
166
  return rs;
167
167
  }
168
+ maybeSetRowDraggedOver(id, draggedOver, requireSameParentRow = undefined) {
169
+ var _a, _b, _c, _d, _e, _f;
170
+ const rs = this.get(id);
171
+ if (requireSameParentRow) {
172
+ const requireParentRowState = this.get(requireSameParentRow.id);
173
+ if (((_b = (_a = requireParentRowState.parent) === null || _a === void 0 ? void 0 : _a.row) === null || _b === void 0 ? void 0 : _b.id) !== ((_d = (_c = rs.parent) === null || _c === void 0 ? void 0 : _c.row) === null || _d === void 0 ? void 0 : _d.id))
174
+ return;
175
+ }
176
+ // if this is an expanded parent and draggedOver is Below then we want to set this on this rows bottom-most child
177
+ if (!rs.collapsed && rs.children && ((_e = rs.children) === null || _e === void 0 ? void 0 : _e.length) > 0 && draggedOver === RowState_1.DraggedOver.Below) {
178
+ let rowState = rs;
179
+ // recursively find the bottom-most child
180
+ while (rowState.children && ((_f = rowState.children) === null || _f === void 0 ? void 0 : _f.length) > 0) {
181
+ rowState = rowState.children[rowState.children.length - 1];
182
+ }
183
+ rowState.isDraggedOver = draggedOver;
184
+ return;
185
+ }
186
+ // this allows a single-row re-render
187
+ rs.isDraggedOver = draggedOver;
188
+ }
168
189
  }
169
190
  exports.RowStates = RowStates;
170
191
  const missingHeader = { kind: "header", id: "header", data: "MISSING" };
@@ -4,7 +4,7 @@ import { GridDataRow } from "../components/Row";
4
4
  import { GridSortConfig } from "../GridTable";
5
5
  import { GridTableApi } from "../GridTableApi";
6
6
  import { Direction, GridColumnWithId } from "../types";
7
- import { RowState } from "./RowState";
7
+ import { DraggedOver, RowState } from "./RowState";
8
8
  export type SelectedState = "checked" | "unchecked" | "partial";
9
9
  /**
10
10
  * Stores the collapsed & selected state of rows.
@@ -76,6 +76,7 @@ export declare class TableState<R extends Kinded> {
76
76
  isCollapsed(id: string): boolean;
77
77
  toggleCollapsed(id: string): void;
78
78
  deleteRows(ids: string[]): void;
79
+ maybeSetRowDraggedOver(id: string, draggedOver: DraggedOver, requireSameParentRow?: GridDataRow<R> | undefined): void;
79
80
  }
80
81
  /** Provides a context for rows to access their table's `TableState`. */
81
82
  export declare const TableStateContext: React.Context<{
@@ -212,6 +212,9 @@ class TableState {
212
212
  this.rows = this.rows.filter((row) => !ids.includes(row.id));
213
213
  this.rowStates.delete(ids);
214
214
  }
215
+ maybeSetRowDraggedOver(id, draggedOver, requireSameParentRow = undefined) {
216
+ this.rowStates.maybeSetRowDraggedOver(id, draggedOver, requireSameParentRow);
217
+ }
215
218
  }
216
219
  exports.TableState = TableState;
217
220
  /** Provides a context for rows to access their table's `TableState`. */
@@ -32,3 +32,4 @@ export declare function calcColumnSizes<R extends Kinded>(columns: GridColumnWit
32
32
  /** Assign column ids if missing. */
33
33
  export declare function assignDefaultColumnIds<T extends Kinded>(columns: GridColumn<T>[]): GridColumnWithId<T>[];
34
34
  export declare const generateColumnId: (columnIndex: number) => string;
35
+ export declare function dragHandleColumn<T extends Kinded>(columnDef?: Partial<GridColumn<T>>): GridColumn<T>;
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateColumnId = exports.assignDefaultColumnIds = exports.calcColumnSizes = exports.collapseColumn = exports.selectColumn = exports.actionColumn = exports.numericColumn = exports.dateColumn = exports.column = void 0;
3
+ exports.dragHandleColumn = exports.generateColumnId = exports.assignDefaultColumnIds = exports.calcColumnSizes = exports.collapseColumn = exports.selectColumn = exports.actionColumn = exports.numericColumn = exports.dateColumn = exports.column = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const CollapseToggle_1 = require("../components/CollapseToggle");
6
6
  const SelectToggle_1 = require("../components/SelectToggle");
7
7
  const types_1 = require("../types");
8
8
  const utils_1 = require("./utils");
9
9
  const utils_2 = require("../../../utils");
10
+ const src_1 = require("../../..");
11
+ const Css_1 = require("../../../Css");
10
12
  /** Provides default styling for a GridColumn representing a Date. */
11
13
  function column(columnDef) {
12
14
  return { ...columnDef };
@@ -193,3 +195,43 @@ function assignDefaultColumnIds(columns) {
193
195
  exports.assignDefaultColumnIds = assignDefaultColumnIds;
194
196
  const generateColumnId = (columnIndex) => `beamColumn_${columnIndex}`;
195
197
  exports.generateColumnId = generateColumnId;
198
+ function dragHandleColumn(columnDef) {
199
+ const base = {
200
+ ...nonKindDefaults(),
201
+ id: "beamDragHandleColumn",
202
+ clientSideSort: false,
203
+ align: "center",
204
+ // Defining `w: 40px` to accommodate for the `16px` wide checkbox and `12px` of padding on either side.
205
+ w: "40px",
206
+ wrapAction: false,
207
+ isAction: true,
208
+ expandColumns: undefined,
209
+ // Select Column should not display the select toggle for `expandableHeader` or `totals` row kinds
210
+ expandableHeader: utils_1.emptyCell,
211
+ totals: utils_1.emptyCell,
212
+ // Use any of the user's per-row kind methods if they have them.
213
+ ...columnDef,
214
+ };
215
+ // return newMethodMissingProxy(base, (key) => {
216
+ // return (data: any, { row, level }: { row: GridDataRow<any>; level: number }) => ({
217
+ // content: <CollapseToggle row={row} compact={level > 0} />,
218
+ // });
219
+ // }) as any;
220
+ return (0, utils_2.newMethodMissingProxy)(base, (key) => {
221
+ return (data, { row, dragData }) => {
222
+ if (!dragData)
223
+ return;
224
+ const { rowRenderRef: ref, onDragStart, onDragEnd, onDrop, onDragEnter, onDragOver } = dragData;
225
+ return {
226
+ // how do we get the callbacks and the ref here?
227
+ // inject them into the row in the Row component?
228
+ content: row.draggable ? ((0, jsx_runtime_1.jsx)("div", { draggable: row.draggable, onDragStart: (evt) => {
229
+ // show the whole row being dragged when dragging with the handle
230
+ ref.current && evt.dataTransfer.setDragImage(ref.current, 0, 0);
231
+ return onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(row, evt);
232
+ }, onDragEnd: (evt) => onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(row, evt), onDrop: (evt) => onDrop === null || onDrop === void 0 ? void 0 : onDrop(row, evt), onDragEnter: (evt) => onDragEnter === null || onDragEnter === void 0 ? void 0 : onDragEnter(row, evt), onDragOver: (evt) => onDragOver === null || onDragOver === void 0 ? void 0 : onDragOver(row, evt), css: Css_1.Css.mh100.ma.$, children: (0, jsx_runtime_1.jsx)(src_1.Icon, { icon: "drag" }) })) : undefined,
233
+ };
234
+ };
235
+ });
236
+ }
237
+ exports.dragHandleColumn = dragHandleColumn;
@@ -8,8 +8,16 @@ import { Properties } from "../../../Css";
8
8
  /** If a column def return just string text for a given row, apply some default styling. */
9
9
  export declare function toContent(maybeContent: ReactNode | GridCellContent, isHeader: boolean, canSortColumn: boolean, isClientSideSorting: boolean, style: GridStyle, as: RenderAs, alignment: GridCellAlignment, column: GridColumnWithId<any>, isExpandableHeader: boolean, isExpandable: boolean, minStickyLeftOffset: number, isKeptSelectedRow: boolean): ReactNode;
10
10
  export declare function isGridCellContent(content: ReactNode | GridCellContent): content is GridCellContent;
11
+ export type DragData<R extends Kinded> = {
12
+ rowRenderRef: React.RefObject<HTMLTableRowElement>;
13
+ onDragStart?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
14
+ onDragEnd?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
15
+ onDrop?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
16
+ onDragEnter?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
17
+ onDragOver?: (row: GridDataRow<R>, event: React.DragEvent<HTMLElement>) => void;
18
+ };
11
19
  /** Return the content for a given column def applied to a given row. */
12
- export declare function applyRowFn<R extends Kinded>(column: GridColumnWithId<R>, row: GridDataRow<R>, api: GridRowApi<R>, level: number, expanded: boolean): ReactNode | GridCellContent;
20
+ export declare function applyRowFn<R extends Kinded>(column: GridColumnWithId<R>, row: GridDataRow<R>, api: GridRowApi<R>, level: number, expanded: boolean, dragData?: DragData<R>): ReactNode | GridCellContent;
13
21
  export declare const ASC: "ASC";
14
22
  export declare const DESC: "DESC";
15
23
  export declare const emptyCell: GridCellContent;
@@ -34,3 +42,9 @@ export declare const zIndices: {
34
42
  };
35
43
  /** Loads an array from sessionStorage, if it exists, or `undefined`. */
36
44
  export declare function loadArrayOrUndefined(key: string): any;
45
+ export declare function insertAtIndex<T>(array: Array<T>, element: T, index: number): Array<T>;
46
+ export declare function isCursorBelowMidpoint(target: HTMLElement, clientY: number): boolean;
47
+ export declare function recursivelyGetContainingRow<R extends Kinded>(rowId: string, rowArray: GridDataRow<R>[], parent?: GridDataRow<R>): {
48
+ array: GridDataRow<R>[];
49
+ parent: GridDataRow<R> | undefined;
50
+ } | undefined;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadArrayOrUndefined = exports.zIndices = exports.reservedRowKinds = exports.KEPT_GROUP = exports.EXPANDABLE_HEADER = exports.TOTALS = exports.HEADER = exports.matchesFilter = exports.maybeApplyFunction = exports.getJustification = exports.getAlignment = exports.getFirstOrLastCellCss = exports.emptyCell = exports.DESC = exports.ASC = exports.applyRowFn = exports.isGridCellContent = exports.toContent = void 0;
3
+ exports.recursivelyGetContainingRow = exports.isCursorBelowMidpoint = exports.insertAtIndex = exports.loadArrayOrUndefined = exports.zIndices = exports.reservedRowKinds = exports.KEPT_GROUP = exports.EXPANDABLE_HEADER = exports.TOTALS = exports.HEADER = exports.matchesFilter = exports.maybeApplyFunction = exports.getJustification = exports.getAlignment = exports.getFirstOrLastCellCss = exports.emptyCell = exports.DESC = exports.ASC = exports.applyRowFn = exports.isGridCellContent = exports.toContent = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const Icon_1 = require("../../Icon");
6
6
  const ExpandableHeader_1 = require("../components/ExpandableHeader");
@@ -72,12 +72,12 @@ function isContentEmpty(content) {
72
72
  return emptyValues.includes(content);
73
73
  }
74
74
  /** Return the content for a given column def applied to a given row. */
75
- function applyRowFn(column, row, api, level, expanded) {
75
+ function applyRowFn(column, row, api, level, expanded, dragData) {
76
76
  // Usually this is a function to apply against the row, but sometimes it's a hard-coded value, i.e. for headers
77
77
  const maybeContent = column[row.kind];
78
78
  if (typeof maybeContent === "function") {
79
79
  // Auto-destructure data
80
- return maybeContent(row["data"], { row: row, api, level, expanded });
80
+ return maybeContent(row["data"], { row: row, api, level, expanded, dragData });
81
81
  }
82
82
  else {
83
83
  return maybeContent;
@@ -172,3 +172,31 @@ function loadArrayOrUndefined(key) {
172
172
  return ids ? JSON.parse(ids) : undefined;
173
173
  }
174
174
  exports.loadArrayOrUndefined = loadArrayOrUndefined;
175
+ function insertAtIndex(array, element, index) {
176
+ return [...array.slice(0, index), element, ...array.slice(index, array.length)];
177
+ }
178
+ exports.insertAtIndex = insertAtIndex;
179
+ function isCursorBelowMidpoint(target, clientY) {
180
+ const style = window.getComputedStyle(target);
181
+ const rect = target.getBoundingClientRect();
182
+ const pt = parseInt(style.getPropertyValue("padding-top")) / 2;
183
+ const pb = parseInt(style.getPropertyValue("padding-bottom"));
184
+ return clientY > rect.top + pt + (rect.height - pb) / 2;
185
+ }
186
+ exports.isCursorBelowMidpoint = isCursorBelowMidpoint;
187
+ function recursivelyGetContainingRow(rowId, rowArray, parent) {
188
+ if (rowArray.some((row) => row.id === rowId)) {
189
+ return { array: rowArray, parent };
190
+ }
191
+ for (let i = 0; i < rowArray.length; i++) {
192
+ if (!rowArray[i].children) {
193
+ continue;
194
+ }
195
+ const result = recursivelyGetContainingRow(rowId, rowArray[i].children, rowArray[i]);
196
+ if (result) {
197
+ return result;
198
+ }
199
+ }
200
+ return undefined;
201
+ }
202
+ exports.recursivelyGetContainingRow = recursivelyGetContainingRow;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.332.1",
3
+ "version": "2.333.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",