@absreim/react-bootstrap-data-grid 1.4.1 → 1.4.2
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/Grid.js +33 -4
- package/editing/EditControlsCell.js +7 -7
- package/package.json +1 -1
- package/selection/SelectAllHeaderCell.d.ts +3 -3
- package/selection/SelectAllHeaderCell.js +44 -31
- package/selection/types.d.ts +10 -0
- package/style.css +1 -1
- package/style.scss +1 -39
- package/util/isSubset.d.ts +2 -0
- package/util/isSubset.js +11 -0
- package/selection/deselectAll.d.ts +0 -2
- package/selection/deselectAll.js +0 -3
- package/selection/selectAll.d.ts +0 -2
- package/selection/selectAll.js +0 -3
package/Grid.js
CHANGED
|
@@ -17,6 +17,7 @@ import EditableRow from "./editing/EditableRow";
|
|
|
17
17
|
import inputStrsToRowDef from "./editing/inputStrsToRowDef";
|
|
18
18
|
import { unwrapAdditionalComponentsStyleModel, unwrapTableStyleModel, } from "./styling/styleModelUnwrappers";
|
|
19
19
|
import useCurrentPageRows from "./pipeline/useCurrentPageRows";
|
|
20
|
+
import isSubset from "./util/isSubset";
|
|
20
21
|
var Grid = function (_a) {
|
|
21
22
|
var _b;
|
|
22
23
|
var rows = _a.rows, cols = _a.cols, pagination = _a.pagination, sortModel = _a.sortModel, filterModel = _a.filterModel, selectModel = _a.selectModel, editModel = _a.editModel, caption = _a.caption, styleModel = _a.styleModel;
|
|
@@ -56,8 +57,8 @@ var Grid = function (_a) {
|
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
59
|
if (!selectionExists && selectModel.type === "multi") {
|
|
59
|
-
var
|
|
60
|
-
selectModel.setSelected(
|
|
60
|
+
var allRowIndices = rows.map(function (_, index) { return index; });
|
|
61
|
+
selectModel.setSelected(allRowIndices);
|
|
61
62
|
}
|
|
62
63
|
// Button should be disabled in the case of selectionExists &&
|
|
63
64
|
// selectModel.type === "single", so function execution should never get
|
|
@@ -102,7 +103,35 @@ var Grid = function (_a) {
|
|
|
102
103
|
selectedSet.add(selectModel.selected);
|
|
103
104
|
}
|
|
104
105
|
var rowsAreSelectable = !!(selectModel && selectModel.mode !== "column");
|
|
105
|
-
var
|
|
106
|
+
var selectionInfo = useMemo(function () {
|
|
107
|
+
if (!selectModel) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (selectModel.type === "single") {
|
|
111
|
+
return {
|
|
112
|
+
selectType: "single",
|
|
113
|
+
existingSelection: selectionExists
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
var getMultiExistingSelection = function (selectionExists, rows) {
|
|
117
|
+
var rowIndices = rows.map(function (_, index) { return index; });
|
|
118
|
+
var isFullSelection = isSubset(rowIndices, selectModel.selected);
|
|
119
|
+
// Note that isFullSelection is true if there are no rows at all. In that case, the existing selection value
|
|
120
|
+
// should be "none", not "full".
|
|
121
|
+
if (!selectionExists) {
|
|
122
|
+
return "none";
|
|
123
|
+
}
|
|
124
|
+
if (isFullSelection) {
|
|
125
|
+
return "full";
|
|
126
|
+
}
|
|
127
|
+
return "partial";
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
selectType: "multi",
|
|
131
|
+
existingSelection: getMultiExistingSelection(selectionExists, rows)
|
|
132
|
+
};
|
|
133
|
+
}, [selectModel, selectionExists, rows]);
|
|
134
|
+
var getRowClickHandler = function (index) { return function () {
|
|
106
135
|
if (!rowsAreSelectable) {
|
|
107
136
|
return;
|
|
108
137
|
}
|
|
@@ -132,7 +161,7 @@ var Grid = function (_a) {
|
|
|
132
161
|
}, [styleModel === null || styleModel === void 0 ? void 0 : styleModel.additionalComponentsStyleModel]);
|
|
133
162
|
return (_jsxs("div", { "data-testid": "rbdg-top-level-div", className: classNames(unwrappedAdditionalStyleModel.topLevelDiv), children: [filterState && filterModel && (_jsxs("div", { "data-testid": "rbdg-filter-inputs-div", className: classNames(unwrappedAdditionalStyleModel.filterInputsDiv), children: [_jsx(ToggleButton, { isActive: filterOptionsVisible, label: "".concat(filterOptionsVisible ? "Hide" : "Show ", " Filter Options"), onClick: handleToggleFilterOptions, classes: (_b = styleModel === null || styleModel === void 0 ? void 0 : styleModel.additionalComponentsStyleModel) === null || _b === void 0 ? void 0 : _b.filterUiToggleButton }), filterOptionsVisible && (_jsx(FilterOptionsTable, { caption: filterModel.filterTableCaption, filterState: filterState, setFilterState: filterModel.setTableFilterState, styleModel: styleModel === null || styleModel === void 0 ? void 0 : styleModel.filterInputTableStyleModel }))] })), _jsxs("div", { "data-testid": "rbdg-table-and-pagination-div", className: classNames(unwrappedAdditionalStyleModel.tableAndPaginationDiv), children: [_jsxs("table", { className: classNames("table", {
|
|
134
163
|
"table-hover": rowsAreSelectable,
|
|
135
|
-
}, unwrappedTableModel.table), "aria-rowcount": filteredRows.length + 1, children: [caption !== undefined && (_jsx("caption", { className: classNames(unwrappedTableModel.caption), children: caption })), _jsx("thead", { className: classNames(unwrappedTableModel.thead), children: _jsxs("tr", { "aria-rowindex": 1, className: classNames(unwrappedTableModel.theadTr), children: [showSelectCol && (_jsx(SelectAllHeaderCell, {
|
|
164
|
+
}, unwrappedTableModel.table), "aria-rowcount": filteredRows.length + 1, children: [caption !== undefined && (_jsx("caption", { className: classNames(unwrappedTableModel.caption), children: caption })), _jsx("thead", { className: classNames(unwrappedTableModel.thead), children: _jsxs("tr", { "aria-rowindex": 1, className: classNames(unwrappedTableModel.theadTr), children: [showSelectCol && (_jsx(SelectAllHeaderCell, { selectionInfo: selectionInfo, onClick: selectAllOnClick, totalRows: rows.length, additionalClasses: unwrappedTableModel.rowSelectColTh })), cols.map(function (_a, index) {
|
|
136
165
|
var _b;
|
|
137
166
|
var name = _a.name, label = _a.label, sortable = _a.sortable;
|
|
138
167
|
var colSortModel = sortModel && sortable
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import classNames from "classnames";
|
|
3
3
|
var stopPropagationWrapper = function (fn) { return function (event) {
|
|
4
4
|
event.stopPropagation();
|
|
@@ -6,14 +6,14 @@ var stopPropagationWrapper = function (fn) { return function (event) {
|
|
|
6
6
|
}; };
|
|
7
7
|
var EditControlsCell = function (_a) {
|
|
8
8
|
var ariaColIndex = _a.ariaColIndex, beginEditingCallback = _a.beginEditingCallback, cancelEditingCallback = _a.cancelEditingCallback, isEditing = _a.isEditing, saveCallback = _a.saveCallback, deleteCallback = _a.deleteCallback, editControlsCellClasses = _a.editControlsCellClasses, saveButtonClasses = _a.saveButtonClasses, deleteButtonClasses = _a.deleteButtonClasses, startButtonClasses = _a.startButtonClasses, cancelButtonClasses = _a.cancelButtonClasses;
|
|
9
|
-
return (_jsx("td", { "aria-colindex": ariaColIndex, className: classNames(editControlsCellClasses), children: _jsx("div", { className: "hstack gap-2", children: isEditing ? (_jsxs(_Fragment, { children: [_jsx("button", { className: classNames("btn", cancelButtonClasses.length === 0
|
|
9
|
+
return (_jsx("td", { "aria-colindex": ariaColIndex, className: classNames(editControlsCellClasses), children: _jsx("div", { className: "hstack gap-2", children: isEditing ? (_jsxs(_Fragment, { children: [_jsx("button", { "aria-label": "Cancel", className: classNames("btn", cancelButtonClasses.length === 0
|
|
10
10
|
? ["btn-secondary"]
|
|
11
|
-
: cancelButtonClasses), onClick: stopPropagationWrapper(cancelEditingCallback),
|
|
11
|
+
: cancelButtonClasses), onClick: stopPropagationWrapper(cancelEditingCallback), title: "Cancel", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "currentColor", viewBox: "0 0 16 16", children: _jsx("path", { d: "M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293z" }) }) }), _jsx("button", { "aria-label": "Save", className: classNames("btn", saveButtonClasses.length === 0
|
|
12
12
|
? ["btn-primary"]
|
|
13
|
-
: saveButtonClasses), onClick: stopPropagationWrapper(saveCallback),
|
|
14
|
-
? ["btn-
|
|
15
|
-
: deleteButtonClasses), onClick: stopPropagationWrapper(deleteCallback),
|
|
13
|
+
: saveButtonClasses), onClick: stopPropagationWrapper(saveCallback), title: "Save", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "currentColor", viewBox: "0 0 16 16", children: [_jsx("path", { d: "M12 2h-2v3h2z" }), _jsx("path", { d: "M1.5 0A1.5 1.5 0 0 0 0 1.5v13A1.5 1.5 0 0 0 1.5 16h13a1.5 1.5 0 0 0 1.5-1.5V2.914a1.5 1.5 0 0 0-.44-1.06L14.147.439A1.5 1.5 0 0 0 13.086 0zM4 6a1 1 0 0 1-1-1V1h10v4a1 1 0 0 1-1 1zM3 9h10a1 1 0 0 1 1 1v5H2v-5a1 1 0 0 1 1-1" })] }) })] })) : (_jsxs(_Fragment, { children: [deleteCallback && (_jsx("button", { "aria-label": "Delete", className: classNames("btn", deleteButtonClasses.length === 0
|
|
14
|
+
? ["btn-secondary"]
|
|
15
|
+
: deleteButtonClasses), onClick: stopPropagationWrapper(deleteCallback), title: "Delete", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "currentColor", viewBox: "0 0 16 16", children: _jsx("path", { d: "M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5M8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5m3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0" }) }) })), _jsx("button", { "aria-label": "Edit", className: classNames("btn", startButtonClasses.length === 0
|
|
16
16
|
? ["btn-primary"]
|
|
17
|
-
: startButtonClasses), onClick: stopPropagationWrapper(beginEditingCallback),
|
|
17
|
+
: startButtonClasses), onClick: stopPropagationWrapper(beginEditingCallback), title: "Edit", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "currentColor", viewBox: "0 0 16 16", children: [_jsx("path", { d: "M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z" }), _jsx("path", { fillRule: "evenodd", d: "M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5z" })] }) })] })) }) }));
|
|
18
18
|
};
|
|
19
19
|
export default EditControlsCell;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absreim/react-bootstrap-data-grid",
|
|
3
3
|
"description": "Data grid UI component for use with web apps using React and Bootstrap",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Brook Li",
|
|
7
7
|
"homepage": "https://react-bootstrap-data-grid.vercel.app/",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { SelectionInfo } from "./types";
|
|
3
3
|
interface SelectAllHeaderCellProps {
|
|
4
4
|
onClick: () => void;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
selectionInfo: SelectionInfo;
|
|
6
|
+
totalRows: number;
|
|
7
7
|
additionalClasses?: string[];
|
|
8
8
|
}
|
|
9
9
|
declare const SelectAllHeaderCell: FC<SelectAllHeaderCellProps>;
|
|
@@ -1,42 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import selectAll from "./selectAll";
|
|
4
|
-
import arrowPlaceholder from "../sorting/arrowPlaceholder";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
5
4
|
import classNames from "classnames";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return deselectAll;
|
|
5
|
+
var getCheckboxState = function (selectionInfo, noRows) {
|
|
6
|
+
var disabledState = {
|
|
7
|
+
indeterminate: false,
|
|
8
|
+
checked: false,
|
|
9
|
+
disabled: true,
|
|
10
|
+
description: "Select all (disabled)",
|
|
11
|
+
};
|
|
12
|
+
if (noRows) {
|
|
13
|
+
return disabledState;
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
var existingSelection = selectionInfo.existingSelection;
|
|
16
|
+
if (existingSelection === "full") {
|
|
17
|
+
return {
|
|
18
|
+
indeterminate: false,
|
|
19
|
+
checked: true,
|
|
20
|
+
disabled: false,
|
|
21
|
+
description: "Deselect all rows",
|
|
22
|
+
};
|
|
19
23
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
if (existingSelection === true || existingSelection === "partial") {
|
|
25
|
+
return {
|
|
26
|
+
indeterminate: true,
|
|
27
|
+
checked: true,
|
|
28
|
+
disabled: false,
|
|
29
|
+
description: "Deselect all rows",
|
|
30
|
+
};
|
|
26
31
|
}
|
|
27
|
-
if (
|
|
28
|
-
return
|
|
32
|
+
if (existingSelection === "none") {
|
|
33
|
+
return {
|
|
34
|
+
indeterminate: false,
|
|
35
|
+
checked: false,
|
|
36
|
+
disabled: false,
|
|
37
|
+
description: "Select all rows",
|
|
38
|
+
};
|
|
29
39
|
}
|
|
30
|
-
//
|
|
31
|
-
return
|
|
40
|
+
// single select mode and none selected
|
|
41
|
+
return disabledState;
|
|
32
42
|
};
|
|
33
43
|
var SelectAllHeaderCell = function (_a) {
|
|
34
|
-
var onClick = _a.onClick,
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
-
|
|
44
|
+
var onClick = _a.onClick, selectionInfo = _a.selectionInfo, totalRows = _a.totalRows, additionalClasses = _a.additionalClasses;
|
|
45
|
+
var noRows = totalRows === 0;
|
|
46
|
+
var _b = getCheckboxState(selectionInfo, noRows), indeterminate = _b.indeterminate, checked = _b.checked, disabled = _b.disabled, description = _b.description;
|
|
47
|
+
var ref = useRef(null);
|
|
48
|
+
useEffect(function () {
|
|
49
|
+
ref.current.indeterminate = indeterminate;
|
|
50
|
+
}, [indeterminate]);
|
|
51
|
+
return (_jsx("th", { "aria-colindex": 1, title: description, "aria-description": description, className: classNames({
|
|
38
52
|
"btn-primary": !additionalClasses || additionalClasses.length === 0,
|
|
39
|
-
|
|
40
|
-
}, additionalClasses || []), onClick: onClick, children: getSelectIcon(selectType, selectionExists) }));
|
|
53
|
+
}, additionalClasses || []), children: _jsx("input", { type: "checkbox", checked: checked, ref: ref, disabled: disabled, "aria-label": description, onChange: onClick }) }));
|
|
41
54
|
};
|
|
42
55
|
export default SelectAllHeaderCell;
|
package/selection/types.d.ts
CHANGED
|
@@ -14,3 +14,13 @@ export interface SingleSelectModel {
|
|
|
14
14
|
groupName: string;
|
|
15
15
|
}
|
|
16
16
|
export type SelectModel = SingleSelectModel | MultiSelectModel;
|
|
17
|
+
export type MultiExistingSelection = "full" | "partial" | "none";
|
|
18
|
+
export interface SingleSelectionInfo {
|
|
19
|
+
selectType: "single";
|
|
20
|
+
existingSelection: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface MultiSelectionInfo {
|
|
23
|
+
selectType: "multi";
|
|
24
|
+
existingSelection: 'full' | 'partial' | 'none';
|
|
25
|
+
}
|
|
26
|
+
export type SelectionInfo = SingleSelectionInfo | MultiSelectionInfo;
|
package/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.rbdg-clickable-grid-header-cell{cursor:pointer}
|
|
1
|
+
.rbdg-clickable-grid-header-cell{cursor:pointer}
|
package/style.scss
CHANGED
|
@@ -1,41 +1,3 @@
|
|
|
1
1
|
.rbdg-clickable-grid-header-cell {
|
|
2
2
|
cursor: pointer;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.rbdg-select-header-cell {
|
|
6
|
-
.rdbg-svg-icon {
|
|
7
|
-
background-color: var(--bs-btn-bg);
|
|
8
|
-
}
|
|
9
|
-
.rdbg-svg-icon-foreground {
|
|
10
|
-
color: var(--bs-btn-color);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
&:hover {
|
|
14
|
-
.rdbg-svg-icon {
|
|
15
|
-
background-color: var(--bs-btn-hover-bg);
|
|
16
|
-
}
|
|
17
|
-
.rdbg-svg-icon-foreground {
|
|
18
|
-
color: var(--bs-btn-hover-color);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.rbdg-grid {
|
|
24
|
-
display: table;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.rbdg-grid-head {
|
|
28
|
-
display: table-header-group;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.rbdg-grid-body {
|
|
32
|
-
display: table-row-group;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.rbdg-grid-row {
|
|
36
|
-
display: table-row;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.rbdg-grid-cell {
|
|
40
|
-
display: table-cell;
|
|
41
|
-
}
|
|
3
|
+
}
|
package/util/isSubset.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var isSubset = function (subset, superSet) {
|
|
2
|
+
var supersetSet = new Set(superSet);
|
|
3
|
+
for (var _i = 0, subset_1 = subset; _i < subset_1.length; _i++) {
|
|
4
|
+
var num = subset_1[_i];
|
|
5
|
+
if (!supersetSet.has(num)) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return true;
|
|
10
|
+
};
|
|
11
|
+
export default isSubset;
|
package/selection/deselectAll.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
var deselectAll = (_jsxs("svg", { className: "rdbg-svg-icon", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", width: "16", height: "16", fill: "currentColor", children: [_jsx("desc", { children: "Minus sign inside a square" }), _jsx("rect", { className: "rdbg-svg-icon-foreground", x: "3.5", y: "7.5", width: "9", height: "1" })] }));
|
|
3
|
-
export default deselectAll;
|
package/selection/selectAll.d.ts
DELETED
package/selection/selectAll.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
var selectAll = (_jsxs("svg", { className: "rdbg-svg-icon", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", width: "16", height: "16", fill: "currentColor", children: [_jsx("desc", { children: "Plus sign inside a square" }), _jsx("rect", { className: "rdbg-svg-icon-foreground", x: "3.5", y: "7.5", width: "9", height: "1" }), _jsx("rect", { className: "rdbg-svg-icon-foreground", x: "3.5", y: "7.5", width: "9", height: "1", transform: "translate(0 16) rotate(-90)" })] }));
|
|
3
|
-
export default selectAll;
|