@homebound/beam 2.332.1 → 2.333.1
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/components/Table/GridTable.d.ts +6 -1
- package/dist/components/Table/GridTable.js +83 -2
- package/dist/components/Table/components/Row.d.ts +7 -0
- package/dist/components/Table/components/Row.js +19 -3
- package/dist/components/Table/utils/RowState.d.ts +7 -0
- package/dist/components/Table/utils/RowState.js +9 -1
- package/dist/components/Table/utils/RowStates.d.ts +2 -1
- package/dist/components/Table/utils/RowStates.js +21 -0
- package/dist/components/Table/utils/TableState.d.ts +2 -1
- package/dist/components/Table/utils/TableState.js +3 -0
- package/dist/components/Table/utils/columns.d.ts +1 -0
- package/dist/components/Table/utils/columns.js +43 -1
- package/dist/components/Table/utils/utils.d.ts +15 -1
- package/dist/components/Table/utils/utils.js +31 -3
- package/dist/inputs/TreeSelectField/TreeSelectField.js +16 -3
- package/dist/inputs/internal/ComboBoxBase.js +9 -7
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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;
|
|
@@ -115,13 +115,26 @@ function TreeSelectFieldBase(props) {
|
|
|
115
115
|
return areAllSelected;
|
|
116
116
|
}
|
|
117
117
|
initialOptions.forEach(areAllChildrenSelected);
|
|
118
|
+
// Given a child option, determine if the parent is selected.
|
|
119
|
+
const isParentSelected = (option) => {
|
|
120
|
+
var _a;
|
|
121
|
+
const parents = (_a = (0, utils_1.findOption)(initialOptions, (0, Value_1.valueToKey)(getOptionValue(option)), getOptionValue)) === null || _a === void 0 ? void 0 : _a.parents;
|
|
122
|
+
if (!parents)
|
|
123
|
+
return false;
|
|
124
|
+
return parents.some((parent) => selectedKeys.includes((0, Value_1.valueToKey)(getOptionValue(parent))));
|
|
125
|
+
};
|
|
118
126
|
return {
|
|
119
127
|
selectedKeys,
|
|
120
128
|
inputValue: selectedOptions.length === 1
|
|
121
129
|
? getOptionLabel(selectedOptions[0])
|
|
122
|
-
: selectedOptions.length
|
|
123
|
-
?
|
|
124
|
-
|
|
130
|
+
: isReadOnly && selectedOptions.length > 0
|
|
131
|
+
? selectedOptions
|
|
132
|
+
.filter((o) => !isParentSelected(o))
|
|
133
|
+
.map(getOptionLabel)
|
|
134
|
+
.join(", ")
|
|
135
|
+
: selectedOptions.length === 0
|
|
136
|
+
? nothingSelectedText
|
|
137
|
+
: "",
|
|
125
138
|
filteredOptions,
|
|
126
139
|
selectedOptions,
|
|
127
140
|
allOptions: initialOptions,
|
|
@@ -56,7 +56,7 @@ function ComboBoxBase(props) {
|
|
|
56
56
|
// Do a one-time initialize of fieldState
|
|
57
57
|
const [fieldState, setFieldState] = (0, react_1.useState)(() => {
|
|
58
58
|
return {
|
|
59
|
-
inputValue: getInputValue(selectedOptions, getOptionLabel, multiselect, nothingSelectedText),
|
|
59
|
+
inputValue: getInputValue(selectedOptions, getOptionLabel, multiselect, nothingSelectedText, isReadOnly),
|
|
60
60
|
searchValue: undefined,
|
|
61
61
|
optionsLoading: false,
|
|
62
62
|
};
|
|
@@ -179,10 +179,10 @@ function ComboBoxBase(props) {
|
|
|
179
179
|
else {
|
|
180
180
|
setFieldState((prevState) => ({
|
|
181
181
|
...prevState,
|
|
182
|
-
inputValue: getInputValue(selectedOptions, getOptionLabel, multiselect, nothingSelectedText),
|
|
182
|
+
inputValue: getInputValue(selectedOptions, getOptionLabel, multiselect, nothingSelectedText, isReadOnly),
|
|
183
183
|
}));
|
|
184
184
|
}
|
|
185
|
-
}, [state.isOpen, selectedOptions, getOptionLabel, multiselect, nothingSelectedText]);
|
|
185
|
+
}, [state.isOpen, selectedOptions, getOptionLabel, multiselect, nothingSelectedText, isReadOnly]);
|
|
186
186
|
// For the most part, the returned props contain `aria-*` and `id` attributes for accessibility purposes.
|
|
187
187
|
const { buttonProps: triggerProps, inputProps, listBoxProps, labelProps, } = (0, react_aria_1.useComboBox)({
|
|
188
188
|
...comboBoxProps,
|
|
@@ -213,12 +213,14 @@ function ComboBoxBase(props) {
|
|
|
213
213
|
return ((0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.fdc.w100.maxw(fieldMaxWidth).if(labelStyle === "left").maxw100.$, ref: comboBoxRef, children: [(0, jsx_runtime_1.jsx)(ComboBoxInput_1.ComboBoxInput, { ...otherProps, fullWidth: fullWidth, buttonProps: buttonProps, buttonRef: triggerRef, inputProps: inputProps, inputRef: inputRef, inputWrapRef: inputWrapRef, listBoxRef: listBoxRef, state: state, labelProps: labelProps, selectedOptions: selectedOptions, getOptionValue: getOptionValue, getOptionLabel: getOptionLabel, contrast: contrast, nothingSelectedText: nothingSelectedText, borderless: borderless, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), resetField: resetField }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: triggerRef, popoverRef: popoverRef, positionProps: positionProps, onClose: () => state.close(), isOpen: state.isOpen, minWidth: 200, children: (0, jsx_runtime_1.jsx)(ListBox_1.ListBox, { ...listBoxProps, positionProps: positionProps, state: state, listBoxRef: listBoxRef, selectedOptions: selectedOptions, getOptionLabel: getOptionLabel, getOptionValue: (o) => (0, Value_1.valueToKey)(getOptionValue(o)), contrast: contrast, horizontalLayout: labelStyle === "left", loading: fieldState.optionsLoading, disabledOptionsWithReasons: disabledOptionsWithReasons }) }))] }));
|
|
214
214
|
}
|
|
215
215
|
exports.ComboBoxBase = ComboBoxBase;
|
|
216
|
-
function getInputValue(selectedOptions, getOptionLabel, multiselect, nothingSelectedText) {
|
|
216
|
+
function getInputValue(selectedOptions, getOptionLabel, multiselect, nothingSelectedText, readOnly) {
|
|
217
217
|
return selectedOptions.length === 1
|
|
218
218
|
? getOptionLabel(selectedOptions[0])
|
|
219
|
-
:
|
|
220
|
-
?
|
|
221
|
-
:
|
|
219
|
+
: readOnly && selectedOptions.length > 0
|
|
220
|
+
? selectedOptions.map(getOptionLabel).join(", ")
|
|
221
|
+
: multiselect && selectedOptions.length === 0
|
|
222
|
+
? nothingSelectedText
|
|
223
|
+
: "";
|
|
222
224
|
}
|
|
223
225
|
/** Transforms/simplifies `optionsOrLoad` into just options, with unsetLabel maybe added. */
|
|
224
226
|
function initializeOptions(optionsOrLoad, getOptionValue, unsetLabel) {
|