@patternfly/react-data-view 6.4.0-prerelease.12 → 6.4.0-prerelease.14

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.
@@ -16,6 +16,8 @@ export interface DataViewTextFilterProps extends SearchInputProps {
16
16
  trimValue?: boolean;
17
17
  /** Custom OUIA ID */
18
18
  ouiaId?: string;
19
+ /** Enable keyboard shortcut (/) to focus the filter. Defaults to true. */
20
+ enableShortcut?: boolean;
19
21
  }
20
22
  export declare const DataViewTextFilter: FC<DataViewTextFilterProps>;
21
23
  export default DataViewTextFilter;
@@ -13,9 +13,37 @@ var __rest = (this && this.__rest) || function (s, e) {
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.DataViewTextFilter = void 0;
15
15
  const jsx_runtime_1 = require("react/jsx-runtime");
16
+ const react_1 = require("react");
16
17
  const react_core_1 = require("@patternfly/react-core");
17
18
  const DataViewTextFilter = (_a) => {
18
- var { filterId, title, value = '', onChange, onClear = () => onChange === null || onChange === void 0 ? void 0 : onChange(undefined, ''), showToolbarItem, trimValue = true, ouiaId = 'DataViewTextFilter' } = _a, props = __rest(_a, ["filterId", "title", "value", "onChange", "onClear", "showToolbarItem", "trimValue", "ouiaId"]);
19
+ var { filterId, title, value = '', onChange, onClear = () => onChange === null || onChange === void 0 ? void 0 : onChange(undefined, ''), showToolbarItem, trimValue = true, ouiaId = 'DataViewTextFilter', enableShortcut = true } = _a, props = __rest(_a, ["filterId", "title", "value", "onChange", "onClear", "showToolbarItem", "trimValue", "ouiaId", "enableShortcut"]);
20
+ (0, react_1.useEffect)(() => {
21
+ if (!enableShortcut) {
22
+ return;
23
+ }
24
+ const handleKeyDown = (event) => {
25
+ // Only handle "/" key when not typing in an input, textarea, or contenteditable element
26
+ if (event.key === '/' && !event.ctrlKey && !event.metaKey && !event.altKey) {
27
+ const target = event.target;
28
+ const isInputElement = target.tagName === 'INPUT' ||
29
+ target.tagName === 'TEXTAREA' ||
30
+ target.isContentEditable;
31
+ // Only focus if the filter is visible and we're not already in an input field
32
+ if (showToolbarItem && !isInputElement) {
33
+ // Find the input element by its ID (searchInputId prop)
34
+ const inputElement = document.getElementById(filterId);
35
+ if (inputElement) {
36
+ event.preventDefault();
37
+ inputElement.focus();
38
+ }
39
+ }
40
+ }
41
+ };
42
+ window.addEventListener('keydown', handleKeyDown);
43
+ return () => {
44
+ window.removeEventListener('keydown', handleKeyDown);
45
+ };
46
+ }, [showToolbarItem, filterId, enableShortcut]);
19
47
  return ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarFilter, { "data-ouia-component-id": ouiaId, labels: value.length > 0 ? [{ key: title, node: value }] : [], deleteLabel: () => onChange === null || onChange === void 0 ? void 0 : onChange(undefined, ''), categoryName: title, showToolbarItem: showToolbarItem, children: (0, jsx_runtime_1.jsx)(react_core_1.SearchInput, Object.assign({ searchInputId: filterId, value: value, onChange: (e, inputValue) => onChange === null || onChange === void 0 ? void 0 : onChange(e, trimValue ? inputValue.trim() : inputValue), onClear: onClear, placeholder: `Filter by ${title}`, "aria-label": `${title !== null && title !== void 0 ? title : filterId} filter`, "data-ouia-component-id": `${ouiaId}-input` }, props)) }, ouiaId));
20
48
  };
21
49
  exports.DataViewTextFilter = DataViewTextFilter;
@@ -1 +1 @@
1
- export {};
1
+ import '@testing-library/jest-dom';
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  const react_1 = require("@testing-library/react");
8
+ require("@testing-library/jest-dom");
8
9
  const DataViewTextFilter_1 = __importDefault(require("./DataViewTextFilter"));
9
10
  const DataViewToolbar_1 = __importDefault(require("../DataViewToolbar"));
10
11
  describe('DataViewTextFilter component', () => {
@@ -19,4 +20,86 @@ describe('DataViewTextFilter component', () => {
19
20
  const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTextFilter_1.default, Object.assign({}, defaultProps)) }));
20
21
  expect(container).toMatchSnapshot();
21
22
  });
23
+ it('should focus the search input when "/" key is pressed and filter is visible', () => {
24
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTextFilter_1.default, Object.assign({}, defaultProps, { showToolbarItem: true })) }));
25
+ const input = document.getElementById('test-filter');
26
+ expect(input).toBeInTheDocument();
27
+ // Simulate pressing "/" key by creating and dispatching a KeyboardEvent
28
+ const keyEvent = new KeyboardEvent('keydown', {
29
+ key: '/',
30
+ code: 'Slash',
31
+ bubbles: true,
32
+ cancelable: true,
33
+ });
34
+ window.dispatchEvent(keyEvent);
35
+ // Check that the input has focus
36
+ expect(document.activeElement).toBe(input);
37
+ });
38
+ it('should not focus the search input when "/" key is pressed if filter is not visible', () => {
39
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTextFilter_1.default, Object.assign({}, defaultProps, { showToolbarItem: false })) }));
40
+ const input = document.getElementById('test-filter');
41
+ // Simulate pressing "/" key
42
+ const keyEvent = new KeyboardEvent('keydown', {
43
+ key: '/',
44
+ code: 'Slash',
45
+ bubbles: true,
46
+ cancelable: true,
47
+ });
48
+ window.dispatchEvent(keyEvent);
49
+ if (input) {
50
+ expect(document.activeElement).not.toBe(input);
51
+ }
52
+ });
53
+ it('should not focus the search input when "/" key is pressed while typing in another input', () => {
54
+ const { container } = (0, react_1.render)((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("input", { "data-testid": "other-input" }), (0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTextFilter_1.default, Object.assign({}, defaultProps, { showToolbarItem: true })) })] }));
55
+ const otherInput = container.querySelector('[data-testid="other-input"]');
56
+ // Focus the other input first
57
+ otherInput.focus();
58
+ expect(document.activeElement).toBe(otherInput);
59
+ // Simulate pressing "/" key while focused on the other input
60
+ // The event target should be the input element
61
+ const keyEvent = new KeyboardEvent('keydown', {
62
+ key: '/',
63
+ code: 'Slash',
64
+ bubbles: true,
65
+ cancelable: true,
66
+ });
67
+ Object.defineProperty(keyEvent, 'target', {
68
+ value: otherInput,
69
+ enumerable: true,
70
+ });
71
+ window.dispatchEvent(keyEvent);
72
+ // The search input should not be focused since we're already in an input field
73
+ expect(document.activeElement).toBe(otherInput);
74
+ });
75
+ it('should not focus the search input when enableShortcut is false', () => {
76
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTextFilter_1.default, Object.assign({}, defaultProps, { showToolbarItem: true, enableShortcut: false })) }));
77
+ const input = document.getElementById('test-filter');
78
+ expect(input).toBeInTheDocument();
79
+ // Simulate pressing "/" key
80
+ const keyEvent = new KeyboardEvent('keydown', {
81
+ key: '/',
82
+ code: 'Slash',
83
+ bubbles: true,
84
+ cancelable: true,
85
+ });
86
+ window.dispatchEvent(keyEvent);
87
+ // The input should not be focused since the shortcut is disabled
88
+ expect(document.activeElement).not.toBe(input);
89
+ });
90
+ it('should focus the search input when enableShortcut is true (default)', () => {
91
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(DataViewToolbar_1.default, { filters: (0, jsx_runtime_1.jsx)(DataViewTextFilter_1.default, Object.assign({}, defaultProps, { showToolbarItem: true })) }));
92
+ const input = document.getElementById('test-filter');
93
+ expect(input).toBeInTheDocument();
94
+ // Simulate pressing "/" key
95
+ const keyEvent = new KeyboardEvent('keydown', {
96
+ key: '/',
97
+ code: 'Slash',
98
+ bubbles: true,
99
+ cancelable: true,
100
+ });
101
+ window.dispatchEvent(keyEvent);
102
+ // The input should be focused since the shortcut is enabled by default
103
+ expect(document.activeElement).toBe(input);
104
+ });
22
105
  });
