@absreim/react-bootstrap-data-grid 2.4.1 → 2.5.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/package.json +1 -1
- package/toolbar/Toolbar.js +59 -4
- package/toolbar/ToolbarContainer.js +0 -2
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": "2.
|
|
4
|
+
"version": "2.5.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Brook Li",
|
|
7
7
|
"homepage": "https://react-bootstrap-data-grid.vercel.app/",
|
package/toolbar/Toolbar.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState, } from "react";
|
|
2
3
|
import classNames from "classnames";
|
|
3
4
|
var buttonSpecs = {
|
|
4
5
|
filtering: {
|
|
@@ -10,14 +11,68 @@ var buttonSpecs = {
|
|
|
10
11
|
icon: (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "currentColor", viewBox: "0 0 16 16", children: [_jsx("path", { d: "M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5" }), _jsx("path", { d: "M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z" })] })),
|
|
11
12
|
},
|
|
12
13
|
};
|
|
13
|
-
// TODO: figure out tabindex and accessibility
|
|
14
14
|
var Toolbar = function (_a) {
|
|
15
15
|
var enabledFeatures = _a.enabledFeatures, option = _a.option, setOption = _a.setOption, toolbarClasses = _a.toolbarClasses, activeClasses = _a.activeClasses, inactiveClasses = _a.inactiveClasses;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
var enabledOptions = useMemo(function () {
|
|
17
|
+
return Object.keys(buttonSpecs).filter(function (toolbarOption) { return !!enabledFeatures[toolbarOption]; });
|
|
18
|
+
}, [enabledFeatures]);
|
|
19
|
+
var _b = useState(enabledOptions[0] || null), focusableOption = _b[0], setFocusableOption = _b[1];
|
|
20
|
+
var divRef = useRef(null);
|
|
21
|
+
// Deals with cases where selected option is no longer available due to enabledFeatures prop getting changed.
|
|
22
|
+
var actualOption = useMemo(function () {
|
|
23
|
+
if (focusableOption === null || !enabledOptions.includes(focusableOption)) {
|
|
24
|
+
return enabledOptions[0] || null;
|
|
25
|
+
}
|
|
26
|
+
return focusableOption;
|
|
27
|
+
}, [enabledOptions, focusableOption]);
|
|
28
|
+
var onKeydown = function (event) {
|
|
29
|
+
if (actualOption === null) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
var currentIndex = enabledOptions.findIndex(function (option) { return option === actualOption; });
|
|
33
|
+
if (currentIndex === -1) {
|
|
34
|
+
// Should not happen due normalization of the value by the actualOption useMemo hook.
|
|
35
|
+
// This branch is put here anyway for explanatory purposes.
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (event.code === "ArrowLeft" && currentIndex - 1 < 0) {
|
|
39
|
+
setFocusableOption(enabledOptions[enabledOptions.length - 1]);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (event.code === "ArrowLeft" && currentIndex - 1 >= 0) {
|
|
43
|
+
setFocusableOption(enabledOptions[currentIndex - 1]);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (event.code === "ArrowRight" &&
|
|
47
|
+
currentIndex + 1 >= enabledOptions.length) {
|
|
48
|
+
setFocusableOption(enabledOptions[0]);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (event.code === "ArrowRight" &&
|
|
52
|
+
currentIndex + 1 < enabledOptions.length) {
|
|
53
|
+
setFocusableOption(enabledOptions[currentIndex + 1]);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
useEffect(function () {
|
|
58
|
+
if (actualOption === null) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (divRef.current === null) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!divRef.current.contains(document.activeElement)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
var focusTarget = divRef.current.querySelector(":scope > button[data-toolbar-option=\"".concat(actualOption, "\"]"));
|
|
68
|
+
if (focusTarget) {
|
|
69
|
+
focusTarget.focus();
|
|
70
|
+
}
|
|
71
|
+
}, [actualOption]);
|
|
72
|
+
return (_jsx("div", { ref: divRef, className: classNames(toolbarClasses || ["hstack", "gap-2", "justify-content-start", "px-2"]), role: "toolbar", onKeyDown: onKeydown, children: enabledOptions.map(function (toolbarOption) { return (_jsx("button", { tabIndex: actualOption === toolbarOption ? 0 : -1, "data-toolbar-option": toolbarOption, "aria-label": buttonSpecs[toolbarOption].label, "aria-roledescription": "Grouped toggle button to show/hide ".concat(toolbarOption, " UI"), "aria-pressed": option === toolbarOption, className: classNames.apply(void 0, (option === toolbarOption
|
|
19
73
|
? activeClasses || ["btn", "btn-outline-secondary", "active"]
|
|
20
74
|
: inactiveClasses || ["btn", "btn-outline-secondary"])), title: buttonSpecs[toolbarOption].label, onClick: function () {
|
|
75
|
+
setFocusableOption(toolbarOption);
|
|
21
76
|
setOption(option === toolbarOption
|
|
22
77
|
? null
|
|
23
78
|
: toolbarOption);
|
|
@@ -10,8 +10,6 @@ var ToolbarContainer = function (_a) {
|
|
|
10
10
|
!!interfaces[toolbarOption];
|
|
11
11
|
return prev;
|
|
12
12
|
}, {});
|
|
13
|
-
// TODO: mention in documentation that Bootstrap 5.3 is required due to the
|
|
14
|
-
// use of the z-index utility
|
|
15
13
|
return (_jsxs("div", { className: "vstack", "data-testid": "toolbar container", children: [_jsx(Toolbar, { enabledFeatures: enabledFeatures, option: option, setOption: setOption, toolbarClasses: styleModel === null || styleModel === void 0 ? void 0 : styleModel.toolbar, activeClasses: styleModel === null || styleModel === void 0 ? void 0 : styleModel.activeButton, inactiveClasses: styleModel === null || styleModel === void 0 ? void 0 : styleModel.inactiveButton }), _jsx("div", { className: "position-relative", children: option !== null && (_jsx("div", { "data-testid": "toolbar feature interface content container", className: classNames((styleModel === null || styleModel === void 0 ? void 0 : styleModel.interfaceContainer) || [
|
|
16
14
|
"position-absolute",
|
|
17
15
|
"z-1",
|