@homebound/beam 2.106.2 → 2.107.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/CollapseToggle.js +7 -10
- package/dist/components/Table/GridTable.d.ts +5 -18
- package/dist/components/Table/GridTable.js +36 -159
- package/dist/components/Table/RowState.d.ts +38 -0
- package/dist/components/Table/RowState.js +185 -0
- package/dist/components/Table/columnSizes.d.ts +22 -0
- package/dist/components/Table/columnSizes.js +59 -0
- package/dist/components/Table/index.d.ts +2 -1
- package/dist/components/Table/index.js +4 -1
- package/dist/forms/BoundCheckboxField.d.ts +1 -1
- package/dist/inputs/Checkbox.d.ts +1 -6
- package/dist/inputs/Checkbox.js +5 -3
- package/dist/inputs/RichTextField.js +7 -6
- package/package.json +1 -1
|
@@ -4,21 +4,18 @@ exports.CollapseToggle = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const components_1 = require("..");
|
|
7
|
+
const hooks_1 = require("../../hooks");
|
|
7
8
|
function CollapseToggle(props) {
|
|
8
9
|
const { row } = props;
|
|
9
|
-
const {
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
setTick(Date.now());
|
|
15
|
-
}, [row.id, currentlyCollapsed, toggleCollapsed]);
|
|
16
|
-
const iconKey = currentlyCollapsed ? "chevronRight" : "chevronDown";
|
|
17
|
-
const headerIconKey = currentlyCollapsed ? "chevronsRight" : "chevronsDown";
|
|
10
|
+
const { rowState } = (0, react_1.useContext)(components_1.RowStateContext);
|
|
11
|
+
const isCollapsed = (0, hooks_1.useComputed)(() => rowState.isCollapsed(row.id), [rowState]);
|
|
12
|
+
const iconKey = isCollapsed ? "chevronRight" : "chevronDown";
|
|
13
|
+
const headerIconKey = isCollapsed ? "chevronsRight" : "chevronsDown";
|
|
14
|
+
// If we're not a header, only render a toggle if we have child rows to actually collapse
|
|
18
15
|
const isHeader = row.kind === "header";
|
|
19
16
|
if (!isHeader && (!props.row.children || props.row.children.length === 0)) {
|
|
20
17
|
return null;
|
|
21
18
|
}
|
|
22
|
-
return (0, jsx_runtime_1.jsx)(components_1.IconButton, { onClick:
|
|
19
|
+
return (0, jsx_runtime_1.jsx)(components_1.IconButton, { onClick: () => rowState.toggleCollapsed(row.id), icon: isHeader ? headerIconKey : iconKey }, void 0);
|
|
23
20
|
}
|
|
24
21
|
exports.CollapseToggle = CollapseToggle;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { MutableRefObject, ReactElement, ReactNode } from "react";
|
|
2
2
|
import { PresentationContextProps, PresentationFieldProps } from "../PresentationContext";
|
|
3
3
|
import { GridRowLookup } from "./GridRowLookup";
|
|
4
4
|
import { Margin, Only, Properties, Typography, Xss } from "../../Css";
|
|
@@ -176,6 +176,8 @@ export interface GridTableProps<R extends Kinded, S, X> {
|
|
|
176
176
|
/** NOTE: This API is experimental and primarily intended for story and testing purposes */
|
|
177
177
|
export declare type GridTableApi = {
|
|
178
178
|
scrollToIndex: (index: number) => void;
|
|
179
|
+
/** Returns the ids of currently-selected rows. */
|
|
180
|
+
getSelectedRowIds(): string[];
|
|
179
181
|
};
|
|
180
182
|
/**
|
|
181
183
|
* Renders data in our table layout.
|
|
@@ -298,24 +300,9 @@ export declare type GridDataRow<R extends Kinded> = {
|
|
|
298
300
|
children?: GridDataRow<R>[];
|
|
299
301
|
/** Whether to pin this sort to the first/last of its parent's children. */
|
|
300
302
|
pin?: "first" | "last";
|
|
301
|
-
} & DiscriminateUnion<R, "kind", R["kind"]
|
|
303
|
+
} & IfAny<R, {}, DiscriminateUnion<R, "kind", R["kind"]>>;
|
|
304
|
+
declare type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;
|
|
302
305
|
/** Return the content for a given column def applied to a given row. */
|
|
303
306
|
export declare function applyRowFn<R extends Kinded>(column: GridColumn<R>, row: GridDataRow<R>): ReactNode | GridCellContent;
|
|
304
|
-
/**
|
|
305
|
-
* Provides each row access to a method to check if it is collapsed and toggle it's collapsed state.
|
|
306
|
-
*
|
|
307
|
-
* Calling `toggleCollapse` will keep the row itself showing, but will hide any
|
|
308
|
-
* children rows (specifically those that have this row's `id` in their `parentIds`
|
|
309
|
-
* prop).
|
|
310
|
-
*
|
|
311
|
-
* headerCollapsed is used to trigger rows at the root level to rerender their chevron when all are
|
|
312
|
-
* collapsed/expanded.
|
|
313
|
-
*/
|
|
314
|
-
declare type GridCollapseContextProps = {
|
|
315
|
-
headerCollapsed: boolean;
|
|
316
|
-
isCollapsed: (id: string) => boolean;
|
|
317
|
-
toggleCollapsed(id: string): void;
|
|
318
|
-
};
|
|
319
|
-
export declare const GridCollapseContext: React.Context<GridCollapseContextProps>;
|
|
320
307
|
export declare function matchesFilter(maybeContent: ReactNode | GridCellContent, filter: string): boolean;
|
|
321
308
|
export {};
|
|
@@ -22,9 +22,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.matchesFilter = exports.
|
|
25
|
+
exports.matchesFilter = exports.applyRowFn = exports.calcColumnSizes = exports.GridTable = exports.setGridTableDefaults = exports.setDefaultStyle = exports.setRunningInJest = exports.emptyCell = exports.DESC = exports.ASC = void 0;
|
|
26
26
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
27
|
-
const utils_1 = require("@react-aria/utils");
|
|
28
27
|
const memoize_one_1 = __importDefault(require("memoize-one"));
|
|
29
28
|
const mobx_react_1 = require("mobx-react");
|
|
30
29
|
const react_1 = __importStar(require("react"));
|
|
@@ -32,15 +31,17 @@ const react_router_dom_1 = require("react-router-dom");
|
|
|
32
31
|
const react_virtuoso_1 = require("react-virtuoso");
|
|
33
32
|
const CssReset_1 = require("../CssReset");
|
|
34
33
|
const PresentationContext_1 = require("../PresentationContext");
|
|
34
|
+
const columnSizes_1 = require("./columnSizes");
|
|
35
35
|
const GridRowLookup_1 = require("./GridRowLookup");
|
|
36
36
|
const GridSortContext_1 = require("./GridSortContext");
|
|
37
37
|
const nestedCards_1 = require("./nestedCards");
|
|
38
|
+
const RowState_1 = require("./RowState");
|
|
38
39
|
const SortHeader_1 = require("./SortHeader");
|
|
39
40
|
const sortRows_1 = require("./sortRows");
|
|
40
41
|
const useSortState_1 = require("./useSortState");
|
|
41
42
|
const Css_1 = require("../../Css");
|
|
43
|
+
const hooks_1 = require("../../hooks");
|
|
42
44
|
const tinycolor2_1 = __importDefault(require("tinycolor2"));
|
|
43
|
-
const use_debounce_1 = require("use-debounce");
|
|
44
45
|
const _1 = require(".");
|
|
45
46
|
exports.ASC = "ASC";
|
|
46
47
|
exports.DESC = "DESC";
|
|
@@ -82,15 +83,19 @@ exports.setGridTableDefaults = setGridTableDefaults;
|
|
|
82
83
|
* special styling to the row that uses `kind: "header"`.)
|
|
83
84
|
*/
|
|
84
85
|
function GridTable(props) {
|
|
85
|
-
var _a, _b, _c, _d
|
|
86
|
+
var _a, _b, _c, _d;
|
|
86
87
|
const { id = "gridTable", as = "div", columns, rows, style = defaults.style, rowStyles, stickyHeader = defaults.stickyHeader, stickyOffset = "0", xss, sorting, filter, filterMaxRows, fallbackMessage = "No rows found.", infoMessage, setRowCount, observeRows, persistCollapse, api, resizeTarget, } = props;
|
|
87
|
-
|
|
88
|
+
// Create a ref that always contains the latest rows, for our effectively-singleton RowState to use
|
|
89
|
+
const rowsRef = (0, react_1.useRef)(rows);
|
|
90
|
+
rowsRef.current = rows;
|
|
91
|
+
const [rowState] = (0, react_1.useState)(() => new RowState_1.RowState(rowsRef, persistCollapse));
|
|
88
92
|
// We only use this in as=virtual mode, but keep this here for rowLookup to use
|
|
89
93
|
const virtuosoRef = (0, react_1.useRef)(null);
|
|
90
94
|
const tableRef = (0, react_1.useRef)(null);
|
|
91
95
|
if (api) {
|
|
92
96
|
api.current = {
|
|
93
97
|
scrollToIndex: (index) => virtuosoRef.current && virtuosoRef.current.scrollToIndex(index),
|
|
98
|
+
getSelectedRowIds: () => rowState.selectedIds,
|
|
94
99
|
};
|
|
95
100
|
}
|
|
96
101
|
const [sortState, setSortKey] = (0, useSortState_1.useSortState)(columns, sorting);
|
|
@@ -101,37 +106,9 @@ function GridTable(props) {
|
|
|
101
106
|
}
|
|
102
107
|
return rows;
|
|
103
108
|
}, [columns, rows, sorting, sortState]);
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
const
|
|
107
|
-
const [tableWidth, setTableWidth] = (0, react_1.useState)();
|
|
108
|
-
// Calc our initial/first render sizes where we won't have a width yet
|
|
109
|
-
const [columnSizes, setColumnSizes] = (0, react_1.useState)(calcColumnSizes(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth, tableWidth, style.minWidthPx));
|
|
110
|
-
const setTableAndColumnWidths = (0, react_1.useCallback)((width) => {
|
|
111
|
-
var _a;
|
|
112
|
-
setTableWidth(width);
|
|
113
|
-
setColumnSizes(calcColumnSizes(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth, width, style.minWidthPx));
|
|
114
|
-
}, [setTableWidth, setColumnSizes, columns, style]);
|
|
115
|
-
const setTableAndColumnWidthsDebounced = (0, use_debounce_1.useDebouncedCallback)(setTableAndColumnWidths, 100);
|
|
116
|
-
const onResize = (0, react_1.useCallback)(() => {
|
|
117
|
-
const target = (resizeTarget === null || resizeTarget === void 0 ? void 0 : resizeTarget.current) ? resizeTarget.current : tableRef.current;
|
|
118
|
-
if (target && target.clientWidth !== tableWidth) {
|
|
119
|
-
if (calculateImmediately.current) {
|
|
120
|
-
calculateImmediately.current = false;
|
|
121
|
-
setTableAndColumnWidths(target.clientWidth);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
setTableAndColumnWidthsDebounced(target.clientWidth);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}, [
|
|
128
|
-
resizeTarget === null || resizeTarget === void 0 ? void 0 : resizeTarget.current,
|
|
129
|
-
tableRef.current,
|
|
130
|
-
setTableAndColumnWidths,
|
|
131
|
-
calculateImmediately,
|
|
132
|
-
setTableAndColumnWidthsDebounced,
|
|
133
|
-
]);
|
|
134
|
-
(0, utils_1.useResizeObserver)({ ref: resizeTarget !== null && resizeTarget !== void 0 ? resizeTarget : tableRef, onResize });
|
|
109
|
+
const columnSizes = (0, columnSizes_1.useSetupColumnSizes)(style, columns, tableRef, resizeTarget);
|
|
110
|
+
// Make a single copy of our current collapsed state, so we'll have a single observer.
|
|
111
|
+
const collapsedIds = (0, hooks_1.useComputed)(() => rowState.collapsedIds, [rowState]);
|
|
135
112
|
// Filter + flatten + component-ize the sorted rows.
|
|
136
113
|
let [headerRows, filteredRows] = (0, react_1.useMemo)(() => {
|
|
137
114
|
// Break up "foo bar" into `[foo, bar]` and a row must match both `foo` and `bar`
|
|
@@ -141,19 +118,19 @@ function GridTable(props) {
|
|
|
141
118
|
// changes, and so by not passing the sortProps, it means the data rows' React.memo will still cache them.
|
|
142
119
|
const sortProps = row.kind === "header" ? { sorting, sortState, setSortKey } : { sorting };
|
|
143
120
|
const RowComponent = observeRows ? ObservedGridRow : MemoizedGridRow;
|
|
144
|
-
return ((0, jsx_runtime_1.jsx)(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
121
|
+
return ((0, jsx_runtime_1.jsx)(RowComponent, Object.assign({}, {
|
|
122
|
+
as,
|
|
123
|
+
columns,
|
|
124
|
+
row,
|
|
125
|
+
style,
|
|
126
|
+
rowStyles,
|
|
127
|
+
stickyHeader,
|
|
128
|
+
stickyOffset,
|
|
129
|
+
openCards: nestedCards ? nestedCards.currentOpenCards() : undefined,
|
|
130
|
+
columnSizes,
|
|
131
|
+
level,
|
|
132
|
+
...sortProps,
|
|
133
|
+
}), `${row.kind}-${row.id}`));
|
|
157
134
|
}
|
|
158
135
|
// Split out the header rows from the data rows so that we can put an `infoMessage` in between them (if needed).
|
|
159
136
|
const headerRows = [];
|
|
@@ -166,8 +143,8 @@ function GridTable(props) {
|
|
|
166
143
|
const matches = filters.length === 0 ||
|
|
167
144
|
row.pin ||
|
|
168
145
|
filters.every((filter) => columns.map((c) => applyRowFn(c, row)).some((maybeContent) => matchesFilter(maybeContent, filter)));
|
|
169
|
-
// Even if we don't pass the filter, one of our children might, so we continue on after this check
|
|
170
146
|
let isCard = false;
|
|
147
|
+
// Even if we don't pass the filter, one of our children might, so we continue on after this check
|
|
171
148
|
if (matches) {
|
|
172
149
|
isCard = nestedCards && nestedCards.maybeOpenCard(row);
|
|
173
150
|
filteredRows.push([row, makeRowComponent(row, level)]);
|
|
@@ -206,11 +183,9 @@ function GridTable(props) {
|
|
|
206
183
|
sortState,
|
|
207
184
|
stickyHeader,
|
|
208
185
|
stickyOffset,
|
|
209
|
-
collapsedIds,
|
|
210
|
-
collapseAllContext,
|
|
211
|
-
collapseRowContext,
|
|
212
186
|
observeRows,
|
|
213
187
|
columnSizes,
|
|
188
|
+
collapsedIds,
|
|
214
189
|
]);
|
|
215
190
|
let tooManyClientSideRows = false;
|
|
216
191
|
if (filterMaxRows && filteredRows.length > filterMaxRows) {
|
|
@@ -228,8 +203,8 @@ function GridTable(props) {
|
|
|
228
203
|
}, [filteredRows === null || filteredRows === void 0 ? void 0 : filteredRows.length, setRowCount]);
|
|
229
204
|
const noData = filteredRows.length === 0;
|
|
230
205
|
const firstRowMessage = (noData && fallbackMessage) || (tooManyClientSideRows && "Hiding some rows, use filter...") || infoMessage;
|
|
231
|
-
const borderless = (
|
|
232
|
-
const typeScale = (
|
|
206
|
+
const borderless = (_a = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _a === void 0 ? void 0 : _a.borderless;
|
|
207
|
+
const typeScale = (_b = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _b === void 0 ? void 0 : _b.typeScale;
|
|
233
208
|
const fieldProps = (0, react_1.useMemo)(() => ({
|
|
234
209
|
hideLabel: true,
|
|
235
210
|
numberAlignment: "right",
|
|
@@ -243,7 +218,8 @@ function GridTable(props) {
|
|
|
243
218
|
// just trust the GridTable impl that, at runtime, `as=virtual` will (other than being virtualized)
|
|
244
219
|
// behave semantically the same as `as=div` did for its tests.
|
|
245
220
|
const _as = as === "virtual" && runningInJest ? "div" : as;
|
|
246
|
-
|
|
221
|
+
const rowStateContext = (0, react_1.useMemo)(() => ({ rowState }), [rowState]);
|
|
222
|
+
return ((0, jsx_runtime_1.jsx)(RowState_1.RowStateContext.Provider, Object.assign({ value: rowStateContext }, { children: (0, jsx_runtime_1.jsx)(PresentationContext_1.PresentationProvider, Object.assign({ fieldProps: fieldProps, wrap: (_c = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _c === void 0 ? void 0 : _c.wrap }, { children: renders[_as](style, id, columns, headerRows, filteredRows, firstRowMessage, stickyHeader, (_d = style.nestedCards) === null || _d === void 0 ? void 0 : _d.firstLastColumnWidth, xss, virtuosoRef, tableRef) }), void 0) }), void 0));
|
|
247
223
|
}
|
|
248
224
|
exports.GridTable = GridTable;
|
|
249
225
|
// Determine which HTML element to use to build the GridTable
|
|
@@ -494,7 +470,7 @@ function GridRow(props) {
|
|
|
494
470
|
// Decrement colspan count and skip if greater than 1.
|
|
495
471
|
if (currentColspan > 1) {
|
|
496
472
|
currentColspan -= 1;
|
|
497
|
-
return;
|
|
473
|
+
return null;
|
|
498
474
|
}
|
|
499
475
|
const maybeContent = applyRowFn(column, row);
|
|
500
476
|
currentColspan = isGridCellContent(maybeContent) ? (_a = maybeContent.colspan) !== null && _a !== void 0 ? _a : 1 : 1;
|
|
@@ -624,11 +600,6 @@ const defaultRenderFn = (as) => (key, css, content) => {
|
|
|
624
600
|
const Cell = as === "table" ? "td" : "div";
|
|
625
601
|
return ((0, jsx_runtime_1.jsx)(Cell, Object.assign({ css: { ...css, ...tableRowStyles(as) } }, { children: content }), key));
|
|
626
602
|
};
|
|
627
|
-
exports.GridCollapseContext = react_1.default.createContext({
|
|
628
|
-
headerCollapsed: false,
|
|
629
|
-
isCollapsed: () => false,
|
|
630
|
-
toggleCollapsed: () => { },
|
|
631
|
-
});
|
|
632
603
|
/** Sets up the `GridContext` so that header cells can access the current sort settings. */
|
|
633
604
|
const headerRenderFn = (columns, column, sortState, setSortKey, as) => (key, css, content) => {
|
|
634
605
|
const [currentKey, direction] = sortState || [];
|
|
@@ -710,102 +681,8 @@ exports.matchesFilter = matchesFilter;
|
|
|
710
681
|
function maybeDarken(color, defaultColor) {
|
|
711
682
|
return color ? (0, tinycolor2_1.default)(color).darken(4).toString() : defaultColor;
|
|
712
683
|
}
|
|
713
|
-
|
|
714
|
-
function
|
|
715
|
-
if (!persistCollapse)
|
|
716
|
-
return [];
|
|
717
|
-
const collapsedGridRowIds = localStorage.getItem(persistCollapse);
|
|
718
|
-
return collapsedGridRowIds ? JSON.parse(collapsedGridRowIds) : [];
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* A custom hook to manage a list of ids.
|
|
722
|
-
*
|
|
723
|
-
* What's special about this hook is that we manage a stable identity
|
|
724
|
-
* for the `toggleId` function, so that rows that have _not_ toggled
|
|
725
|
-
* themselves on/off will have an unchanged callback and so not be
|
|
726
|
-
* re-rendered.
|
|
727
|
-
*
|
|
728
|
-
* That said, when they do trigger a `toggleId`, the stable/"stale" callback
|
|
729
|
-
* function should see/update the latest list of values, which is not possible with a
|
|
730
|
-
* traditional `useState` hook because it captures the original/stale list identity.
|
|
731
|
-
*/
|
|
732
|
-
function useToggleIds(rows, persistCollapse) {
|
|
733
|
-
// Make a list that we will only mutate, so that our callbacks have a stable identity.
|
|
734
|
-
const [collapsedIds] = (0, react_1.useState)(getCollapsedRows(persistCollapse));
|
|
735
|
-
// Use this to trigger the component to re-render even though we're not calling `setList`
|
|
736
|
-
const [tick, setTick] = (0, react_1.useState)("");
|
|
737
|
-
// Checking whether something is collapsed does not depend on anything
|
|
738
|
-
const isCollapsed = (0, react_1.useCallback)((id) => collapsedIds.includes(id),
|
|
739
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
740
|
-
[]);
|
|
741
|
-
const collapseAllContext = (0, react_1.useMemo)(() => {
|
|
742
|
-
// Create the stable `toggleCollapsed`, i.e. we are purposefully passing an (almost) empty dep list
|
|
743
|
-
// Since only toggling all rows required knowledge of what the rows are
|
|
744
|
-
const toggleAll = (_id) => {
|
|
745
|
-
// We have different behavior when going from expand/collapse all.
|
|
746
|
-
const isAllCollapsed = collapsedIds[0] === "header";
|
|
747
|
-
collapsedIds.splice(0, collapsedIds.length);
|
|
748
|
-
if (isAllCollapsed) {
|
|
749
|
-
// Expand all means keep `collapsedIds` empty
|
|
750
|
-
}
|
|
751
|
-
else {
|
|
752
|
-
// Otherwise push `header` on the list as a hint that we're in the collapsed-all state
|
|
753
|
-
collapsedIds.push("header");
|
|
754
|
-
// Find all non-leaf rows so that toggling "all collapsed" -> "all not collapsed" opens
|
|
755
|
-
// the parent rows of any level.
|
|
756
|
-
const parentIds = new Set();
|
|
757
|
-
const todo = [...rows];
|
|
758
|
-
while (todo.length > 0) {
|
|
759
|
-
const r = todo.pop();
|
|
760
|
-
if (r.children) {
|
|
761
|
-
parentIds.add(r.id);
|
|
762
|
-
todo.push(...r.children);
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
// And then mark all parent rows as collapsed.
|
|
766
|
-
collapsedIds.push(...parentIds);
|
|
767
|
-
}
|
|
768
|
-
if (persistCollapse) {
|
|
769
|
-
localStorage.setItem(persistCollapse, JSON.stringify(collapsedIds));
|
|
770
|
-
}
|
|
771
|
-
// Trigger a re-render
|
|
772
|
-
setTick(collapsedIds.join(","));
|
|
773
|
-
};
|
|
774
|
-
return { headerCollapsed: isCollapsed("header"), isCollapsed, toggleCollapsed: toggleAll };
|
|
775
|
-
},
|
|
776
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
777
|
-
[rows]);
|
|
778
|
-
const collapseRowContext = (0, react_1.useMemo)(() => {
|
|
779
|
-
// Create the stable `toggleCollapsed`, i.e. we are purposefully passing an empty dep list
|
|
780
|
-
// Since toggling a single row does not need to know about the other rows
|
|
781
|
-
const toggleRow = (id) => {
|
|
782
|
-
// This is the regular/non-header behavior to just add/remove the individual row id
|
|
783
|
-
const i = collapsedIds.indexOf(id);
|
|
784
|
-
if (i === -1) {
|
|
785
|
-
collapsedIds.push(id);
|
|
786
|
-
}
|
|
787
|
-
else {
|
|
788
|
-
collapsedIds.splice(i, 1);
|
|
789
|
-
}
|
|
790
|
-
if (persistCollapse) {
|
|
791
|
-
localStorage.setItem(persistCollapse, JSON.stringify(collapsedIds));
|
|
792
|
-
}
|
|
793
|
-
// Trigger a re-render
|
|
794
|
-
setTick(collapsedIds.join(","));
|
|
795
|
-
};
|
|
796
|
-
return { headerCollapsed: isCollapsed("header"), isCollapsed, toggleCollapsed: toggleRow };
|
|
797
|
-
},
|
|
798
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
799
|
-
[collapseAllContext.isCollapsed("header")]);
|
|
800
|
-
// Return a copy of the list, b/c we want external useMemos that do explicitly use the
|
|
801
|
-
// entire list as a dep to re-render whenever the list is changed (which they need to
|
|
802
|
-
// see as new list identity).
|
|
803
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
804
|
-
const copy = (0, react_1.useMemo)(() => [...collapsedIds], [tick, collapsedIds]);
|
|
805
|
-
return [copy, collapseAllContext, collapseRowContext];
|
|
806
|
-
}
|
|
807
|
-
/** GridTable as Table utility to apply <tr> element override styles */
|
|
808
|
-
const tableRowStyles = (as, column) => {
|
|
684
|
+
/** GridTable as Table utility to apply <tr> element override styles. */
|
|
685
|
+
function tableRowStyles(as, column) {
|
|
809
686
|
const thWidth = column === null || column === void 0 ? void 0 : column.w;
|
|
810
687
|
return as === "table"
|
|
811
688
|
? {
|
|
@@ -813,4 +690,4 @@ const tableRowStyles = (as, column) => {
|
|
|
813
690
|
...(thWidth ? Css_1.Css.w(thWidth).$ : {}),
|
|
814
691
|
}
|
|
815
692
|
: {};
|
|
816
|
-
}
|
|
693
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { MutableRefObject } from "react";
|
|
2
|
+
import { GridDataRow } from "./GridTable";
|
|
3
|
+
export declare type SelectedState = "checked" | "unchecked" | "partial";
|
|
4
|
+
/**
|
|
5
|
+
* Stores the collapsed & selected state of rows.
|
|
6
|
+
*
|
|
7
|
+
* I.e. this implements "collapse parent" --> "hides children", and
|
|
8
|
+
* "select parent" --> "select parent + children".
|
|
9
|
+
*
|
|
10
|
+
* There should be a single, stable `RowStateStore` instance per `GridTable`, so
|
|
11
|
+
* that children don't have to re-render even as we incrementally add/remove rows
|
|
12
|
+
* to the table (i.e. the top-level rows identity changes, but each row within it
|
|
13
|
+
* may not).
|
|
14
|
+
*
|
|
15
|
+
* We use mobx ObservableSets/ObservableMaps to drive granular re-rendering of rows/cells
|
|
16
|
+
* that need to change their toggle/select on/off in response to parent/child
|
|
17
|
+
* changes.
|
|
18
|
+
*/
|
|
19
|
+
export declare class RowState {
|
|
20
|
+
private rows;
|
|
21
|
+
private persistCollapse;
|
|
22
|
+
private readonly collapsedRows;
|
|
23
|
+
private readonly selectedRows;
|
|
24
|
+
/**
|
|
25
|
+
* Creates the `RowState` for a given `GridTable`.
|
|
26
|
+
*/
|
|
27
|
+
constructor(rows: MutableRefObject<GridDataRow<any>[]>, persistCollapse: string | undefined);
|
|
28
|
+
get selectedIds(): string[];
|
|
29
|
+
getSelected(id: string): SelectedState;
|
|
30
|
+
selectRow(id: string, selected: boolean): void;
|
|
31
|
+
get collapsedIds(): string[];
|
|
32
|
+
isCollapsed(id: string): boolean;
|
|
33
|
+
toggleCollapsed(id: string): void;
|
|
34
|
+
}
|
|
35
|
+
/** Provides a context for rows to access their table's `RowState`. */
|
|
36
|
+
export declare const RowStateContext: React.Context<{
|
|
37
|
+
rowState: RowState;
|
|
38
|
+
}>;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RowStateContext = exports.RowState = void 0;
|
|
7
|
+
const mobx_1 = require("mobx");
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
9
|
+
/**
|
|
10
|
+
* Stores the collapsed & selected state of rows.
|
|
11
|
+
*
|
|
12
|
+
* I.e. this implements "collapse parent" --> "hides children", and
|
|
13
|
+
* "select parent" --> "select parent + children".
|
|
14
|
+
*
|
|
15
|
+
* There should be a single, stable `RowStateStore` instance per `GridTable`, so
|
|
16
|
+
* that children don't have to re-render even as we incrementally add/remove rows
|
|
17
|
+
* to the table (i.e. the top-level rows identity changes, but each row within it
|
|
18
|
+
* may not).
|
|
19
|
+
*
|
|
20
|
+
* We use mobx ObservableSets/ObservableMaps to drive granular re-rendering of rows/cells
|
|
21
|
+
* that need to change their toggle/select on/off in response to parent/child
|
|
22
|
+
* changes.
|
|
23
|
+
*/
|
|
24
|
+
class RowState {
|
|
25
|
+
/**
|
|
26
|
+
* Creates the `RowState` for a given `GridTable`.
|
|
27
|
+
*/
|
|
28
|
+
constructor(rows, persistCollapse) {
|
|
29
|
+
this.rows = rows;
|
|
30
|
+
this.persistCollapse = persistCollapse;
|
|
31
|
+
this.selectedRows = new mobx_1.ObservableMap();
|
|
32
|
+
this.collapsedRows = new mobx_1.ObservableSet(persistCollapse ? readLocalCollapseState(persistCollapse) : []);
|
|
33
|
+
// Make ourselves an observable so that mobx will do caching of .collapseIds so
|
|
34
|
+
// that it'll be a stable identity for GridTable to useMemo against.
|
|
35
|
+
(0, mobx_1.makeAutoObservable)(this, { rows: false }); // as any b/c rows is private, so the mapped type doesn't see it
|
|
36
|
+
}
|
|
37
|
+
get selectedIds() {
|
|
38
|
+
// Return only ids that are fully checked, i.e. not partial
|
|
39
|
+
const ids = [...this.selectedRows.entries()].filter(([, v]) => v === "checked").map(([k]) => k);
|
|
40
|
+
// Hide our header marker
|
|
41
|
+
const headerIndex = ids.indexOf("header");
|
|
42
|
+
if (headerIndex > -1) {
|
|
43
|
+
ids.splice(headerIndex, 1);
|
|
44
|
+
}
|
|
45
|
+
return ids;
|
|
46
|
+
}
|
|
47
|
+
// Should be called in an Observer/useComputed to trigger re-renders
|
|
48
|
+
getSelected(id) {
|
|
49
|
+
// We may not have every row in here, i.e. on 1st page load or after clicking here, so assume unchecked
|
|
50
|
+
return this.selectedRows.get(id) || "unchecked";
|
|
51
|
+
}
|
|
52
|
+
selectRow(id, selected) {
|
|
53
|
+
if (id === "header") {
|
|
54
|
+
// Select/unselect all has special behavior
|
|
55
|
+
if (selected) {
|
|
56
|
+
// Just mash the header + all rows + children as selected
|
|
57
|
+
const map = new Map();
|
|
58
|
+
map.set("header", "checked");
|
|
59
|
+
visit(this.rows.current, (row) => map.set(row.id, "checked"));
|
|
60
|
+
this.selectedRows.replace(map);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Similarly "unmash" all rows + children.
|
|
64
|
+
this.selectedRows.clear();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// This is the regular/non-header behavior to just add/remove the individual row id,
|
|
69
|
+
// plus percolate the change down-to-child + up-to-parents.
|
|
70
|
+
// Find the clicked on row
|
|
71
|
+
const curr = findRow(this.rows.current, id);
|
|
72
|
+
if (!curr) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Everything here & down is deterministically on/off
|
|
76
|
+
const map = new Map();
|
|
77
|
+
visit([curr.row], (row) => map.set(row.id, selected ? "checked" : "unchecked"));
|
|
78
|
+
// Now walk up the parents and see if they are now-all-checked/now-all-unchecked/some-of-each
|
|
79
|
+
for (const parent of [...curr.parents].reverse()) {
|
|
80
|
+
if (parent.children) {
|
|
81
|
+
const children = parent.children.map((row) => map.get(row.id) || this.getSelected(row.id));
|
|
82
|
+
map.set(parent.id, deriveParentSelected(children));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// And do the header + top-level "children" as a final one-off
|
|
86
|
+
const children = this.rows.current
|
|
87
|
+
.filter((row) => row.id !== "header")
|
|
88
|
+
.map((row) => map.get(row.id) || this.getSelected(row.id));
|
|
89
|
+
map.set("header", deriveParentSelected(children));
|
|
90
|
+
this.selectedRows.merge(map);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
get collapsedIds() {
|
|
94
|
+
return [...this.collapsedRows.values()];
|
|
95
|
+
}
|
|
96
|
+
// Should be called in an Observer/useComputed to trigger re-renders
|
|
97
|
+
isCollapsed(id) {
|
|
98
|
+
return this.collapsedRows.has(id) || this.collapsedRows.has("header");
|
|
99
|
+
}
|
|
100
|
+
toggleCollapsed(id) {
|
|
101
|
+
const collapsedIds = [...this.collapsedRows.values()];
|
|
102
|
+
// We have different behavior when going from expand/collapse all.
|
|
103
|
+
if (id === "header") {
|
|
104
|
+
const isAllCollapsed = collapsedIds[0] === "header";
|
|
105
|
+
if (isAllCollapsed) {
|
|
106
|
+
// Expand all means keep `collapsedIds` empty
|
|
107
|
+
collapsedIds.splice(0, collapsedIds.length);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Otherwise push `header` on the list as a hint that we're in the collapsed-all state
|
|
111
|
+
collapsedIds.push("header");
|
|
112
|
+
// Find all non-leaf rows so that toggling "all collapsed" -> "all not collapsed" opens
|
|
113
|
+
// the parent rows of any level.
|
|
114
|
+
const parentIds = new Set();
|
|
115
|
+
const todo = [...this.rows.current];
|
|
116
|
+
while (todo.length > 0) {
|
|
117
|
+
const r = todo.pop();
|
|
118
|
+
if (r.children) {
|
|
119
|
+
parentIds.add(r.id);
|
|
120
|
+
todo.push(...r.children);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// And then mark all parent rows as collapsed.
|
|
124
|
+
collapsedIds.push(...parentIds);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// This is the regular/non-header behavior to just add/remove the individual row id
|
|
129
|
+
const i = collapsedIds.indexOf(id);
|
|
130
|
+
if (i === -1) {
|
|
131
|
+
collapsedIds.push(id);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
collapsedIds.splice(i, 1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
this.collapsedRows.replace(collapsedIds);
|
|
138
|
+
if (this.persistCollapse) {
|
|
139
|
+
localStorage.setItem(this.persistCollapse, JSON.stringify(collapsedIds));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.RowState = RowState;
|
|
144
|
+
/** Provides a context for rows to access their table's `RowState`. */
|
|
145
|
+
exports.RowStateContext = react_1.default.createContext({
|
|
146
|
+
get rowState() {
|
|
147
|
+
throw new Error("No RowStateContext provider");
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
// Get the rows that are already in the toggled state, so we can keep them toggled
|
|
151
|
+
function readLocalCollapseState(persistCollapse) {
|
|
152
|
+
const collapsedGridRowIds = localStorage.getItem(persistCollapse);
|
|
153
|
+
return collapsedGridRowIds ? JSON.parse(collapsedGridRowIds) : [];
|
|
154
|
+
}
|
|
155
|
+
/** Finds a row by id, and returns it + any parents. */
|
|
156
|
+
function findRow(rows, id) {
|
|
157
|
+
// This is technically an array of "maybe FoundRow"
|
|
158
|
+
const todo = rows.map((row) => ({ row, parents: [] }));
|
|
159
|
+
while (todo.length > 0) {
|
|
160
|
+
const curr = todo.pop();
|
|
161
|
+
if (curr.row.id === id) {
|
|
162
|
+
return curr;
|
|
163
|
+
}
|
|
164
|
+
else if (curr.row.children) {
|
|
165
|
+
// Search our children and pass along us as the parent
|
|
166
|
+
todo.push(...curr.row.children.map((child) => ({ row: child, parents: [...curr.parents, curr.row] })));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
function deriveParentSelected(children) {
|
|
172
|
+
const allChecked = children.every((child) => child === "checked");
|
|
173
|
+
const allUnchecked = children.every((child) => child === "unchecked");
|
|
174
|
+
return allChecked ? "checked" : allUnchecked ? "unchecked" : "partial";
|
|
175
|
+
}
|
|
176
|
+
function visit(rows, fn) {
|
|
177
|
+
const todo = [...rows];
|
|
178
|
+
while (todo.length > 0) {
|
|
179
|
+
const row = todo.pop();
|
|
180
|
+
fn(row);
|
|
181
|
+
if (row.children) {
|
|
182
|
+
todo.push(...row.children);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MutableRefObject } from "react";
|
|
2
|
+
import { GridColumn, GridStyle } from "./GridTable";
|
|
3
|
+
/**
|
|
4
|
+
* Calculates an array of sizes for each of our columns.
|
|
5
|
+
*
|
|
6
|
+
* We originally supported CSS grid-template-column definitions which allowed fancier,
|
|
7
|
+
* dynamic/content-based widths, but have eventually dropped it mainly due to:
|
|
8
|
+
*
|
|
9
|
+
* 1. In virtual tables, a) the table never has all of the rows in DOM at a single time,
|
|
10
|
+
* so any "content-based" widths will change as you scroll the table, which is weird, and
|
|
11
|
+
* b) a sticky header and rows are put in different DOM parent elements by react-virtuoso,
|
|
12
|
+
* so wouldn't arrive at the same "content-based" widths.
|
|
13
|
+
*
|
|
14
|
+
* 2. Using CSS grid but still have a row-level div for hover/focus targeting required
|
|
15
|
+
* a "fake" `display: contents` div that couldn't have actually any styles applied to it.
|
|
16
|
+
*
|
|
17
|
+
* So we've just got with essentially fixed/deterministic widths, i.e. `px` or `percent` or
|
|
18
|
+
* `fr`.
|
|
19
|
+
*
|
|
20
|
+
* Disclaimer that we roll our own `fr` b/c we're not in CSS grid anymore.
|
|
21
|
+
*/
|
|
22
|
+
export declare function useSetupColumnSizes(style: GridStyle, columns: GridColumn<any>[], tableRef: MutableRefObject<HTMLElement | null>, resizeTarget: MutableRefObject<HTMLElement | null> | undefined): string[];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSetupColumnSizes = void 0;
|
|
4
|
+
const utils_1 = require("@react-aria/utils");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const GridTable_1 = require("./GridTable");
|
|
7
|
+
const use_debounce_1 = require("use-debounce");
|
|
8
|
+
/**
|
|
9
|
+
* Calculates an array of sizes for each of our columns.
|
|
10
|
+
*
|
|
11
|
+
* We originally supported CSS grid-template-column definitions which allowed fancier,
|
|
12
|
+
* dynamic/content-based widths, but have eventually dropped it mainly due to:
|
|
13
|
+
*
|
|
14
|
+
* 1. In virtual tables, a) the table never has all of the rows in DOM at a single time,
|
|
15
|
+
* so any "content-based" widths will change as you scroll the table, which is weird, and
|
|
16
|
+
* b) a sticky header and rows are put in different DOM parent elements by react-virtuoso,
|
|
17
|
+
* so wouldn't arrive at the same "content-based" widths.
|
|
18
|
+
*
|
|
19
|
+
* 2. Using CSS grid but still have a row-level div for hover/focus targeting required
|
|
20
|
+
* a "fake" `display: contents` div that couldn't have actually any styles applied to it.
|
|
21
|
+
*
|
|
22
|
+
* So we've just got with essentially fixed/deterministic widths, i.e. `px` or `percent` or
|
|
23
|
+
* `fr`.
|
|
24
|
+
*
|
|
25
|
+
* Disclaimer that we roll our own `fr` b/c we're not in CSS grid anymore.
|
|
26
|
+
*/
|
|
27
|
+
function useSetupColumnSizes(style, columns, tableRef, resizeTarget) {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
// Calculate the column sizes immediately rather than via the `debounce` method.
|
|
30
|
+
// We do this for Storybook integrations that may use MockDate. MockDate changes the behavior of `new Date()`,
|
|
31
|
+
// which is used internally by `useDebounce`, so the frozen clock means the callback is never called.
|
|
32
|
+
const calculateImmediately = (0, react_1.useRef)(true);
|
|
33
|
+
const [tableWidth, setTableWidth] = (0, react_1.useState)();
|
|
34
|
+
// Calc our initial/first render sizes where we won't have a width yet
|
|
35
|
+
const [columnSizes, setColumnSizes] = (0, react_1.useState)(
|
|
36
|
+
// TODO Add a useEffect to re-calc this on change
|
|
37
|
+
(0, GridTable_1.calcColumnSizes)(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth, tableWidth, style.minWidthPx));
|
|
38
|
+
const setTableAndColumnWidths = (0, react_1.useCallback)((width) => {
|
|
39
|
+
var _a;
|
|
40
|
+
setTableWidth(width);
|
|
41
|
+
setColumnSizes((0, GridTable_1.calcColumnSizes)(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth, width, style.minWidthPx));
|
|
42
|
+
}, [setTableWidth, setColumnSizes, columns, style]);
|
|
43
|
+
const setTableAndColumnWidthsDebounced = (0, use_debounce_1.useDebouncedCallback)(setTableAndColumnWidths, 100);
|
|
44
|
+
const target = (_b = resizeTarget === null || resizeTarget === void 0 ? void 0 : resizeTarget.current) !== null && _b !== void 0 ? _b : tableRef.current;
|
|
45
|
+
const onResize = (0, react_1.useCallback)(() => {
|
|
46
|
+
if (target && target.clientWidth !== tableWidth) {
|
|
47
|
+
if (calculateImmediately.current) {
|
|
48
|
+
calculateImmediately.current = false;
|
|
49
|
+
setTableAndColumnWidths(target.clientWidth);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
setTableAndColumnWidthsDebounced(target.clientWidth);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}, [target, tableWidth, setTableAndColumnWidths, setTableAndColumnWidthsDebounced]);
|
|
56
|
+
(0, utils_1.useResizeObserver)({ ref: resizeTarget !== null && resizeTarget !== void 0 ? resizeTarget : tableRef, onResize });
|
|
57
|
+
return columnSizes;
|
|
58
|
+
}
|
|
59
|
+
exports.useSetupColumnSizes = useSetupColumnSizes;
|
|
@@ -3,7 +3,8 @@ export * from "./columns";
|
|
|
3
3
|
export type { GridRowLookup } from "./GridRowLookup";
|
|
4
4
|
export { GridSortContext } from "./GridSortContext";
|
|
5
5
|
export { ASC, DESC, GridTable, setDefaultStyle, setGridTableDefaults } from "./GridTable";
|
|
6
|
-
export type { Direction, GridCellAlignment, GridCellContent,
|
|
6
|
+
export type { Direction, GridCellAlignment, GridCellContent, GridColumn, GridDataRow, GridRowStyles, GridSortConfig, GridStyle, GridTableDefaults, GridTableProps, GridTableXss, Kinded, RowStyle, setRunningInJest, } from "./GridTable";
|
|
7
|
+
export { RowState, RowStateContext } from "./RowState";
|
|
7
8
|
export { simpleDataRows, simpleHeader, simpleRows } from "./simpleHelpers";
|
|
8
9
|
export type { SimpleHeaderAndDataOf, SimpleHeaderAndDataWith } from "./simpleHelpers";
|
|
9
10
|
export { SortHeader } from "./SortHeader";
|
|
@@ -10,7 +10,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
10
10
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.defaultStyle = exports.condensedStyle = exports.cardStyle = exports.beamTotalsFlexibleStyle = exports.beamTotalsFixedStyle = exports.beamNestedFlexibleStyle = exports.beamNestedFixedStyle = exports.beamFlexibleStyle = exports.beamFixedStyle = exports.SortHeader = exports.simpleRows = exports.simpleHeader = exports.simpleDataRows = exports.setGridTableDefaults = exports.setDefaultStyle = exports.GridTable = exports.DESC = exports.ASC = exports.GridSortContext = void 0;
|
|
13
|
+
exports.defaultStyle = exports.condensedStyle = exports.cardStyle = exports.beamTotalsFlexibleStyle = exports.beamTotalsFixedStyle = exports.beamNestedFlexibleStyle = exports.beamNestedFixedStyle = exports.beamFlexibleStyle = exports.beamFixedStyle = exports.SortHeader = exports.simpleRows = exports.simpleHeader = exports.simpleDataRows = exports.RowStateContext = exports.RowState = exports.setGridTableDefaults = exports.setDefaultStyle = exports.GridTable = exports.DESC = exports.ASC = exports.GridSortContext = void 0;
|
|
14
14
|
__exportStar(require("./CollapseToggle"), exports);
|
|
15
15
|
__exportStar(require("./columns"), exports);
|
|
16
16
|
var GridSortContext_1 = require("./GridSortContext");
|
|
@@ -21,6 +21,9 @@ Object.defineProperty(exports, "DESC", { enumerable: true, get: function () { re
|
|
|
21
21
|
Object.defineProperty(exports, "GridTable", { enumerable: true, get: function () { return GridTable_1.GridTable; } });
|
|
22
22
|
Object.defineProperty(exports, "setDefaultStyle", { enumerable: true, get: function () { return GridTable_1.setDefaultStyle; } });
|
|
23
23
|
Object.defineProperty(exports, "setGridTableDefaults", { enumerable: true, get: function () { return GridTable_1.setGridTableDefaults; } });
|
|
24
|
+
var RowState_1 = require("./RowState");
|
|
25
|
+
Object.defineProperty(exports, "RowState", { enumerable: true, get: function () { return RowState_1.RowState; } });
|
|
26
|
+
Object.defineProperty(exports, "RowStateContext", { enumerable: true, get: function () { return RowState_1.RowStateContext; } });
|
|
24
27
|
var simpleHelpers_1 = require("./simpleHelpers");
|
|
25
28
|
Object.defineProperty(exports, "simpleDataRows", { enumerable: true, get: function () { return simpleHelpers_1.simpleDataRows; } });
|
|
26
29
|
Object.defineProperty(exports, "simpleHeader", { enumerable: true, get: function () { return simpleHelpers_1.simpleHeader; } });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FieldState } from "@homebound/form-state";
|
|
2
2
|
import { CheckboxProps } from "../inputs";
|
|
3
|
-
export declare type BoundCheckboxFieldProps = Omit<CheckboxProps, "
|
|
3
|
+
export declare type BoundCheckboxFieldProps = Omit<CheckboxProps, "selected" | "onChange" | "label"> & {
|
|
4
4
|
field: FieldState<any, boolean | null | undefined>;
|
|
5
5
|
/** Make optional so that callers can override if they want to. */
|
|
6
6
|
onChange?: (values: boolean) => void;
|
|
@@ -2,17 +2,12 @@ import { ReactNode } from "react";
|
|
|
2
2
|
export interface CheckboxProps {
|
|
3
3
|
label: string;
|
|
4
4
|
checkboxOnly?: boolean;
|
|
5
|
+
selected: boolean | "indeterminate";
|
|
5
6
|
/** Handler that is called when the element's selection state changes. */
|
|
6
7
|
onChange: (selected: boolean) => void;
|
|
7
8
|
/** Additional text displayed below label */
|
|
8
9
|
description?: string;
|
|
9
10
|
disabled?: boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Indeterminism is presentational only.
|
|
12
|
-
* The indeterminate visual representation remains regardless of user interaction.
|
|
13
|
-
*/
|
|
14
|
-
indeterminate?: boolean;
|
|
15
|
-
selected?: boolean;
|
|
16
11
|
errorMsg?: string;
|
|
17
12
|
helperText?: string | ReactNode;
|
|
18
13
|
/** Callback fired when focus removes from the component */
|
package/dist/inputs/Checkbox.js
CHANGED
|
@@ -7,12 +7,14 @@ const react_aria_1 = require("react-aria");
|
|
|
7
7
|
const react_stately_1 = require("react-stately");
|
|
8
8
|
const CheckboxBase_1 = require("./CheckboxBase");
|
|
9
9
|
function Checkbox(props) {
|
|
10
|
-
const { label,
|
|
11
|
-
|
|
10
|
+
const { label, disabled: isDisabled = false, selected, ...otherProps } = props;
|
|
11
|
+
// Treat indeterminate as false so that clicking on indeterminate always goes --> true.
|
|
12
|
+
const isSelected = selected === true;
|
|
13
|
+
const isIndeterminate = selected === "indeterminate";
|
|
14
|
+
const ariaProps = { isSelected, isDisabled, isIndeterminate, ...otherProps };
|
|
12
15
|
const checkboxProps = { ...ariaProps, "aria-label": label };
|
|
13
16
|
const ref = (0, react_1.useRef)(null);
|
|
14
17
|
const toggleState = (0, react_stately_1.useToggleState)(ariaProps);
|
|
15
|
-
const isSelected = toggleState.isSelected;
|
|
16
18
|
const { inputProps } = (0, react_aria_1.useCheckbox)(checkboxProps, toggleState, ref);
|
|
17
19
|
return ((0, jsx_runtime_1.jsx)(CheckboxBase_1.CheckboxBase, Object.assign({ ariaProps: ariaProps, isDisabled: isDisabled, isIndeterminate: isIndeterminate, isSelected: isSelected, inputProps: inputProps, label: label }, otherProps), void 0));
|
|
18
20
|
}
|
|
@@ -25,7 +25,7 @@ require("trix/dist/trix.css");
|
|
|
25
25
|
function RichTextField(props) {
|
|
26
26
|
const { mergeTags, label, value = "", onChange, onBlur = utils_1.noop, onFocus = utils_1.noop, readOnly } = props;
|
|
27
27
|
// We get a reference to the Editor instance after trix-init fires
|
|
28
|
-
const editor = (0, react_2.
|
|
28
|
+
const [editor, setEditor] = (0, react_2.useState)();
|
|
29
29
|
const editorElement = (0, react_2.useRef)();
|
|
30
30
|
// Keep track of what we pass to onChange, so that we can make ourselves keep looking
|
|
31
31
|
// like a controlled input, i.e. by only calling loadHTML if a new incoming `value` !== `currentHtml`,
|
|
@@ -48,12 +48,13 @@ function RichTextField(props) {
|
|
|
48
48
|
const targetEl = e.target;
|
|
49
49
|
if (targetEl.id === id) {
|
|
50
50
|
editorElement.current = targetEl;
|
|
51
|
-
editor
|
|
51
|
+
const editor = editorElement.current.editor;
|
|
52
|
+
setEditor(editor);
|
|
52
53
|
if (mergeTags !== undefined) {
|
|
53
54
|
attachTributeJs(mergeTags, editorElement.current);
|
|
54
55
|
}
|
|
55
56
|
currentHtml.current = value;
|
|
56
|
-
editor.
|
|
57
|
+
editor.loadHTML(value || "");
|
|
57
58
|
// Remove listener once we've initialized
|
|
58
59
|
window.removeEventListener("trix-initialize", onEditorInit);
|
|
59
60
|
function trixChange(e) {
|
|
@@ -88,10 +89,10 @@ function RichTextField(props) {
|
|
|
88
89
|
}, []);
|
|
89
90
|
(0, react_2.useEffect)(() => {
|
|
90
91
|
// If our value prop changes (without the change coming from us), reload it
|
|
91
|
-
if (!readOnly && editor
|
|
92
|
-
editor.
|
|
92
|
+
if (!readOnly && editor && value !== currentHtml.current) {
|
|
93
|
+
editor.loadHTML(value || "");
|
|
93
94
|
}
|
|
94
|
-
}, [value, readOnly]);
|
|
95
|
+
}, [value, readOnly, editor]);
|
|
95
96
|
const { placeholder, autoFocus } = props;
|
|
96
97
|
if (!readOnly) {
|
|
97
98
|
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.w100.maxw("550px").$ }, { children: [label && (0, jsx_runtime_1.jsx)(Label_1.Label, { labelProps: {}, label: label }, void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ css: { ...Css_1.Css.br4.bgWhite.$, ...trixCssOverrides } }, { children: [(0, jsx_runtime_1.jsx)("input", { type: "hidden", id: `input-${id}`, value: value }, void 0), (0, react_2.createElement)("trix-editor", {
|