@@ -15,10 +15,22 @@ exports.DataViewToolbar = void 0;
15
15
  const jsx_runtime_1 = require("react/jsx-runtime");
16
16
  const react_1 = require("react");
17
17
  const react_core_1 = require("@patternfly/react-core");
18
+ const react_jss_1 = require("react-jss");
19
+ const useStyles = (0, react_jss_1.createUseStyles)({
20
+ dataViewToolbarPagination: {
21
+ flexBasis: '100%',
22
+ width: '100%'
23
+ },
24
+ dataViewToolbarPaginationWrapper: {
25
+ flexBasis: '100%',
26
+ width: '100%'
27
+ }
28
+ });
18
29
  const DataViewToolbar = (_a) => {
19
30
  var { className, ouiaId = 'DataViewToolbar', bulkSelect, actions, toggleGroup, pagination, filters, customLabelGroupContent, clearAllFilters, children } = _a, props = __rest(_a, ["className", "ouiaId", "bulkSelect", "actions", "toggleGroup", "pagination", "filters", "customLabelGroupContent", "clearAllFilters", "children"]);
31
+ const classes = useStyles();
20
32
  const defaultClearFilters = (0, react_1.useRef)((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { children: (0, jsx_runtime_1.jsx)(react_core_1.Button, { ouiaId: `${ouiaId}-clear-all-filters`, variant: "link", onClick: clearAllFilters, isInline: true, children: "Clear filters" }) }));
21
- return ((0, jsx_runtime_1.jsx)(react_core_1.Toolbar, Object.assign({ ouiaId: ouiaId, className: className, customLabelGroupContent: customLabelGroupContent !== null && customLabelGroupContent !== void 0 ? customLabelGroupContent : defaultClearFilters.current }, props, { children: (0, jsx_runtime_1.jsxs)(react_core_1.ToolbarContent, { children: [bulkSelect && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { "data-ouia-component-id": `${ouiaId}-bulk-select`, children: bulkSelect })), filters && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { children: filters })), actions && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { children: actions })), toggleGroup && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { children: toggleGroup })), pagination && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { variant: react_core_1.ToolbarItemVariant.pagination, "data-ouia-component-id": `${ouiaId}-pagination`, children: pagination })), children] }) })));
33
+ return ((0, jsx_runtime_1.jsx)(react_core_1.Toolbar, Object.assign({ ouiaId: ouiaId, className: className, customLabelGroupContent: customLabelGroupContent !== null && customLabelGroupContent !== void 0 ? customLabelGroupContent : defaultClearFilters.current }, props, { children: (0, jsx_runtime_1.jsxs)(react_core_1.ToolbarContent, { children: [bulkSelect && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { "data-ouia-component-id": `${ouiaId}-bulk-select`, children: bulkSelect })), filters && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { children: filters })), actions && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { children: actions })), toggleGroup && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { children: toggleGroup })), pagination && ((0, jsx_runtime_1.jsx)(react_core_1.ToolbarItem, { variant: react_core_1.ToolbarItemVariant.pagination, "data-ouia-component-id": `${ouiaId}-pagination`, className: classes.dataViewToolbarPagination, children: (0, jsx_runtime_1.jsx)("div", { className: classes.dataViewToolbarPaginationWrapper, children: pagination }) })), children] }) })));
22
34
  };
23
35
  exports.DataViewToolbar = DataViewToolbar;
24
36
  exports.default = exports.DataViewToolbar;
@@ -16,6 +16,8 @@ export interface DataViewTextFilterProps extends SearchInputProps {
16
16
  trimValue?: boolean;
17
17
  /** Custom OUIA ID */
18
18
  ouiaId?: string;
19
+ /** Enable keyboard shortcut (/) to focus the filter. Defaults to true. */
20
+ enableShortcut?: boolean;
19
21
  }
20
22
  export declare const DataViewTextFilter: FC<DataViewTextFilterProps>;
21
23
  export default DataViewTextFilter;
@@ -10,9 +10,37 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { useEffect } from 'react';
13
14
  import { SearchInput, ToolbarFilter } from '@patternfly/react-core';
14
15
  export const DataViewTextFilter = (_a) => {
15
- var { filterId, title, value = '', onChange, onClear = () => onChange === null || onChange === void 0 ? void 0 : onChange(undefined, ''), showToolbarItem, trimValue = true, ouiaId = 'DataViewTextFilter' } = _a, props = __rest(_a, ["filterId", "title", "value", "onChange", "onClear", "showToolbarItem", "trimValue", "ouiaId"]);
16
+ var { filterId, title, value = '', onChange, onClear = () => onChange === null || onChange === void 0 ? void 0 : onChange(undefined, ''), showToolbarItem, trimValue = true, ouiaId = 'DataViewTextFilter', enableShortcut = true } = _a, props = __rest(_a, ["filterId", "title", "value", "onChange", "onClear", "showToolbarItem", "trimValue", "ouiaId", "enableShortcut"]);
17
+ useEffect(() => {
18
+ if (!enableShortcut) {
19
+ return;
20
+ }
21
+ const handleKeyDown = (event) => {
22
+ // Only handle "/" key when not typing in an input, textarea, or contenteditable element
23
+ if (event.key === '/' && !event.ctrlKey && !event.metaKey && !event.altKey) {
24
+ const target = event.target;
25
+ const isInputElement = target.tagName === 'INPUT' ||
26
+ target.tagName === 'TEXTAREA' ||
27
+ target.isContentEditable;
28
+ // Only focus if the filter is visible and we're not already in an input field
29
+ if (showToolbarItem && !isInputElement) {
30
+ // Find the input element by its ID (searchInputId prop)
31
+ const inputElement = document.getElementById(filterId);
32
+ if (inputElement) {
33
+ event.preventDefault();
34
+ inputElement.focus();
35
+ }
36
+ }
37
+ }
38
+ };
39
+ window.addEventListener('keydown', handleKeyDown);
40
+ return () => {
41
+ window.removeEventListener('keydown', handleKeyDown);
42
+ };
43
+ }, [showToolbarItem, filterId, enableShortcut]);
16
44
  return (_jsx(ToolbarFilter, { "data-ouia-component-id": ouiaId, labels: value.length > 0 ? [{ key: title, node: value }] : [], deleteLabel: () => onChange === null || onChange === void 0 ? void 0 : onChange(undefined, ''), categoryName: title, showToolbarItem: showToolbarItem, children: _jsx(SearchInput, Object.assign({ searchInputId: filterId, value: value, onChange: (e, inputValue) => onChange === null || onChange === void 0 ? void 0 : onChange(e, trimValue ? inputValue.trim() : inputValue), onClear: onClear, placeholder: `Filter by ${title}`, "aria-label": `${title !== null && title !== void 0 ? title : filterId} filter`, "data-ouia-component-id": `${ouiaId}-input` }, props)) }, ouiaId));
17
45
  };
