@homebound/beam 2.304.0 → 2.305.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/utils/RowState.d.ts +3 -1
- package/dist/components/Table/utils/RowState.js +14 -15
- package/dist/components/Table/utils/RowStates.d.ts +1 -1
- package/dist/components/Table/utils/RowStates.js +25 -16
- package/dist/components/Table/utils/TableState.js +2 -10
- package/dist/inputs/DateFields/DateFieldBase.js +7 -25
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { GridDataRow
|
|
1
|
+
import { GridDataRow } from "../components/Row";
|
|
2
2
|
import { RowStates } from "./RowStates";
|
|
3
|
+
import { SelectedState } from "./TableState";
|
|
3
4
|
/**
|
|
4
5
|
* A reactive/observable state of each GridDataRow's current behavior.
|
|
5
6
|
*
|
|
@@ -7,6 +8,7 @@ import { RowStates } from "./RowStates";
|
|
|
7
8
|
* that uses parent/children easier to write, i.e. selected-ness and collapsed-ness.
|
|
8
9
|
*/
|
|
9
10
|
export declare class RowState {
|
|
11
|
+
private states;
|
|
10
12
|
/** Our row, only ref observed, so we don't crawl into GraphQL fragments. */
|
|
11
13
|
row: GridDataRow<any>;
|
|
12
14
|
/** Our children row states, as of the latest `props.rows`, without any filtering applied. */
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RowState = void 0;
|
|
4
4
|
const mobx_1 = require("mobx");
|
|
5
|
-
const
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
6
|
/**
|
|
7
7
|
* A reactive/observable state of each GridDataRow's current behavior.
|
|
8
8
|
*
|
|
@@ -15,6 +15,7 @@ class RowState {
|
|
|
15
15
|
// isEffectiveMatched = isDirectlyMatched || hasMatchedChildren
|
|
16
16
|
constructor(states, row) {
|
|
17
17
|
var _a;
|
|
18
|
+
this.states = states;
|
|
18
19
|
/** Our children row states, as of the latest `props.rows`, without any filtering applied. */
|
|
19
20
|
this.children = undefined;
|
|
20
21
|
/** Whether we match a client-side filter; true if no filter is in place. */
|
|
@@ -108,21 +109,19 @@ class RowState {
|
|
|
108
109
|
* child of a selected parent row.
|
|
109
110
|
*/
|
|
110
111
|
select(selected) {
|
|
111
|
-
if (this.row.selectable
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
if (this.row.selectable !== false) {
|
|
113
|
+
this.selected = selected;
|
|
114
|
+
}
|
|
114
115
|
// We don't check inferSelectedState here, b/c even if the parent is considered selectable
|
|
115
116
|
// on its own, we still push down selected-ness to our visible children.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
child.select(selected);
|
|
119
|
-
}
|
|
117
|
+
for (const child of this.visibleChildren) {
|
|
118
|
+
child.select(selected);
|
|
120
119
|
}
|
|
121
120
|
}
|
|
122
121
|
/** Marks the row as removed from `props.rows`, to potentially become kept. */
|
|
123
122
|
markRemoved() {
|
|
124
123
|
// The kept group is never in `props.rows`, so ignore asks to delete it
|
|
125
|
-
if (this.row.kind ===
|
|
124
|
+
if (this.row.kind === utils_1.KEPT_GROUP)
|
|
126
125
|
return;
|
|
127
126
|
this.removed = this.selected && this.removed !== "hard" ? "soft" : "hard";
|
|
128
127
|
}
|
|
@@ -136,7 +135,7 @@ class RowState {
|
|
|
136
135
|
// - or it has (probably) been server-side filtered
|
|
137
136
|
return (this.selected &&
|
|
138
137
|
// Headers, totals, etc., do not need keeping
|
|
139
|
-
!
|
|
138
|
+
!utils_1.reservedRowKinds.includes(this.row.kind) &&
|
|
140
139
|
!this.isParent &&
|
|
141
140
|
(!this.isMatched || this.removed === "soft"));
|
|
142
141
|
}
|
|
@@ -144,15 +143,15 @@ class RowState {
|
|
|
144
143
|
return this.row.inferSelectedState !== false;
|
|
145
144
|
}
|
|
146
145
|
get visibleChildren() {
|
|
147
|
-
var _a, _b
|
|
148
|
-
// The keptGroup
|
|
149
|
-
if (this.row.kind ===
|
|
150
|
-
return
|
|
146
|
+
var _a, _b;
|
|
147
|
+
// The keptGroup is special and its children are the dynamically kept rows
|
|
148
|
+
if (this.row.kind === utils_1.KEPT_GROUP)
|
|
149
|
+
return this.states.keptRows;
|
|
151
150
|
// Ignore hard-deleted rows, i.e. from `api.deleteRows`; in theory any hard-deleted
|
|
152
151
|
// rows should be removed from `this.children` anyway, by a change to `props.rows`,
|
|
153
152
|
// but just in case the user calls _only_ `api.deleteRows`, and expects the row to
|
|
154
153
|
// go away, go ahead and filter them out here.
|
|
155
|
-
return (
|
|
154
|
+
return (_b = (_a = this.children) === null || _a === void 0 ? void 0 : _a.filter((c) => c.isMatched === true && c.removed !== "hard")) !== null && _b !== void 0 ? _b : [];
|
|
156
155
|
}
|
|
157
156
|
/**
|
|
158
157
|
* Returns whether this row should act like a parent.
|
|
@@ -31,5 +31,5 @@ export declare class RowStates {
|
|
|
31
31
|
get keptRows(): RowState[];
|
|
32
32
|
get collapsedRows(): RowState[];
|
|
33
33
|
/** Create our synthetic "group row" for kept rows, that users never pass in, but we self-inject as needed. */
|
|
34
|
-
private
|
|
34
|
+
private createKeptGroupRow;
|
|
35
35
|
}
|
|
@@ -14,7 +14,7 @@ class RowStates {
|
|
|
14
14
|
this.map = new mobx_1.ObservableMap();
|
|
15
15
|
this.storage = new RowStorage_1.RowStorage(this);
|
|
16
16
|
// Pre-create our keptGroupRow for if/when we need it.
|
|
17
|
-
this.keptGroupRow = this.
|
|
17
|
+
this.keptGroupRow = this.createKeptGroupRow();
|
|
18
18
|
this.header = undefined;
|
|
19
19
|
/** The first level of rows, i.e. not the header (or kept group), but the totals + top-level children. */
|
|
20
20
|
this.topRows = [];
|
|
@@ -65,22 +65,16 @@ class RowStates {
|
|
|
65
65
|
this.topRows = rows.filter((row) => row !== headerRow).map((row) => addRowAndChildren(row));
|
|
66
66
|
// And attach them to the header for select-all/etc. to work
|
|
67
67
|
if (this.header) {
|
|
68
|
-
this.header.children =
|
|
68
|
+
this.header.children = [
|
|
69
|
+
// Always add the keptGroupRow, and we'll use keptGroupRow.isMatched=true/false to keep it
|
|
70
|
+
// from messing up "header is all selected" if its hidden/when there are no kept rows.
|
|
71
|
+
this.keptGroupRow,
|
|
72
|
+
...this.topRows.filter((rs) => !utils_1.reservedRowKinds.includes(rs.row.kind)),
|
|
73
|
+
];
|
|
69
74
|
}
|
|
70
75
|
// Then mark any remaining as removed
|
|
71
76
|
for (const state of existing)
|
|
72
77
|
state.markRemoved();
|
|
73
|
-
const keptRows = this.keptRows;
|
|
74
|
-
if (keptRows.length > 0) {
|
|
75
|
-
// Stitch the current keptRows into the placeholder keptGroupRow
|
|
76
|
-
this.keptGroupRow.children = keptRows;
|
|
77
|
-
this.keptGroupRow.row.children = keptRows.map((rs) => rs.row);
|
|
78
|
-
// And then stitch the keptGroupRow itself into the root header, so that the kept rows
|
|
79
|
-
// are treated as just another child for the header's select/unselect all to work.
|
|
80
|
-
if (this.header) {
|
|
81
|
-
this.header.children.unshift(this.keptGroupRow);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
78
|
// After the first load of real data, we detach collapse state, to respect
|
|
85
79
|
// any incoming initCollapsed.
|
|
86
80
|
if (this.topRows.some((rs) => !utils_1.reservedRowKinds.includes(rs.row.kind))) {
|
|
@@ -134,6 +128,11 @@ class RowStates {
|
|
|
134
128
|
rs.isMatched = ids.includes(rs.row.id);
|
|
135
129
|
}
|
|
136
130
|
}
|
|
131
|
+
// We cheat a little and pretend the "kept group matches the filter" not based on it itself
|
|
132
|
+
// literally matching the filter, or its children matching the filter (which is typically
|
|
133
|
+
// how the filter logic works), but if it just has any child rows at all (which actually means
|
|
134
|
+
// its children did _not_ match the filter, but are kept).
|
|
135
|
+
this.keptGroupRow.isMatched = this.keptRows.length > 0;
|
|
137
136
|
}
|
|
138
137
|
/** Returns kept rows, i.e. those that were user-selected but then client-side or server-side filtered. */
|
|
139
138
|
get keptRows() {
|
|
@@ -143,10 +142,20 @@ class RowStates {
|
|
|
143
142
|
return this.allStates.filter((rs) => rs.collapsed);
|
|
144
143
|
}
|
|
145
144
|
/** Create our synthetic "group row" for kept rows, that users never pass in, but we self-inject as needed. */
|
|
146
|
-
|
|
145
|
+
createKeptGroupRow() {
|
|
147
146
|
// The "group row" for selected rows that are hidden by filters and add the children
|
|
148
|
-
const keptGroupRow = {
|
|
149
|
-
|
|
147
|
+
const keptGroupRow = {
|
|
148
|
+
id: utils_1.KEPT_GROUP,
|
|
149
|
+
kind: utils_1.KEPT_GROUP,
|
|
150
|
+
initCollapsed: true,
|
|
151
|
+
selectable: false,
|
|
152
|
+
data: undefined,
|
|
153
|
+
children: [],
|
|
154
|
+
};
|
|
155
|
+
const rs = new RowState_1.RowState(this, keptGroupRow);
|
|
156
|
+
// Make the RowState behave like a parent, even though we calc its visibleChildren.
|
|
157
|
+
rs.children = [];
|
|
158
|
+
return rs;
|
|
150
159
|
}
|
|
151
160
|
}
|
|
152
161
|
exports.RowStates = RowStates;
|
|
@@ -45,12 +45,8 @@ class TableState {
|
|
|
45
45
|
// Make ourselves an observable so that mobx will do caching of .collapseIds so
|
|
46
46
|
// that it'll be a stable identity for GridTable to useMemo against.
|
|
47
47
|
(0, mobx_1.makeAutoObservable)(this, {
|
|
48
|
-
// We
|
|
49
|
-
|
|
50
|
-
// b) if rows changes, we re-run computeds like getSelectedRows that may need to see the
|
|
51
|
-
// updated _contents_ of a given row, even if our other selected/matched row states don't change.
|
|
52
|
-
// (as any b/c rows is private, so the mapped type doesn't see it)
|
|
53
|
-
rows: mobx_1.observable.shallow,
|
|
48
|
+
// We use `ref`s so that observables can watch the immutable data change w/o deeply proxy-ifying Apollo fragments
|
|
49
|
+
rows: mobx_1.observable.ref,
|
|
54
50
|
columns: mobx_1.observable.ref,
|
|
55
51
|
});
|
|
56
52
|
// If the kept rows went from empty to not empty, then introduce the SELECTED_GROUP row as collapsed
|
|
@@ -119,10 +115,6 @@ class TableState {
|
|
|
119
115
|
}
|
|
120
116
|
// Updates the list of rows and regenerates the collapsedRows property if needed.
|
|
121
117
|
setRows(rows) {
|
|
122
|
-
// Note that because of using `rows: observable.shallow` above, this is always
|
|
123
|
-
// false, and this logic runs on every render. We can eventually fix this, but it
|
|
124
|
-
// is convenient b/c it puts no-longer-kept rows back into the right spot in their
|
|
125
|
-
// parents.
|
|
126
118
|
if (rows !== this.rows) {
|
|
127
119
|
this.rowStates.setRows(rows);
|
|
128
120
|
this.rows = rows;
|
|
@@ -26,8 +26,6 @@ function DateFieldBase(props) {
|
|
|
26
26
|
const overlayRef = (0, react_1.useRef)(null);
|
|
27
27
|
// Local focus ref used to avoid updating WIP values
|
|
28
28
|
const isFocused = (0, react_1.useRef)(false);
|
|
29
|
-
// Ref helper to identify when focus is returned to the TextField due to the DatePicker closing.
|
|
30
|
-
const closingDatePicker = (0, react_1.useRef)(false);
|
|
31
29
|
const dateFormat = (0, utils_1.getDateFormat)(format);
|
|
32
30
|
// The `wipValue` allows the "range" mode to set the value to `undefined`, even if the `onChange` response cannot be undefined.
|
|
33
31
|
// This makes working within the DateRangePicker much more user-friendly.
|
|
@@ -45,10 +43,6 @@ function DateFieldBase(props) {
|
|
|
45
43
|
value: inputValue,
|
|
46
44
|
};
|
|
47
45
|
const state = (0, react_stately_1.useOverlayTriggerState)({ isOpen: defaultOpen });
|
|
48
|
-
const onPickerClose = (0, react_1.useCallback)(() => {
|
|
49
|
-
closingDatePicker.current = true;
|
|
50
|
-
state.close();
|
|
51
|
-
}, [state]);
|
|
52
46
|
const { labelProps, inputProps } = (0, react_aria_1.useTextField)({
|
|
53
47
|
...textFieldProps,
|
|
54
48
|
// Setting `inputMode` to none. This disables the virtual keyboard from being triggered on touch devices
|
|
@@ -56,12 +50,6 @@ function DateFieldBase(props) {
|
|
|
56
50
|
onFocus: () => {
|
|
57
51
|
var _a;
|
|
58
52
|
isFocused.current = true;
|
|
59
|
-
// Open overlay on focus of the input, only if the focus is not triggered due to the overlay being closed.
|
|
60
|
-
if (!closingDatePicker.current) {
|
|
61
|
-
state.open();
|
|
62
|
-
}
|
|
63
|
-
// Reset the closingDatePicker ref to false, so that the overlay can be opened again on the next focus event
|
|
64
|
-
closingDatePicker.current = false;
|
|
65
53
|
(0, utils_2.maybeCall)(onFocus);
|
|
66
54
|
if (wipValue && dateFormat !== utils_1.dateFormats.short) {
|
|
67
55
|
// When focused, change to use the "short" date format, as it is simpler to update by hand and parse.
|
|
@@ -74,7 +62,6 @@ function DateFieldBase(props) {
|
|
|
74
62
|
var _a, _b;
|
|
75
63
|
// Resets the ref variables when the input loses focus.
|
|
76
64
|
isFocused.current = false;
|
|
77
|
-
closingDatePicker.current = false;
|
|
78
65
|
// If interacting with the overlay or the input, then assume the user is still working within the DatePicker and return early to not trigger onBlur functionality.
|
|
79
66
|
if ((inputWrapRef.current && inputWrapRef.current.contains(e.relatedTarget)) ||
|
|
80
67
|
(overlayRef.current && overlayRef.current.contains(e.relatedTarget))) {
|
|
@@ -107,18 +94,13 @@ function DateFieldBase(props) {
|
|
|
107
94
|
},
|
|
108
95
|
}, inputRef);
|
|
109
96
|
const { triggerProps, overlayProps } = (0, react_aria_1.useOverlayTrigger)({ type: "dialog" }, state, buttonRef);
|
|
110
|
-
const { buttonProps } = (0, react_aria_1.useButton)({
|
|
111
|
-
...triggerProps,
|
|
112
|
-
isDisabled: isDisabled || isReadOnly,
|
|
113
|
-
// When pressed then move focus the input, which will select the text and trigger the DatePicker to open
|
|
114
|
-
onPress: () => { var _a; return (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); },
|
|
115
|
-
}, buttonRef);
|
|
97
|
+
const { buttonProps } = (0, react_aria_1.useButton)({ ...triggerProps, isDisabled: isDisabled || isReadOnly, onPress: state.open }, buttonRef);
|
|
116
98
|
const { overlayProps: positionProps } = (0, react_aria_1.useOverlayPosition)({
|
|
117
99
|
targetRef: inputWrapRef,
|
|
118
100
|
overlayRef,
|
|
119
101
|
shouldFlip: true,
|
|
120
102
|
isOpen: state.isOpen,
|
|
121
|
-
onClose:
|
|
103
|
+
onClose: state.close,
|
|
122
104
|
placement: "bottom left",
|
|
123
105
|
shouldUpdatePosition: true,
|
|
124
106
|
offset: 4,
|
|
@@ -164,11 +146,11 @@ function DateFieldBase(props) {
|
|
|
164
146
|
setInputValue("");
|
|
165
147
|
onChange(undefined);
|
|
166
148
|
} })) }));
|
|
167
|
-
const calendarButton = ((0, jsx_runtime_1.jsx)("button", { ref: buttonRef, ...buttonProps, disabled: isDisabled, css: Css_1.Css.if(isDisabled).cursorNotAllowed.$,
|
|
149
|
+
const calendarButton = ((0, jsx_runtime_1.jsx)("button", { ref: buttonRef, ...buttonProps, disabled: isDisabled, css: Css_1.Css.if(isDisabled).cursorNotAllowed.$, ...tid.calendarButton, children: (0, jsx_runtime_1.jsx)(components_1.Icon, { icon: "calendar", color: isDisabled ? Css_1.Palette.Gray400 : Css_1.Palette.Gray700 }) }));
|
|
168
150
|
const EndFieldButtons = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isRangeFilterField && clearButton, !hideCalendarIcon && calendarButton] }));
|
|
169
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(TextFieldBase_1.TextFieldBase, { ...textFieldProps, ...{ internalProps: { forceFocus: state.isOpen } }, errorMsg: errorMsg, helperText: helperText, required: required, labelProps: labelProps, inputProps: { ...inputProps, size: inputSize }, inputRef: inputRef, inputWrapRef: inputWrapRef, onChange: (v) => {
|
|
151
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(TextFieldBase_1.TextFieldBase, { ...textFieldProps, ...{ internalProps: { forceFocus: state.isOpen } }, errorMsg: errorMsg, helperText: helperText, required: required, labelProps: labelProps, inputProps: { ...inputProps, size: inputSize, onClick: state.open }, inputRef: inputRef, inputWrapRef: inputWrapRef, onChange: (v) => {
|
|
170
152
|
// hide the calendar if the user is manually entering the date
|
|
171
|
-
|
|
153
|
+
state.close();
|
|
172
154
|
if (v) {
|
|
173
155
|
setInputValue(v);
|
|
174
156
|
// If changing the value directly (vs using the DatePicker), then we always use the short format
|
|
@@ -179,16 +161,16 @@ function DateFieldBase(props) {
|
|
|
179
161
|
else if (v === undefined) {
|
|
180
162
|
setInputValue("");
|
|
181
163
|
}
|
|
182
|
-
}, endAdornment: !iconLeft && EndFieldButtons, startAdornment: !hideCalendarIcon && iconLeft && calendarButton, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), ...others }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: inputWrapRef, popoverRef: overlayRef, positionProps: positionProps, onClose:
|
|
164
|
+
}, endAdornment: !iconLeft && EndFieldButtons, startAdornment: !hideCalendarIcon && iconLeft && calendarButton, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), ...others }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: inputWrapRef, popoverRef: overlayRef, positionProps: positionProps, onClose: state.close, isOpen: state.isOpen, children: (0, jsx_runtime_1.jsx)(react_aria_1.FocusScope, { autoFocus: true, contain: true, restoreFocus: true, children: (0, jsx_runtime_1.jsx)(DatePickerOverlay_1.DatePickerOverlay, { overlayProps: overlayProps, children: isRangeMode ? ((0, jsx_runtime_1.jsx)(internal_1.DateRangePicker, { range: wipValue, disabledDays: disabledDays, onSelect: (dr) => {
|
|
183
165
|
var _a;
|
|
184
166
|
// Note: Do not close date range picker on select to allow the user to select multiple dates at a time
|
|
185
167
|
setInputValue((_a = (0, utils_1.formatDateRange)(dr, utils_1.dateFormats.short)) !== null && _a !== void 0 ? _a : "");
|
|
186
168
|
onChange(dr);
|
|
187
169
|
}, useYearPicker: isRangeFilterField, ...tid.datePicker })) : ((0, jsx_runtime_1.jsx)(internal_1.DatePicker, { value: wipValue, disabledDays: disabledDays, onSelect: (d) => {
|
|
188
170
|
var _a;
|
|
171
|
+
state.close();
|
|
189
172
|
setInputValue((_a = (0, utils_1.formatDate)(d, utils_1.dateFormats.short)) !== null && _a !== void 0 ? _a : "");
|
|
190
173
|
onChange(d);
|
|
191
|
-
onPickerClose();
|
|
192
174
|
}, ...tid.datePicker })) }) }) }))] }));
|
|
193
175
|
}
|
|
194
176
|
exports.DateFieldBase = DateFieldBase;
|