@absreim/react-bootstrap-data-grid 2.4.0 → 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.
@@ -7,7 +7,7 @@ var ColHeaderCell = function (_a) {
7
7
  var label = _a.label, sortModel = _a.sortModel, ariaColIndex = _a.ariaColIndex, additionalClasses = _a.additionalClasses, width = _a.width;
8
8
  var _b = useSortHeaderStates(sortModel), handleClick = _b.handleClick, handleMouseOver = _b.handleMouseOver, handleMouseOut = _b.handleMouseOut, sortSymbol = _b.sortSymbol;
9
9
  return (_jsxs("th", { className: classNames({
10
- "rbdg-clickable-grid-header-cell": sortModel,
10
+ "rbdg-sort-toggler": sortModel,
11
11
  "table-active": sortModel === null || sortModel === void 0 ? void 0 : sortModel.sortOrder,
12
12
  }, additionalClasses || []), onClick: sortModel && handleClick, onMouseOver: handleMouseOver, onMouseOut: handleMouseOut, "aria-description": sortModel
13
13
  ? "Column header"
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.0",
4
+ "version": "2.5.0",
5
5
  "license": "MIT",
6
6
  "author": "Brook Li",
7
7
  "homepage": "https://react-bootstrap-data-grid.vercel.app/",
@@ -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
- return (_jsx("div", { className: classNames(toolbarClasses || ["hstack", "gap-2", "justify-content-start", "px-2"]), role: "toolbar", children: Object.keys(buttonSpecs)
17
- .filter(function (toolbarOption) { return !!enabledFeatures[toolbarOption]; })
18
- .map(function (toolbarOption) { return (_jsx("button", { "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
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",