18
46
  export default DataViewTextFilter;
@@ -1 +1 @@
1
- export {};
1
+ import '@testing-library/jest-dom';
@@ -1,5 +1,6 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { render } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
3
4
  import DataViewTextFilter from './DataViewTextFilter';
4
5
  import DataViewToolbar from '../DataViewToolbar';
5
6
  describe('DataViewTextFilter component', () => {
@@ -14,4 +15,86 @@ describe('DataViewTextFilter component', () => {
14
15
  const { container } = render(_jsx(DataViewToolbar, { filters: _jsx(DataViewTextFilter, Object.assign({}, defaultProps)) }));
15
16
  expect(container).toMatchSnapshot();
16
17
  });
18
+ it('should focus the search input when "/" key is pressed and filter is visible', () => {
19
+ render(_jsx(DataViewToolbar, { filters: _jsx(DataViewTextFilter, Object.assign({}, defaultProps, { showToolbarItem: true })) }));
20
+ const input = document.getElementById('test-filter');
21
+ expect(input).toBeInTheDocument();
22
+ // Simulate pressing "/" key by creating and dispatching a KeyboardEvent
23
+ const keyEvent = new KeyboardEvent('keydown', {
24
+ key: '/',
25
+ code: 'Slash',
26
+ bubbles: true,
27
+ cancelable: true,
28
+ });
29
+ window.dispatchEvent(keyEvent);
30
+ // Check that the input has focus
31
+ expect(document.activeElement).toBe(input);
32
+ });
33
+ it('should not focus the search input when "/" key is pressed if filter is not visible', () => {
34
+ render(_jsx(DataViewToolbar, { filters: _jsx(DataViewTextFilter, Object.assign({}, defaultProps, { showToolbarItem: false })) }));
35
+ const input = document.getElementById('test-filter');
36
+ // Simulate pressing "/" key
37
+ const keyEvent = new KeyboardEvent('keydown', {
38
+ key: '/',
39
+ code: 'Slash',
40
+ bubbles: true,
41
+ cancelable: true,
42
+ });
43
+ window.dispatchEvent(keyEvent);
44
+ if (input) {
45
+ expect(document.activeElement).not.toBe(input);
46
+ }
47
+ });
48
+ it('should not focus the search input when "/" key is pressed while typing in another input', () => {
49
+ const { container } = render(_jsxs("div", { children: [_jsx("input", { "data-testid": "other-input" }), _jsx(DataViewToolbar, { filters: _jsx(DataViewTextFilter, Object.assign({}, defaultProps, { showToolbarItem: true })) })] }));
50
+ const otherInput = container.querySelector('[data-testid="other-input"]');
51
+ // Focus the other input first
52
+ otherInput.focus();
53
+ expect(document.activeElement).toBe(otherInput);
54
+ // Simulate pressing "/" key while focused on the other input
55
+ // The event target should be the input element
56
+ const keyEvent = new KeyboardEvent('keydown', {
57
+ key: '/',
58
+ code: 'Slash',
59
+ bubbles: true,
60
+ cancelable: true,
61
+ });
62
+ Object.defineProperty(keyEvent, 'target', {
63
+ value: otherInput,
64
+ enumerable: true,
65
+ });
66
+ window.dispatchEvent(keyEvent);
67
+ // The search input should not be focused since we're already in an input field
68
+ expect(document.activeElement).toBe(otherInput);
69
+ });
70
+ it('should not focus the search input when enableShortcut is false', () => {
71
+ render(_jsx(DataViewToolbar, { filters: _jsx(DataViewTextFilter, Object.assign({}, defaultProps, { showToolbarItem: true, enableShortcut: false })) }));
72
+ const input = document.getElementById('test-filter');
73
+ expect(input).toBeInTheDocument();
74
+ // Simulate pressing "/" key
75
+ const keyEvent = new KeyboardEvent('keydown', {
76
+ key: '/',
77
+ code: 'Slash',
78
+ bubbles: true,
79
+ cancelable: true,
80
+ });
81
+ window.dispatchEvent(keyEvent);
82
+ // The input should not be focused since the shortcut is disabled
83
+ expect(document.activeElement).not.toBe(input);
84
+ });
85
+ it('should focus the search input when enableShortcut is true (default)', () => {
86
+ render(_jsx(DataViewToolbar, { filters: _jsx(DataViewTextFilter, Object.assign({}, defaultProps, { showToolbarItem: true })) }));
87
+ const input = document.getElementById('test-filter');
88
+ expect(input).toBeInTheDocument();
89
+ // Simulate pressing "/" key
90
+ const keyEvent = new KeyboardEvent('keydown', {
91
+ key: '/',
92
+ code: 'Slash',
93
+ bubbles: true,
94
+ cancelable: true,
95
+ });
96
+ window.dispatchEvent(keyEvent);
97
+ // The input should be focused since the shortcut is enabled by default
98
+ expect(document.activeElement).toBe(input);
99
+ });
17
100
  });
@@ -12,9 +12,21 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import { useRef } from 'react';
14
14
  import { Button, Toolbar, ToolbarContent, ToolbarItem, ToolbarItemVariant } from '@patternfly/react-core';
