@homebound/beam 2.375.0 → 2.377.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/components/Table/GridTable.js +9 -5
- package/dist/components/Table/GridTableApi.d.ts +4 -3
- package/dist/components/Table/GridTableApi.js +12 -6
- package/dist/components/Table/index.d.ts +1 -1
- package/dist/components/Table/index.js +2 -1
- package/dist/components/Table/utils/GridRowLookup.d.ts +8 -3
- package/dist/components/Table/utils/GridRowLookup.js +15 -1
- package/dist/inputs/internal/ComboBoxBase.js +1 -16
- package/package.json +1 -1
|
@@ -92,13 +92,15 @@ function GridTable(props) {
|
|
|
92
92
|
const columnsWithIds = (0, react_1.useMemo)(() => (0, columns_1.assignDefaultColumnIds)(_columns), [_columns]);
|
|
93
93
|
// We only use this in as=virtual mode, but keep this here for rowLookup to use
|
|
94
94
|
const virtuosoRef = (0, react_1.useRef)(null);
|
|
95
|
+
// Stores the current rendered range of rows from virtuoso (used for determining if we can skip re-scrolling to a row if already in view)
|
|
96
|
+
const virtuosoRangeRef = (0, react_1.useRef)(null);
|
|
95
97
|
// Use this ref to watch for changes in the GridTable's container and resize columns accordingly.
|
|
96
98
|
const resizeRef = (0, react_1.useRef)(null);
|
|
97
99
|
const api = (0, react_1.useMemo)(() => {
|
|
98
100
|
var _a;
|
|
99
101
|
// Let the user pass in their own api handle, otherwise make our own
|
|
100
102
|
const api = (_a = props.api) !== null && _a !== void 0 ? _a : new GridTableApi_1.GridTableApiImpl();
|
|
101
|
-
api.init(persistCollapse, virtuosoRef);
|
|
103
|
+
api.init(persistCollapse, virtuosoRef, virtuosoRangeRef);
|
|
102
104
|
api.setActiveRowId(activeRowId);
|
|
103
105
|
api.setActiveCellId(activeCellId);
|
|
104
106
|
// Push the initial columns directly into tableState, b/c that is what
|
|
@@ -294,7 +296,7 @@ function GridTable(props) {
|
|
|
294
296
|
// behave semantically the same as `as=div` did for its tests.
|
|
295
297
|
const _as = as === "virtual" && runningInJest ? "div" : as;
|
|
296
298
|
const rowStateContext = (0, react_1.useMemo)(() => ({ tableState: tableState }), [tableState]);
|
|
297
|
-
return ((0, jsx_runtime_1.jsx)(TableState_1.TableStateContext.Provider, { value: rowStateContext, children: (0, jsx_runtime_1.jsxs)(PresentationContext_1.PresentationProvider, { fieldProps: fieldProps, wrap: (_d = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _d === void 0 ? void 0 : _d.wrap, children: [(0, jsx_runtime_1.jsx)("div", { ref: resizeRef, css: (0, components_1.getTableRefWidthStyles)(as === "virtual") }), renders[_as](style, id, columns, visibleDataRows, keptSelectedRows, firstRowMessage, stickyHeader, xss, virtuosoRef, tableHeadRows, stickyOffset, infiniteScroll)] }) }));
|
|
299
|
+
return ((0, jsx_runtime_1.jsx)(TableState_1.TableStateContext.Provider, { value: rowStateContext, children: (0, jsx_runtime_1.jsxs)(PresentationContext_1.PresentationProvider, { fieldProps: fieldProps, wrap: (_d = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _d === void 0 ? void 0 : _d.wrap, children: [(0, jsx_runtime_1.jsx)("div", { ref: resizeRef, css: (0, components_1.getTableRefWidthStyles)(as === "virtual") }), renders[_as](style, id, columns, visibleDataRows, keptSelectedRows, firstRowMessage, stickyHeader, xss, virtuosoRef, virtuosoRangeRef, tableHeadRows, stickyOffset, infiniteScroll)] }) }));
|
|
298
300
|
}
|
|
299
301
|
// Determine which HTML element to use to build the GridTable
|
|
300
302
|
const renders = {
|
|
@@ -303,7 +305,7 @@ const renders = {
|
|
|
303
305
|
virtual: renderVirtual,
|
|
304
306
|
};
|
|
305
307
|
/** Renders table using divs with flexbox rows, which is the default render */
|
|
306
|
-
function renderDiv(style, id, columns, visibleDataRows, keptSelectedRows, firstRowMessage, stickyHeader, xss, _virtuosoRef, tableHeadRows, stickyOffset, _infiniteScroll) {
|
|
308
|
+
function renderDiv(style, id, columns, visibleDataRows, keptSelectedRows, firstRowMessage, stickyHeader, xss, _virtuosoRef, _virtuosoRangeRef, tableHeadRows, stickyOffset, _infiniteScroll) {
|
|
307
309
|
return ((0, jsx_runtime_1.jsxs)("div", { css: {
|
|
308
310
|
// Use `fit-content` to ensure the width of the table takes up the full width of its content.
|
|
309
311
|
// Otherwise, the table's width would be that of its container, which may not be as wide as the table itself.
|
|
@@ -323,7 +325,7 @@ function renderDiv(style, id, columns, visibleDataRows, keptSelectedRows, firstR
|
|
|
323
325
|
}, children: [keptSelectedRows, firstRowMessage && ((0, jsx_runtime_1.jsx)("div", { css: { ...style.firstRowMessageCss }, "data-gridrow": true, children: firstRowMessage })), visibleDataRows] })] }));
|
|
324
326
|
}
|
|
325
327
|
/** Renders as a table, primarily/solely for good print support. */
|
|
326
|
-
function renderTable(style, id, columns, visibleDataRows, keptSelectedRows, firstRowMessage, stickyHeader, xss, _virtuosoRef, tableHeadRows, stickyOffset, _infiniteScroll) {
|
|
328
|
+
function renderTable(style, id, columns, visibleDataRows, keptSelectedRows, firstRowMessage, stickyHeader, xss, _virtuosoRef, _virtuosoRangeRef, tableHeadRows, stickyOffset, _infiniteScroll) {
|
|
327
329
|
return ((0, jsx_runtime_1.jsxs)("table", { css: {
|
|
328
330
|
...Css_1.Css.w100.add("borderCollapse", "separate").add("borderSpacing", "0").$,
|
|
329
331
|
...Css_1.Css.addIn("& tr ", { pageBreakAfter: "auto", pageBreakInside: "avoid" }).$,
|
|
@@ -357,7 +359,7 @@ function renderTable(style, id, columns, visibleDataRows, keptSelectedRows, firs
|
|
|
357
359
|
* [2]: https://github.com/tannerlinsley/react-virtual/issues/85
|
|
358
360
|
* [3]: https://github.com/tannerlinsley/react-virtual/issues/108
|
|
359
361
|
*/
|
|
360
|
-
function renderVirtual(style, id, columns, visibleDataRows, keptSelectedRows, firstRowMessage, stickyHeader, xss, virtuosoRef, tableHeadRows, _stickyOffset, infiniteScroll) {
|
|
362
|
+
function renderVirtual(style, id, columns, visibleDataRows, keptSelectedRows, firstRowMessage, stickyHeader, xss, virtuosoRef, virtuosoRangeRef, tableHeadRows, _stickyOffset, infiniteScroll) {
|
|
361
363
|
var _a;
|
|
362
364
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
363
365
|
const { footerStyle, listStyle } = (0, react_1.useMemo)(() => {
|
|
@@ -402,6 +404,8 @@ function renderVirtual(style, id, columns, visibleDataRows, keptSelectedRows, fi
|
|
|
402
404
|
}
|
|
403
405
|
// Lastly render the table body rows
|
|
404
406
|
return visibleDataRows[index];
|
|
407
|
+
}, rangeChanged: (newRange) => {
|
|
408
|
+
virtuosoRangeRef.current = newRange;
|
|
405
409
|
}, totalCount: tableHeadRows.length + (firstRowMessage ? 1 : 0) + visibleDataRows.length + keptSelectedRows.length, ...(infiniteScroll
|
|
406
410
|
? {
|
|
407
411
|
increaseViewportBy: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MutableRefObject } from "react";
|
|
2
|
-
import { VirtuosoHandle } from "react-virtuoso";
|
|
2
|
+
import { ListRange, VirtuosoHandle } from "react-virtuoso";
|
|
3
3
|
import { GridRowLookup, GridTableScrollOptions, MaybeFn } from "../index";
|
|
4
4
|
import { GridDataRow } from "./components/Row";
|
|
5
5
|
import { DiscriminateUnion, Kinded } from "./types";
|
|
@@ -77,11 +77,12 @@ export type GridRowApi<R extends Kinded> = GridTableApi<R> & {
|
|
|
77
77
|
export declare class GridTableApiImpl<R extends Kinded> implements GridTableApi<R> {
|
|
78
78
|
readonly tableState: TableState<R>;
|
|
79
79
|
virtuosoRef: MutableRefObject<VirtuosoHandle | null>;
|
|
80
|
+
virtuosoRangeRef: MutableRefObject<ListRange | null>;
|
|
80
81
|
lookup: GridRowLookup<R>;
|
|
81
82
|
constructor();
|
|
82
83
|
/** Called once by the GridTable when it takes ownership of this api instance. */
|
|
83
|
-
init(persistCollapse: string | undefined, virtuosoRef: MutableRefObject<VirtuosoHandle | null>): void;
|
|
84
|
-
scrollToIndex(
|
|
84
|
+
init(persistCollapse: string | undefined, virtuosoRef: MutableRefObject<VirtuosoHandle | null>, virtuosoRangeRef: MutableRefObject<ListRange | null>): void;
|
|
85
|
+
scrollToIndex(indexOrOptions: GridTableScrollOptions): void;
|
|
85
86
|
getSelectedRowIds(kind?: string): string[];
|
|
86
87
|
private getSelectedRowIdsImpl;
|
|
87
88
|
getSelectedRows(kind?: string): any;
|
|
@@ -33,6 +33,7 @@ class GridTableApiImpl {
|
|
|
33
33
|
// This is public to GridTable but not exported outside of Beam
|
|
34
34
|
this.tableState = new TableState_1.TableState(this);
|
|
35
35
|
this.virtuosoRef = { current: null };
|
|
36
|
+
this.virtuosoRangeRef = { current: null };
|
|
36
37
|
// This instance gets spread into each row's GridRowApi, so bind the methods up-front
|
|
37
38
|
bindMethods(this);
|
|
38
39
|
// Memoize these so that if the user is creating new `data` instances on every render, they
|
|
@@ -43,16 +44,21 @@ class GridTableApiImpl {
|
|
|
43
44
|
this.getSelectedRowIdsImpl = (0, mobx_utils_1.computedFn)(this.getSelectedRowIdsImpl, { equals: mobx_1.comparer.shallow });
|
|
44
45
|
}
|
|
45
46
|
/** Called once by the GridTable when it takes ownership of this api instance. */
|
|
46
|
-
init(persistCollapse, virtuosoRef) {
|
|
47
|
+
init(persistCollapse, virtuosoRef, virtuosoRangeRef) {
|
|
47
48
|
// Technically this drives both row-collapse and column-expanded
|
|
48
49
|
if (persistCollapse)
|
|
49
50
|
this.tableState.loadCollapse(persistCollapse);
|
|
50
51
|
this.virtuosoRef = virtuosoRef;
|
|
51
|
-
this.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
this.virtuosoRangeRef = virtuosoRangeRef;
|
|
53
|
+
this.lookup = (0, index_1.createRowLookup)(this, virtuosoRef, virtuosoRangeRef);
|
|
54
|
+
}
|
|
55
|
+
scrollToIndex(indexOrOptions) {
|
|
56
|
+
if (!this.virtuosoRef.current)
|
|
57
|
+
return;
|
|
58
|
+
const scrollToOpts = typeof indexOrOptions === "number" ? { index: indexOrOptions, behavior: "smooth" } : indexOrOptions;
|
|
59
|
+
if ((0, index_1.shouldSkipScrollTo)(scrollToOpts.index, this.virtuosoRangeRef))
|
|
60
|
+
return;
|
|
61
|
+
this.virtuosoRef.current.scrollToIndex(scrollToOpts);
|
|
56
62
|
}
|
|
57
63
|
getSelectedRowIds(kind) {
|
|
58
64
|
return this.getSelectedRowIdsImpl(kind !== null && kind !== void 0 ? kind : undefined);
|
|
@@ -14,7 +14,7 @@ export { cardStyle, condensedStyle, defaultStyle, getTableStyles } from "./Table
|
|
|
14
14
|
export type { GridStyle, RowStyle, RowStyles } from "./TableStyles";
|
|
15
15
|
export * from "./types";
|
|
16
16
|
export * from "./utils/columns";
|
|
17
|
-
export { createRowLookup } from "./utils/GridRowLookup";
|
|
17
|
+
export { createRowLookup, shouldSkipScrollTo } from "./utils/GridRowLookup";
|
|
18
18
|
export type { GridRowLookup } from "./utils/GridRowLookup";
|
|
19
19
|
export { simpleDataRows, simpleHeader } from "./utils/simpleHelpers";
|
|
20
20
|
export type { SimpleHeaderAndData } from "./utils/simpleHelpers";
|
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.setGridTableDefaults = exports.setDefaultStyle = exports.GridTable = exports.TableStateContext = exports.TableState = exports.simpleHeader = exports.simpleDataRows = exports.createRowLookup = exports.getTableStyles = exports.defaultStyle = exports.condensedStyle = exports.cardStyle = exports.useGridTableApi = exports.SortHeader = exports.Row = exports.EditColumnsButton = exports.rowLinkRenderFn = exports.rowClickRenderFn = exports.headerRenderFn = exports.defaultRenderFn = void 0;
|
|
17
|
+
exports.setGridTableDefaults = exports.setDefaultStyle = exports.GridTable = exports.TableStateContext = exports.TableState = exports.simpleHeader = exports.simpleDataRows = exports.shouldSkipScrollTo = exports.createRowLookup = exports.getTableStyles = exports.defaultStyle = exports.condensedStyle = exports.cardStyle = exports.useGridTableApi = exports.SortHeader = exports.Row = exports.EditColumnsButton = exports.rowLinkRenderFn = exports.rowClickRenderFn = exports.headerRenderFn = exports.defaultRenderFn = void 0;
|
|
18
18
|
var cell_1 = require("./components/cell");
|
|
19
19
|
Object.defineProperty(exports, "defaultRenderFn", { enumerable: true, get: function () { return cell_1.defaultRenderFn; } });
|
|
20
20
|
Object.defineProperty(exports, "headerRenderFn", { enumerable: true, get: function () { return cell_1.headerRenderFn; } });
|
|
@@ -41,6 +41,7 @@ __exportStar(require("./types"), exports);
|
|
|
41
41
|
__exportStar(require("./utils/columns"), exports);
|
|
42
42
|
var GridRowLookup_1 = require("./utils/GridRowLookup");
|
|
43
43
|
Object.defineProperty(exports, "createRowLookup", { enumerable: true, get: function () { return GridRowLookup_1.createRowLookup; } });
|
|
44
|
+
Object.defineProperty(exports, "shouldSkipScrollTo", { enumerable: true, get: function () { return GridRowLookup_1.shouldSkipScrollTo; } });
|
|
44
45
|
var simpleHelpers_1 = require("./utils/simpleHelpers");
|
|
45
46
|
Object.defineProperty(exports, "simpleDataRows", { enumerable: true, get: function () { return simpleHelpers_1.simpleDataRows; } });
|
|
46
47
|
Object.defineProperty(exports, "simpleHeader", { enumerable: true, get: function () { return simpleHelpers_1.simpleHeader; } });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MutableRefObject } from "react";
|
|
2
|
-
import { VirtuosoHandle } from "react-virtuoso";
|
|
2
|
+
import { ListRange, VirtuosoHandle } from "react-virtuoso";
|
|
3
3
|
import { GridDataRow } from "../components/Row";
|
|
4
4
|
import { GridTableApiImpl } from "../GridTableApi";
|
|
5
5
|
import { DiscriminateUnion, GridColumnWithId, Kinded } from "../types";
|
|
@@ -16,13 +16,18 @@ export interface GridRowLookup<R extends Kinded> {
|
|
|
16
16
|
};
|
|
17
17
|
/** Returns the list of currently filtered/sorted rows, without headers. */
|
|
18
18
|
currentList(): readonly GridDataRow<R>[];
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Scroll's to the row with the given kind + id. Requires using `as=virtual`.
|
|
21
|
+
* Will skip re-scrolling to a row if it's already visible.
|
|
22
|
+
*/
|
|
20
23
|
scrollTo(kind: R["kind"], id: string): void;
|
|
21
24
|
}
|
|
22
25
|
interface NextPrev<R extends Kinded> {
|
|
23
26
|
next: GridDataRow<R> | undefined;
|
|
24
27
|
prev: GridDataRow<R> | undefined;
|
|
25
28
|
}
|
|
26
|
-
export declare function createRowLookup<R extends Kinded>(api: GridTableApiImpl<R>, virtuosoRef: MutableRefObject<VirtuosoHandle | null>): GridRowLookup<R>;
|
|
29
|
+
export declare function createRowLookup<R extends Kinded>(api: GridTableApiImpl<R>, virtuosoRef: MutableRefObject<VirtuosoHandle | null>, virtuosoRangeRef: MutableRefObject<ListRange | null>): GridRowLookup<R>;
|
|
27
30
|
export declare function getKinds<R extends Kinded>(columns: GridColumnWithId<R>[]): R[];
|
|
31
|
+
/** Optionally takes into consideration if a row is already in view before attempting to scroll to it. */
|
|
32
|
+
export declare function shouldSkipScrollTo(index: number, virtuosoRangeRef: MutableRefObject<ListRange | null>): boolean;
|
|
28
33
|
export {};
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createRowLookup = createRowLookup;
|
|
4
4
|
exports.getKinds = getKinds;
|
|
5
|
+
exports.shouldSkipScrollTo = shouldSkipScrollTo;
|
|
5
6
|
const types_1 = require("../types");
|
|
6
|
-
function createRowLookup(api, virtuosoRef) {
|
|
7
|
+
function createRowLookup(api, virtuosoRef, virtuosoRangeRef) {
|
|
7
8
|
return {
|
|
8
9
|
scrollTo(kind, id) {
|
|
9
10
|
if (virtuosoRef.current === null) {
|
|
@@ -12,6 +13,8 @@ function createRowLookup(api, virtuosoRef) {
|
|
|
12
13
|
throw new Error("scrollTo is only supported for as=virtual");
|
|
13
14
|
}
|
|
14
15
|
const index = api.tableState.visibleRows.findIndex((r) => r && r.kind === kind && r.row.id === id);
|
|
16
|
+
if (shouldSkipScrollTo(index, virtuosoRangeRef))
|
|
17
|
+
return;
|
|
15
18
|
virtuosoRef.current.scrollToIndex({ index, behavior: "smooth" });
|
|
16
19
|
},
|
|
17
20
|
currentList() {
|
|
@@ -53,3 +56,14 @@ function createRowLookup(api, virtuosoRef) {
|
|
|
53
56
|
function getKinds(columns) {
|
|
54
57
|
return Object.keys(columns.find((c) => !c.isAction) || {}).filter((key) => !types_1.nonKindGridColumnKeys.includes(key));
|
|
55
58
|
}
|
|
59
|
+
/** Optionally takes into consideration if a row is already in view before attempting to scroll to it. */
|
|
60
|
+
function shouldSkipScrollTo(index, virtuosoRangeRef) {
|
|
61
|
+
if (!virtuosoRangeRef.current)
|
|
62
|
+
return false;
|
|
63
|
+
const isAlreadyInView =
|
|
64
|
+
// Add 1 on each end to account for "overscan" where the next out of view row is usually already rendered. This isn't a perfect solution,
|
|
65
|
+
// but our current "overscan" is only set to 50px, so it should be close enough and the library recommended alternative of adding an
|
|
66
|
+
// intersection observer to each row seems like a not worth it performance hit (https://github.com/petyosi/react-virtuoso/issues/118)
|
|
67
|
+
index >= virtuosoRangeRef.current.startIndex - 1 && index <= virtuosoRangeRef.current.endIndex + 1;
|
|
68
|
+
return isAlreadyInView;
|
|
69
|
+
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.addNewOption = exports.unsetOption = void 0;
|
|
7
4
|
exports.ComboBoxBase = ComboBoxBase;
|
|
8
5
|
exports.initializeOptions = initializeOptions;
|
|
9
6
|
exports.disabledOptionToKeyedTuple = disabledOptionToKeyedTuple;
|
|
10
7
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
11
|
-
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
|
|
12
8
|
const react_1 = require("react");
|
|
13
9
|
const react_aria_1 = require("react-aria");
|
|
14
10
|
const react_stately_1 = require("react-stately");
|
|
@@ -68,18 +64,7 @@ function ComboBoxBase(props) {
|
|
|
68
64
|
: [propOptions.current, propOptions.options, unsetLabel, onAddNew]);
|
|
69
65
|
const values = (0, react_1.useMemo)(() => propValues !== null && propValues !== void 0 ? propValues : [], [propValues]);
|
|
70
66
|
const inputStylePalette = (0, react_1.useMemo)(() => propsInputStylePalette, [propsInputStylePalette]);
|
|
71
|
-
const
|
|
72
|
-
const selectedOptions = (0, react_1.useMemo)(() => {
|
|
73
|
-
// `selectedOptions` should only ever update if the `values` prop actually change.
|
|
74
|
-
// Assuming `values` is a state variable, then it should hold its identity until it _really_ changes.
|
|
75
|
-
// Though, it is possible that the `options` prop has changed, which is a dependency on this `useMemo`.
|
|
76
|
-
// That could trigger an unnecessary new reference for `selectedOptions`, and cause additional renders or unexpected state changes.
|
|
77
|
-
// We should avoid updating `selectedOptions` unless `values` has actually changed.
|
|
78
|
-
if (!(0, fast_deep_equal_1.default)([...values].sort(), selectedOptionsRef.current.map(getOptionValue).sort())) {
|
|
79
|
-
selectedOptionsRef.current = options.filter((o) => values.includes(getOptionValue(o)));
|
|
80
|
-
}
|
|
81
|
-
return selectedOptionsRef.current;
|
|
82
|
-
}, [options, values, getOptionValue]);
|
|
67
|
+
const selectedOptions = (0, react_1.useMemo)(() => options.filter((o) => values.includes(getOptionValue(o))), [options, values, getOptionValue]);
|
|
83
68
|
const { contains } = (0, react_aria_1.useFilter)({ sensitivity: "base" });
|
|
84
69
|
const isDisabled = !!disabled;
|
|
85
70
|
const isReadOnly = !!readOnly;
|