15
+ import { createUseStyles } from 'react-jss';
16
+ const useStyles = createUseStyles({
17
+ dataViewToolbarPagination: {
18
+ flexBasis: '100%',
19
+ width: '100%'
20
+ },
21
+ dataViewToolbarPaginationWrapper: {
22
+ flexBasis: '100%',
23
+ width: '100%'
24
+ }
25
+ });
15
26
  export const DataViewToolbar = (_a) => {
16
27
  var { className, ouiaId = 'DataViewToolbar', bulkSelect, actions, toggleGroup, pagination, filters, customLabelGroupContent, clearAllFilters, children } = _a, props = __rest(_a, ["className", "ouiaId", "bulkSelect", "actions", "toggleGroup", "pagination", "filters", "customLabelGroupContent", "clearAllFilters", "children"]);
28
+ const classes = useStyles();
17
29
  const defaultClearFilters = useRef(_jsx(ToolbarItem, { children: _jsx(Button, { ouiaId: `${ouiaId}-clear-all-filters`, variant: "link", onClick: clearAllFilters, isInline: true, children: "Clear filters" }) }));
18
- return (_jsx(Toolbar, Object.assign({ ouiaId: ouiaId, className: className, customLabelGroupContent: customLabelGroupContent !== null && customLabelGroupContent !== void 0 ? customLabelGroupContent : defaultClearFilters.current }, props, { children: _jsxs(ToolbarContent, { children: [bulkSelect && (_jsx(ToolbarItem, { "data-ouia-component-id": `${ouiaId}-bulk-select`, children: bulkSelect })), filters && (_jsx(ToolbarItem, { children: filters })), actions && (_jsx(ToolbarItem, { children: actions })), toggleGroup && (_jsx(ToolbarItem, { children: toggleGroup })), pagination && (_jsx(ToolbarItem, { variant: ToolbarItemVariant.pagination, "data-ouia-component-id": `${ouiaId}-pagination`, children: pagination })), children] }) })));
30
+ return (_jsx(Toolbar, Object.assign({ ouiaId: ouiaId, className: className, customLabelGroupContent: customLabelGroupContent !== null && customLabelGroupContent !== void 0 ? customLabelGroupContent : defaultClearFilters.current }, props, { children: _jsxs(ToolbarContent, { children: [bulkSelect && (_jsx(ToolbarItem, { "data-ouia-component-id": `${ouiaId}-bulk-select`, children: bulkSelect })), filters && (_jsx(ToolbarItem, { children: filters })), actions && (_jsx(ToolbarItem, { children: actions })), toggleGroup && (_jsx(ToolbarItem, { children: toggleGroup })), pagination && (_jsx(ToolbarItem, { variant: ToolbarItemVariant.pagination, "data-ouia-component-id": `${ouiaId}-pagination`, className: classes.dataViewToolbarPagination, children: _jsx("div", { className: classes.dataViewToolbarPaginationWrapper, children: pagination }) })), children] }) })));
19
31
  };
20
32
  export default DataViewToolbar;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-data-view",
3
- "version": "6.4.0-prerelease.12",
3
+ "version": "6.4.0-prerelease.14",
4
4
  "description": "Data view used for Red Hat projects.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -244,7 +244,8 @@ const RepositoriesTable: FunctionComponent<RepositoriesTableProps> = ({ selected
244
244
  ouiaId='LayoutExampleFooter'
245
245
  pagination={
246
246
  <Pagination
247
- isCompact
247
+ isCompact
248
+ variant="bottom"
248
249
  perPageOptions={perPageOptions}
249
250
  itemCount={repositories.length}
250
251
  {...pagination}
@@ -89,7 +89,8 @@ const MyTable: React.FunctionComponent = () => {
89
89
  ouiaId='LayoutExampleFooter'
90
90
  pagination={
91
91
  <Pagination
92
- isCompact
92
+ isCompact
93
+ variant="bottom"
93
94
  perPageOptions={perPageOptions}
94
95
  itemCount={filteredData.length}
95
96
  {...pagination}
@@ -44,7 +44,7 @@ const MyTable: React.FunctionComponent = () => {
44
44
  <DataView>
45
45
  <DataViewToolbar ouiaId='DataViewHeader' pagination={<Pagination perPageOptions={perPageOptions} itemCount={repositories.length} {...pagination} />} />
46
46
  <DataViewTable aria-label='Repositories table' ouiaId={ouiaId} columns={columns} rows={pageRows} />
47
- <DataViewToolbar ouiaId='DataViewFooter' pagination={<Pagination isCompact perPageOptions={perPageOptions} itemCount={repositories.length} {...pagination} />} />
47
+ <DataViewToolbar ouiaId='DataViewFooter' pagination={<Pagination isCompact variant="bottom" perPageOptions={perPageOptions} itemCount={repositories.length} {...pagination} />} />
48
48
  </DataView>
49
49
  );
50
50
  };
@@ -234,7 +234,7 @@ const MyTable: React.FunctionComponent = () => {
234
234
  <DataViewToolbar
235
235
  ouiaId="TreeFilterExampleFooter"
236
236
  pagination={
237
- <Pagination isCompact perPageOptions={perPageOptions} itemCount={filteredData.length} {...pagination} />
237
+ <Pagination isCompact variant="bottom" perPageOptions={perPageOptions} itemCount={filteredData.length} {...pagination} />
238
238
  }
239
239
  />
240
240
  </DataView>
@@ -1,4 +1,5 @@
1
1
  import { render } from '@testing-library/react';
2
+ import '@testing-library/jest-dom';
2
3
  import DataViewTextFilter, { DataViewTextFilterProps } from './DataViewTextFilter';
3
4
  import DataViewToolbar from '../DataViewToolbar';
4
5
 
@@ -20,4 +21,132 @@ describe('DataViewTextFilter component', () => {
20
21
  />);
21
22
  expect(container).toMatchSnapshot();
22
23
  });
24
+
25
+ it('should focus the search input when "/" key is pressed and filter is visible', () => {
26
+ render(<DataViewToolbar
27
+ filters={
28
+ <DataViewTextFilter {...defaultProps} showToolbarItem={true} />
29
+ }
30
+ />);
31
+
32
+ const input = document.getElementById('test-filter') as HTMLInputElement;
33
+ expect(input).toBeInTheDocument();
34
+
35
+ // Simulate pressing "/" key by creating and dispatching a KeyboardEvent
36
+ const keyEvent = new KeyboardEvent('keydown', {
37
+ key: '/',
38
+ code: 'Slash',
39
+ bubbles: true,
40
+ cancelable: true,
41
+ });
42
+ window.dispatchEvent(keyEvent);
43
+
44
+ // Check that the input has focus
45
+ expect(document.activeElement).toBe(input);
46
+ });
47
+
48
+ it('should not focus the search input when "/" key is pressed if filter is not visible', () => {
49
+ render(<DataViewToolbar
50
+ filters={
51
+ <DataViewTextFilter {...defaultProps} showToolbarItem={false} />
52
+ }
53
+ />);
54
+
55
+ const input = document.getElementById('test-filter') as HTMLInputElement;
56
+
57
+ // Simulate pressing "/" key
58
+ const keyEvent = new KeyboardEvent('keydown', {
59
+ key: '/',
60
+ code: 'Slash',
61
+ bubbles: true,
62
+ cancelable: true,
63
+ });
64
+ window.dispatchEvent(keyEvent);
65
+
66
+ if (input) {
67
+ expect(document.activeElement).not.toBe(input);
68
+ }
69
+ });
70
+
71
+ it('should not focus the search input when "/" key is pressed while typing in another input', () => {
72
+ const { container } = render(
73
+ <div>
74
+ <input data-testid="other-input" />
75
+ <DataViewToolbar
76
+ filters={
77
+ <DataViewTextFilter {...defaultProps} showToolbarItem={true} />
78
+ }
79
+ />
80
+ </div>
81
+ );
82
+
83
+ const otherInput = container.querySelector('[data-testid="other-input"]') as HTMLInputElement;
84
+
85
+ // Focus the other input first
86
+ otherInput.focus();
87
+ expect(document.activeElement).toBe(otherInput);
88
+
89
+ // Simulate pressing "/" key while focused on the other input
90
+ // The event target should be the input element
91
+ const keyEvent = new KeyboardEvent('keydown', {
92
+ key: '/',
93
+ code: 'Slash',
94
+ bubbles: true,
95
+ cancelable: true,
96
+ });
97
+ Object.defineProperty(keyEvent, 'target', {
98
+ value: otherInput,
99
+ enumerable: true,
100
+ });
101
+ window.dispatchEvent(keyEvent);
102
+
103
+ // The search input should not be focused since we're already in an input field
104
+ expect(document.activeElement).toBe(otherInput);
105
+ });
106
+
107
+ it('should not focus the search input when enableShortcut is false', () => {
108
+ render(<DataViewToolbar
109
+ filters={
110
+ <DataViewTextFilter {...defaultProps} showToolbarItem={true} enableShortcut={false} />
111
+ }
112
+ />);
113
+
114
+ const input = document.getElementById('test-filter') as HTMLInputElement;
115
+ expect(input).toBeInTheDocument();
116
+
117
+ // Simulate pressing "/" key
118
+ const keyEvent = new KeyboardEvent('keydown', {
119
+ key: '/',
120
+ code: 'Slash',
121
+ bubbles: true,
122
+ cancelable: true,
123
+ });
124
+ window.dispatchEvent(keyEvent);
125
+
126
+ // The input should not be focused since the shortcut is disabled
127
+ expect(document.activeElement).not.toBe(input);
128
+ });
129
+
130
+ it('should focus the search input when enableShortcut is true (default)', () => {
131
+ render(<DataViewToolbar
132
+ filters={
133
+ <DataViewTextFilter {...defaultProps} showToolbarItem={true} />
134
+ }
135
+ />);
136
+
137
+ const input = document.getElementById('test-filter') as HTMLInputElement;
138
+ expect(input).toBeInTheDocument();
139
+
140
+ // Simulate pressing "/" key
141
+ const keyEvent = new KeyboardEvent('keydown', {
142
+ key: '/',
143
+ code: 'Slash',
144
+ bubbles: true,
145
+ cancelable: true,
146
+ });
147
+ window.dispatchEvent(keyEvent);
148
+
149
+ // The input should be focused since the shortcut is enabled by default
150
+ expect(document.activeElement).toBe(input);
151
+ });
23
152
  });
@@ -1,4 +1,4 @@
1
- import { FC } from 'react';
1
+ import { FC, useEffect } from 'react';
2
2
  import { SearchInput, SearchInputProps, ToolbarFilter, ToolbarFilterProps } from '@patternfly/react-core';
3
3
 
4
4
  /** extends SearchInputProps */
@@ -17,6 +17,8 @@ export interface DataViewTextFilterProps extends SearchInputProps {
17
17
  trimValue?: boolean;
18
18
  /** Custom OUIA ID */
19
19
  ouiaId?: string;
20
+ /** Enable keyboard shortcut (/) to focus the filter. Defaults to true. */
21
+ enableShortcut?: boolean;
20
22
  }
21
23
 
22
24
  export const DataViewTextFilter: FC<DataViewTextFilterProps> = ({
@@ -28,27 +30,61 @@ export const DataViewTextFilter: FC<DataViewTextFilterProps> = ({
28
30
  showToolbarItem,
29
31
  trimValue = true,
30
32
  ouiaId = 'DataViewTextFilter',
33
+ enableShortcut = true,
31
34
  ...props
32
- }: DataViewTextFilterProps) => (
33
- <ToolbarFilter
34
- key={ouiaId}
35
- data-ouia-component-id={ouiaId}
36
- labels={value.length > 0 ? [ { key: title, node: value } ] : []}
37
- deleteLabel={() => onChange?.(undefined, '')}
38
- categoryName={title}
39
- showToolbarItem={showToolbarItem}
40
- >
41
- <SearchInput
42
- searchInputId={filterId}
43
- value={value}
44
- onChange={(e, inputValue) => onChange?.(e, trimValue ? inputValue.trim() : inputValue)}
45
- onClear={onClear}
46
- placeholder={`Filter by ${title}`}
47
- aria-label={`${title ?? filterId} filter`}
48
- data-ouia-component-id={`${ouiaId}-input`}
49
- {...props}
50
- />
51
- </ToolbarFilter>
52
- );
35
+ }: DataViewTextFilterProps) => {
36
+ useEffect(() => {
37
+ if (!enableShortcut) {
38
+ return;
39
+ }
40
+
41
+ const handleKeyDown = (event: KeyboardEvent) => {
42
+ // Only handle "/" key when not typing in an input, textarea, or contenteditable element
43
+ if (event.key === '/' && !event.ctrlKey && !event.metaKey && !event.altKey) {
44
+ const target = event.target as HTMLElement;
45
+ const isInputElement = target.tagName === 'INPUT' ||
46
+ target.tagName === 'TEXTAREA' ||
47
+ target.isContentEditable;
48
+
49
+ // Only focus if the filter is visible and we're not already in an input field
50
+ if (showToolbarItem && !isInputElement) {
51
+ // Find the input element by its ID (searchInputId prop)
52
+ const inputElement = document.getElementById(filterId) as HTMLInputElement;
53
+ if (inputElement) {
54
+ event.preventDefault();
55
+ inputElement.focus();
56
+ }
57
+ }
58
+ }
59
+ };
60
+
61
+ window.addEventListener('keydown', handleKeyDown);
62
+ return () => {
63
+ window.removeEventListener('keydown', handleKeyDown);
64
+ };
65
+ }, [showToolbarItem, filterId, enableShortcut]);
66
+
67
+ return (
68
+ <ToolbarFilter
69
+ key={ouiaId}
70
+ data-ouia-component-id={ouiaId}
71
+ labels={value.length > 0 ? [ { key: title, node: value } ] : []}
72
+ deleteLabel={() => onChange?.(undefined, '')}
73
+ categoryName={title}
74
+ showToolbarItem={showToolbarItem}
75
+ >
76
+ <SearchInput
77
+ searchInputId={filterId}
78
+ value={value}
79
+ onChange={(e, inputValue) => onChange?.(e, trimValue ? inputValue.trim() : inputValue)}
80
+ onClear={onClear}
81
+ placeholder={`Filter by ${title}`}
82
+ aria-label={`${title ?? filterId} filter`}
83
+ data-ouia-component-id={`${ouiaId}-input`}
84
+ {...props}
85
+ />
86
+ </ToolbarFilter>
87
+ );
88
+ };
53
89
 
54
90
  export default DataViewTextFilter;
@@ -1,5 +1,6 @@
1
1
  import { FC, PropsWithChildren, useRef } from 'react';
2
2
  import { Button, Toolbar, ToolbarContent, ToolbarItem, ToolbarItemVariant, ToolbarProps } from '@patternfly/react-core';
3
+ import { createUseStyles } from 'react-jss';
3
4
 
4
5
  /** extends ToolbarProps */
5
6
  export interface DataViewToolbarProps extends Omit<PropsWithChildren<ToolbarProps>, 'ref'> {
@@ -21,7 +22,19 @@ export interface DataViewToolbarProps extends Omit<PropsWithChildren<ToolbarProp
21
22
  customLabelGroupContent?: React.ReactNode;
22
23
  }
23
24
 
25
+ const useStyles = createUseStyles({
26
+ dataViewToolbarPagination: {
27
+ flexBasis: '100%',
28
+ width: '100%'
29
+ },
30
+ dataViewToolbarPaginationWrapper: {
31
+ flexBasis: '100%',
32
+ width: '100%'
33
+ }
34
+ });
35
+
24
36
  export const DataViewToolbar: FC<DataViewToolbarProps> = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, actions, toggleGroup, pagination, filters, customLabelGroupContent, clearAllFilters, children, ...props }: DataViewToolbarProps) => {
37
+ const classes = useStyles();
25
38
  const defaultClearFilters = useRef(
26
39
  <ToolbarItem>
27
40
  <Button ouiaId={`${ouiaId}-clear-all-filters`} variant="link" onClick={clearAllFilters} isInline>
@@ -53,8 +66,10 @@ export const DataViewToolbar: FC<DataViewToolbarProps> = ({ className, ouiaId =
53
66
  </ToolbarItem>
54
67
  )}
55
68
  {pagination && (
56
- <ToolbarItem variant={ToolbarItemVariant.pagination} data-ouia-component-id={`${ouiaId}-pagination`}>
57
- {pagination}
69
+ <ToolbarItem variant={ToolbarItemVariant.pagination} data-ouia-component-id={`${ouiaId}-pagination`} className={classes.dataViewToolbarPagination}>
70
+ <div className={classes.dataViewToolbarPaginationWrapper}>
71
+ {pagination}
72
+ </div>
58
73
  </ToolbarItem>
59
74
  )}
60
75
  {children}
@@ -19,8 +19,295 @@ exports[`DataViewToolbar component should render correctly 1`] = `
19
19
  class="pf-v6-c-toolbar__content-section"
20
20
  >
21
21
  <div
22
- class="pf-v6-c-toolbar__item pf-m-pagination"
22
+ class="pf-v6-c-toolbar__item pf-m-pagination dataViewToolbarPagination-0-2-1"
23
23
  data-ouia-component-id="DataViewToolbar-pagination"
24
+ >
25
+ <div
26
+ class="dataViewToolbarPaginationWrapper-0-2-2"
27
+ >
28
+ <div
29
+ class="pf-v6-c-pagination"
30
+ data-ouia-component-id="OUIA-Generated-Pagination-top-1"
31
+ data-ouia-component-type="PF6/Pagination"
32
+ data-ouia-safe="true"
33
+ id="options-menu-top-pagination"
34
+ style="--pf-v6-c-pagination__nav-page-select--c-form-control--width-chars: 2;"
35
+ >
36
+ <div
37
+ class="pf-v6-c-pagination__total-items"
38
+ >
39
+ <b>
40
+ 1
41
+ -
42
+ 10
43
+ </b>
44
+
45
+ of
46
+
47
+ <b>
48
+ 0
49
+ </b>
50
+
51
+ </div>
52
+ <div
53
+ class="pf-v6-c-pagination__page-menu"
54
+ >
55
+ <button
56
+ aria-expanded="false"
57
+ aria-haspopup="listbox"
58
+ class="pf-v6-c-menu-toggle pf-m-plain pf-m-text"
59
+ data-ouia-component-id="OUIA-Generated-MenuToggle-plainText-1"
60
+ data-ouia-component-type="PF6/MenuToggle"
61
+ data-ouia-safe="true"
62
+ id="options-menu-top-toggle"
63
+ type="button"
64
+ >
65
+ <span
66
+ class="pf-v6-c-menu-toggle__text"
67
+ >
68
+ <b>
69
+ 1
70
+ -
71
+ 10
72
+ </b>
73
+
74
+ of
75
+
76
+ <b>
77
+ 0
78
+ </b>
79
+
80
+ </span>
81
+ <span
82
+ class="pf-v6-c-menu-toggle__controls"
83
+ >
84
+ <span
85
+ class="pf-v6-c-menu-toggle__toggle-icon"
86
+ >
87
+ <svg
88
+ aria-hidden="true"
89
+ class="pf-v6-svg"
90
+ fill="currentColor"
91
+ height="1em"
92
+ role="img"
93
+ viewBox="0 0 320 512"
94
+ width="1em"
95
+ >
96
+ <path
97
+ d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
98
+ />
99
+ </svg>
100
+ </span>
101
+ </span>
102
+ </button>
103
+ </div>
104
+ <nav
105
+ aria-label="Pagination"
106
+ class="pf-v6-c-pagination__nav"
107
+ >
108
+ <div
109
+ class="pf-v6-c-pagination__nav-control pf-m-first"
110
+ >
111
+ <button
112
+ aria-label="Go to first page"
113
+ class="pf-v6-c-button pf-m-plain"
114
+ data-action="first"
115
+ data-ouia-component-id="OUIA-Generated-Button-plain-1"
116
+ data-ouia-component-type="PF6/Button"
117
+ data-ouia-safe="true"
118
+ disabled=""
119
+ type="button"
120
+ >
121
+ <span
122
+ class="pf-v6-c-button__icon"
123
+ >
124
+ <svg
125
+ aria-hidden="true"
126
+ class="pf-v6-svg"
127
+ fill="currentColor"
128
+ height="1em"
129
+ role="img"
130
+ viewBox="0 0 448 512"
131
+ width="1em"
132
+ >
133
+ <path
134
+ d="M223.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L319.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L393.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34zm-192 34l136 136c9.4 9.4 24.6 9.4 33.9 0l22.6-22.6c9.4-9.4 9.4-24.6 0-33.9L127.9 256l96.4-96.4c9.4-9.4 9.4-24.6 0-33.9L201.7 103c-9.4-9.4-24.6-9.4-33.9 0l-136 136c-9.5 9.4-9.5 24.6-.1 34z"
135
+ />
136
+ </svg>
137
+ </span>
138
+ </button>
139
+ </div>
140
+ <div
141
+ class="pf-v6-c-pagination__nav-control"
142
+ >
143
+ <button
144
+ aria-label="Go to previous page"
145
+ class="pf-v6-c-button pf-m-plain"
146
+ data-action="previous"
147
+ data-ouia-component-id="OUIA-Generated-Button-plain-2"
148
+ data-ouia-component-type="PF6/Button"
149
+ data-ouia-safe="true"
150
+ disabled=""
151
+ type="button"
152
+ >
153
+ <span
154
+ class="pf-v6-c-button__icon"
155
+ >
156
+ <svg
157
+ aria-hidden="true"
158
+ class="pf-v6-svg"
159
+ fill="currentColor"
160
+ height="1em"
161
+ role="img"
162
+ viewBox="0 0 256 512"
163
+ width="1em"
164
+ >
165
+ <path
166
+ d="M31.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L127.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L201.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34z"
167
+ />
168
+ </svg>
169
+ </span>
170
+ </button>
171
+ </div>
172
+ <div
173
+ class="pf-v6-c-pagination__nav-page-select"
174
+ >
175
+ <span
176
+ class="pf-v6-c-form-control"
177
+ >
178
+ <input
179
+ aria-invalid="false"
180
+ aria-label="Current page"
181
+ data-ouia-component-id="OUIA-Generated-TextInputBase-1"
182
+ data-ouia-component-type="PF6/TextInput"
183
+ data-ouia-safe="true"
184
+ max="2"
185
+ min="1"
186
+ type="number"
187
+ value="1"
188
+ />
189
+ </span>
190
+ </div>
191
+ <div
192
+ class="pf-v6-c-pagination__nav-control"
193
+ >
194
+ <button
195
+ aria-label="Go to next page"
196
+ class="pf-v6-c-button pf-m-plain"
197
+ data-action="next"
198
+ data-ouia-component-id="OUIA-Generated-Button-plain-3"
199
+ data-ouia-component-type="PF6/Button"
200
+ data-ouia-safe="true"
201
+ type="button"
202
+ >
203
+ <span
204
+ class="pf-v6-c-button__icon"
205
+ >
206
+ <svg
207
+ aria-hidden="true"
208
+ class="pf-v6-svg"
209
+ fill="currentColor"
210
+ height="1em"
211
+ role="img"
212
+ viewBox="0 0 256 512"
213
+ width="1em"
214
+ >
215
+ <path
216
+ d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"
217
+ />
218
+ </svg>
219
+ </span>
220
+ </button>
221
+ </div>
222
+ <div
223
+ class="pf-v6-c-pagination__nav-control pf-m-last"
224
+ >
225
+ <button
226
+ aria-label="Go to last page"
227
+ class="pf-v6-c-button pf-m-plain"
228
+ data-action="last"
229
+ data-ouia-component-id="OUIA-Generated-Button-plain-4"
230
+ data-ouia-component-type="PF6/Button"
231
+ data-ouia-safe="true"
232
+ type="button"
233
+ >
234
+ <span
235
+ class="pf-v6-c-button__icon"
236
+ >
237
+ <svg
238
+ aria-hidden="true"
239
+ class="pf-v6-svg"
240
+ fill="currentColor"
241
+ height="1em"
242
+ role="img"
243
+ viewBox="0 0 448 512"
244
+ width="1em"
245
+ >
246
+ <path
247
+ d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34zm192-34l-136-136c-9.4-9.4-24.6-9.4-33.9 0l-22.6 22.6c-9.4 9.4-9.4 24.6 0 33.9l96.4 96.4-96.4 96.4c-9.4 9.4-9.4 24.6 0 33.9l22.6 22.6c9.4 9.4 24.6 9.4 33.9 0l136-136c9.4-9.2 9.4-24.4 0-33.8z"
248
+ />
249
+ </svg>
250
+ </span>
251
+ </button>
252
+ </div>
253
+ </nav>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ </div>
258
+ </div>
259
+ <div
260
+ class="pf-v6-c-toolbar__content pf-m-hidden"
261
+ hidden=""
262
+ >
263
+ <div
264
+ class="pf-v6-c-toolbar__group"
265
+ />
266
+ <div
267
+ class="pf-v6-c-toolbar__group pf-m-action-group-inline"
268
+ >
269
+ <div
270
+ class="pf-v6-c-toolbar__item"
271
+ >
272
+ <button
273
+ class="pf-v6-c-button pf-m-link pf-m-inline"
274
+ data-ouia-component-id="DataViewToolbar-clear-all-filters"
275
+ data-ouia-component-type="PF6/Button"
276
+ data-ouia-safe="true"
277
+ type="button"
278
+ >
279
+ <span
280
+ class="pf-v6-c-button__text"
281
+ >
282
+ Clear filters
283
+ </span>
284
+ </button>
285
+ </div>
286
+ </div>
287
+ </div>
288
+ </div>
289
+ </div>
290
+ </body>,
291
+ "container": <div>
292
+ <div
293
+ class="pf-v6-c-toolbar"
294
+ data-ouia-component-id="DataViewToolbar"
295
+ data-ouia-component-type="PF6/Toolbar"
296
+ data-ouia-safe="true"
297
+ id="pf-random-id-0"
298
+ >
299
+ <div
300
+ class="pf-v6-c-toolbar__content"
301
+ >
302
+ <div
303
+ class="pf-v6-c-toolbar__content-section"
304
+ >
305
+ <div
306
+ class="pf-v6-c-toolbar__item pf-m-pagination dataViewToolbarPagination-0-2-1"
307
+ data-ouia-component-id="DataViewToolbar-pagination"
308
+ >
309
+ <div
310
+ class="dataViewToolbarPaginationWrapper-0-2-2"
24
311
  >
25
312
  <div
26
313
  class="pf-v6-c-pagination"
@@ -252,285 +539,6 @@ exports[`DataViewToolbar component should render correctly 1`] = `
252
539
  </div>
253
540
  </div>
254
541
  </div>
255
- <div
256
- class="pf-v6-c-toolbar__content pf-m-hidden"
257
- hidden=""
258
- >
259
- <div
260
- class="pf-v6-c-toolbar__group"
261
- />
262
- <div
263
- class="pf-v6-c-toolbar__group pf-m-action-group-inline"
264
- >
265
- <div
266
- class="pf-v6-c-toolbar__item"
267
- >
268
- <button
269
- class="pf-v6-c-button pf-m-link pf-m-inline"
270
- data-ouia-component-id="DataViewToolbar-clear-all-filters"
271
- data-ouia-component-type="PF6/Button"
272
- data-ouia-safe="true"
273
- type="button"
274
- >
275
- <span
276
- class="pf-v6-c-button__text"
277
- >
278
- Clear filters
279
- </span>
280
- </button>
281
- </div>
282
- </div>
283
- </div>
284
- </div>
285
- </div>
286
- </body>,
287
- "container": <div>
288
- <div
289
- class="pf-v6-c-toolbar"
290
- data-ouia-component-id="DataViewToolbar"
291
- data-ouia-component-type="PF6/Toolbar"
292
- data-ouia-safe="true"
293
- id="pf-random-id-0"
294
- >
295
- <div
296
- class="pf-v6-c-toolbar__content"
297
- >
298
- <div
299
- class="pf-v6-c-toolbar__content-section"
300
- >
301
- <div
302
- class="pf-v6-c-toolbar__item pf-m-pagination"
303
- data-ouia-component-id="DataViewToolbar-pagination"
304
- >
305
- <div
306
- class="pf-v6-c-pagination"
307
- data-ouia-component-id="OUIA-Generated-Pagination-top-1"
308
- data-ouia-component-type="PF6/Pagination"
309
- data-ouia-safe="true"
310
- id="options-menu-top-pagination"
311
- style="--pf-v6-c-pagination__nav-page-select--c-form-control--width-chars: 2;"
312
- >
313
- <div
314
- class="pf-v6-c-pagination__total-items"
315
- >
316
- <b>
317
- 1
318
- -
319
- 10
320
- </b>
321
-
322
- of
323
-
324
- <b>
325
- 0
326
- </b>
327
-
328
- </div>
329
- <div
330
- class="pf-v6-c-pagination__page-menu"
331
- >
332
- <button
333
- aria-expanded="false"
334
- aria-haspopup="listbox"
335
- class="pf-v6-c-menu-toggle pf-m-plain pf-m-text"
336
- data-ouia-component-id="OUIA-Generated-MenuToggle-plainText-1"
337
- data-ouia-component-type="PF6/MenuToggle"
338
- data-ouia-safe="true"
339
- id="options-menu-top-toggle"
340
- type="button"
341
- >
342
- <span
343
- class="pf-v6-c-menu-toggle__text"
344
- >
345
- <b>
346
- 1
347
- -
348
- 10
349
- </b>
350
-
351
- of
352
-
353
- <b>
354
- 0
355
- </b>
356
-
357
- </span>
358
- <span
359
- class="pf-v6-c-menu-toggle__controls"
360
- >
361
- <span
362
- class="pf-v6-c-menu-toggle__toggle-icon"
363
- >
364
- <svg
365
- aria-hidden="true"
366
- class="pf-v6-svg"
367
- fill="currentColor"
368
- height="1em"
369
- role="img"
370
- viewBox="0 0 320 512"
371
- width="1em"
372
- >
373
- <path
374
- d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
375
- />
376
- </svg>
377
- </span>
378
- </span>
379
- </button>
380
- </div>
381
- <nav
382
- aria-label="Pagination"
383
- class="pf-v6-c-pagination__nav"
384
- >
385
- <div
386
- class="pf-v6-c-pagination__nav-control pf-m-first"
387
- >
388
- <button
389
- aria-label="Go to first page"
390
- class="pf-v6-c-button pf-m-plain"
391
- data-action="first"
392
- data-ouia-component-id="OUIA-Generated-Button-plain-1"
393
- data-ouia-component-type="PF6/Button"
394
- data-ouia-safe="true"
395
- disabled=""
396
- type="button"
397
- >
398
- <span
399
- class="pf-v6-c-button__icon"
400
- >
401
- <svg
402
- aria-hidden="true"
403
- class="pf-v6-svg"
404
- fill="currentColor"
405
- height="1em"
406
- role="img"
407
- viewBox="0 0 448 512"
408
- width="1em"
409
- >
410
- <path
411
- d="M223.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L319.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L393.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34zm-192 34l136 136c9.4 9.4 24.6 9.4 33.9 0l22.6-22.6c9.4-9.4 9.4-24.6 0-33.9L127.9 256l96.4-96.4c9.4-9.4 9.4-24.6 0-33.9L201.7 103c-9.4-9.4-24.6-9.4-33.9 0l-136 136c-9.5 9.4-9.5 24.6-.1 34z"
412
- />
413
- </svg>
414
- </span>
415
- </button>
416
- </div>
417
- <div
418
- class="pf-v6-c-pagination__nav-control"
419
- >
420
- <button
421
- aria-label="Go to previous page"
422
- class="pf-v6-c-button pf-m-plain"
423
- data-action="previous"
424
- data-ouia-component-id="OUIA-Generated-Button-plain-2"
425
- data-ouia-component-type="PF6/Button"
426
- data-ouia-safe="true"
427
- disabled=""
428
- type="button"
429
- >
430
- <span
431
- class="pf-v6-c-button__icon"
432
- >
433
- <svg
434
- aria-hidden="true"
435
- class="pf-v6-svg"
436
- fill="currentColor"
437
- height="1em"
438
- role="img"
439
- viewBox="0 0 256 512"
440
- width="1em"
441
- >
442
- <path
443
- d="M31.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L127.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L201.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34z"
444
- />
445
- </svg>
446
- </span>
447
- </button>
448
- </div>
449
- <div
450
- class="pf-v6-c-pagination__nav-page-select"
451
- >
452
- <span
453
- class="pf-v6-c-form-control"
454
- >
455
- <input
456
- aria-invalid="false"
457
- aria-label="Current page"
458
- data-ouia-component-id="OUIA-Generated-TextInputBase-1"
459
- data-ouia-component-type="PF6/TextInput"
460
- data-ouia-safe="true"
461
- max="2"
462
- min="1"
463
- type="number"
464
- value="1"
465
- />
466
- </span>
467
- </div>
468
- <div
469
- class="pf-v6-c-pagination__nav-control"
470
- >
471
- <button
472
- aria-label="Go to next page"
473
- class="pf-v6-c-button pf-m-plain"
474
- data-action="next"
475
- data-ouia-component-id="OUIA-Generated-Button-plain-3"
476
- data-ouia-component-type="PF6/Button"
477
- data-ouia-safe="true"
478
- type="button"
479
- >
480
- <span
481
- class="pf-v6-c-button__icon"
482
- >
483
- <svg
484
- aria-hidden="true"
485
- class="pf-v6-svg"
486
- fill="currentColor"
487
- height="1em"
488
- role="img"
489
- viewBox="0 0 256 512"
490
- width="1em"
491
- >
492
- <path
493
- d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"
494
- />
495
- </svg>
496
- </span>
497
- </button>
498
- </div>
499
- <div
500
- class="pf-v6-c-pagination__nav-control pf-m-last"
501
- >
502
- <button
503
- aria-label="Go to last page"
504
- class="pf-v6-c-button pf-m-plain"
505
- data-action="last"
506
- data-ouia-component-id="OUIA-Generated-Button-plain-4"
507
- data-ouia-component-type="PF6/Button"
508
- data-ouia-safe="true"
509
- type="button"
510
- >
511
- <span
512
- class="pf-v6-c-button__icon"
513
- >
514
- <svg
515
- aria-hidden="true"
516
- class="pf-v6-svg"
517
- fill="currentColor"
518
- height="1em"
519
- role="img"
520
- viewBox="0 0 448 512"
521
- width="1em"
522
- >
523
- <path
524
- d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34zm192-34l-136-136c-9.4-9.4-24.6-9.4-33.9 0l-22.6 22.6c-9.4 9.4-9.4 24.6 0 33.9l96.4 96.4-96.4 96.4c-9.4 9.4-9.4 24.6 0 33.9l22.6 22.6c9.4 9.4 24.6 9.4 33.9 0l136-136c9.4-9.2 9.4-24.4 0-33.8z"
525
- />
526
- </svg>
527
- </span>
528
- </button>
529
- </div>
530
- </nav>
531
- </div>
532
- </div>
533
- </div>
534
542
  </div>
535
543
  <div
536
544
  class="pf-v6-c-toolbar__content pf-m-hidden"