@patternfly/react-data-view 5.4.1 → 5.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/dist/cjs/DataViewFilters/DataViewFilters.d.ts +19 -0
- package/dist/cjs/DataViewFilters/DataViewFilters.js +70 -0
- package/dist/cjs/DataViewFilters/DataViewFilters.test.d.ts +1 -0
- package/dist/cjs/DataViewFilters/DataViewFilters.test.js +19 -0
- package/dist/cjs/DataViewFilters/index.d.ts +2 -0
- package/dist/cjs/DataViewFilters/index.js +23 -0
- package/dist/cjs/DataViewTable/DataViewTable.d.ts +8 -0
- package/dist/cjs/DataViewTableBasic/DataViewTableBasic.d.ts +1 -0
- package/dist/cjs/DataViewTableHead/DataViewTableHead.d.ts +1 -0
- package/dist/cjs/DataViewTableTree/DataViewTableTree.d.ts +1 -0
- package/dist/cjs/DataViewTextFilter/DataViewTextFilter.d.ts +21 -0
- package/dist/cjs/DataViewTextFilter/DataViewTextFilter.js +26 -0
- package/dist/cjs/DataViewTextFilter/DataViewTextFilter.test.d.ts +1 -0
- package/dist/cjs/DataViewTextFilter/DataViewTextFilter.test.js +22 -0
- package/dist/cjs/DataViewTextFilter/index.d.ts +2 -0
- package/dist/cjs/DataViewTextFilter/index.js +23 -0
- package/dist/cjs/DataViewToolbar/DataViewToolbar.d.ts +10 -4
- package/dist/cjs/DataViewToolbar/DataViewToolbar.js +29 -6
- package/dist/cjs/Hooks/filters.d.ts +14 -0
- package/dist/cjs/Hooks/filters.js +70 -0
- package/dist/cjs/Hooks/filters.test.d.ts +1 -0
- package/dist/cjs/Hooks/filters.test.js +50 -0
- package/dist/cjs/Hooks/index.d.ts +1 -0
- package/dist/cjs/Hooks/index.js +1 -0
- package/dist/cjs/Hooks/pagination.d.ts +1 -0
- package/dist/cjs/Hooks/selection.d.ts +1 -1
- package/dist/cjs/Hooks/selection.js +4 -2
- package/dist/cjs/InternalContext/InternalContext.d.ts +1 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +4 -1
- package/dist/dynamic/DataViewFilters/package.json +1 -0
- package/dist/dynamic/DataViewTextFilter/package.json +1 -0
- package/dist/esm/DataViewFilters/DataViewFilters.d.ts +19 -0
- package/dist/esm/DataViewFilters/DataViewFilters.js +43 -0
- package/dist/esm/DataViewFilters/DataViewFilters.test.d.ts +1 -0
- package/dist/esm/DataViewFilters/DataViewFilters.test.js +14 -0
- package/dist/esm/DataViewFilters/index.d.ts +2 -0
- package/dist/esm/DataViewFilters/index.js +2 -0
- package/dist/esm/DataViewTable/DataViewTable.d.ts +8 -0
- package/dist/esm/DataViewTableBasic/DataViewTableBasic.d.ts +1 -0
- package/dist/esm/DataViewTableHead/DataViewTableHead.d.ts +1 -0
- package/dist/esm/DataViewTableTree/DataViewTableTree.d.ts +1 -0
- package/dist/esm/DataViewTextFilter/DataViewTextFilter.d.ts +21 -0
- package/dist/esm/DataViewTextFilter/DataViewTextFilter.js +19 -0
- package/dist/esm/DataViewTextFilter/DataViewTextFilter.test.d.ts +1 -0
- package/dist/esm/DataViewTextFilter/DataViewTextFilter.test.js +17 -0
- package/dist/esm/DataViewTextFilter/index.d.ts +2 -0
- package/dist/esm/DataViewTextFilter/index.js +2 -0
- package/dist/esm/DataViewToolbar/DataViewToolbar.d.ts +10 -4
- package/dist/esm/DataViewToolbar/DataViewToolbar.js +7 -4
- package/dist/esm/Hooks/filters.d.ts +14 -0
- package/dist/esm/Hooks/filters.js +66 -0
- package/dist/esm/Hooks/filters.test.d.ts +1 -0
- package/dist/esm/Hooks/filters.test.js +48 -0
- package/dist/esm/Hooks/index.d.ts +1 -0
- package/dist/esm/Hooks/index.js +1 -0
- package/dist/esm/Hooks/pagination.d.ts +1 -0
- package/dist/esm/Hooks/selection.d.ts +1 -1
- package/dist/esm/Hooks/selection.js +4 -2
- package/dist/esm/InternalContext/InternalContext.d.ts +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/package.json +1 -1
- package/patternfly-docs/content/extensions/data-view/examples/Components/Components.md +2 -2
- package/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx +92 -0
- package/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md +36 -2
- package/src/DataViewFilters/DataViewFilters.test.tsx +21 -0
- package/src/DataViewFilters/DataViewFilters.tsx +125 -0
- package/src/DataViewFilters/__snapshots__/DataViewFilters.test.tsx.snap +182 -0
- package/src/DataViewFilters/index.tsx +2 -0
- package/src/DataViewTable/DataViewTable.tsx +23 -3
- package/src/DataViewTableBasic/DataViewTableBasic.tsx +1 -0
- package/src/DataViewTableHead/DataViewTableHead.tsx +1 -0
- package/src/DataViewTableTree/DataViewTableTree.tsx +1 -0
- package/src/DataViewTextFilter/DataViewTextFilter.test.tsx +24 -0
- package/src/DataViewTextFilter/DataViewTextFilter.tsx +53 -0
- package/src/DataViewTextFilter/__snapshots__/DataViewTextFilter.test.tsx.snap +196 -0
- package/src/DataViewTextFilter/index.ts +2 -0
- package/src/DataViewToolbar/DataViewToolbar.tsx +47 -28
- package/src/DataViewToolbar/__snapshots__/DataViewToolbar.test.tsx.snap +28 -0
- package/src/Hooks/filters.test.tsx +62 -0
- package/src/Hooks/filters.ts +96 -0
- package/src/Hooks/index.ts +1 -0
- package/src/Hooks/pagination.ts +1 -0
- package/src/Hooks/selection.ts +3 -2
- package/src/InternalContext/InternalContext.tsx +1 -0
- package/src/index.ts +3 -0
package/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
CHANGED
|
@@ -11,15 +11,18 @@ source: react
|
|
|
11
11
|
# If you use typescript, the name of the interface to display props for
|
|
12
12
|
# These are found through the sourceProps function provided in patternfly-docs.source.js
|
|
13
13
|
sortValue: 3
|
|
14
|
+
propComponents: ['DataViewFilters', 'DataViewTextFilter']
|
|
14
15
|
sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
|
|
15
16
|
---
|
|
16
17
|
import { useMemo } from 'react';
|
|
17
|
-
import {
|
|
18
|
+
import { BrowserRouter, useSearchParams } from 'react-router-dom';
|
|
19
|
+
import { useDataViewPagination, useDataViewSelection, useDataViewFilters } from '@patternfly/react-data-view/dist/dynamic/Hooks';
|
|
18
20
|
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
|
|
19
21
|
import { BulkSelect, BulkSelectValue } from '@patternfly/react-component-groups/dist/dynamic/BulkSelect';
|
|
20
22
|
import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
|
|
21
23
|
import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
|
|
22
|
-
import {
|
|
24
|
+
import { DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters';
|
|
25
|
+
import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
|
|
23
26
|
|
|
24
27
|
This is a list of functionality you can use to manage data displayed in the **data view**.
|
|
25
28
|
|
|
@@ -84,3 +87,34 @@ The `useDataViewSelection` hook manages the selection state of the data view.
|
|
|
84
87
|
```js file="./SelectionExample.tsx"
|
|
85
88
|
|
|
86
89
|
```
|
|
90
|
+
|
|
91
|
+
# Filters
|
|
92
|
+
Enables filtering of data records in the data view and displays the applied filter chips.
|
|
93
|
+
|
|
94
|
+
### Toolbar usage
|
|
95
|
+
The data view toolbar can include a set of filters by passing a React node to the `filters` property. You can use predefined components `DataViewFilters` and `DataViewTextFilter` to customize and handle filtering directly in the toolbar. The `DataViewFilters` is a wrapper allowing conditional filtering using multiple attributes. If you need just a single filter, you can use `DataViewTextFilter` or a different filter component alone. Props of these filter components are listed at the bottom of this page.
|
|
96
|
+
|
|
97
|
+
You can decide between passing `value` and `onChange` event to every filter separately or pass `values` and `onChange` to the `DataViewFilters` wrapper which make them available to its children. Props directly passed to child filters have a higher priority than the "inherited" ones.
|
|
98
|
+
|
|
99
|
+
### Filters state
|
|
100
|
+
|
|
101
|
+
The `useDataViewFilters` hook manages the filter state of the data view. It allows you to define default filter values, synchronize filter state with URL parameters, and handle filter changes efficiently.
|
|
102
|
+
|
|
103
|
+
**Initial values:**
|
|
104
|
+
- `initialFilters` object with default filter values
|
|
105
|
+
- optional `searchParams` object for managing URL-based filter state
|
|
106
|
+
- optional `setSearchParams` function to update the URL when filters are modified
|
|
107
|
+
|
|
108
|
+
The `useDataViewFilters` hook works well with the React Router library to support URL-based filtering. Alternatively, you can manage filter state in the URL using `URLSearchParams` and `window.history.pushState` APIs, or other routing libraries. If no URL parameters are provided, the filter state is managed internally.
|
|
109
|
+
|
|
110
|
+
**Return values:**
|
|
111
|
+
- `filters` object representing the current filter values
|
|
112
|
+
- `onSetFilters` function to update the filter state
|
|
113
|
+
- `clearAllFilters` function to reset all filters to their initial values
|
|
114
|
+
|
|
115
|
+
### Filtering example
|
|
116
|
+
This example demonstrates the setup and usage of filters within the data view. It includes text filters for different attributes, the ability to clear all filters, and persistence of filter state in the URL.
|
|
117
|
+
|
|
118
|
+
```js file="./FiltersExample.tsx"
|
|
119
|
+
|
|
120
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import DataViewFilters from './DataViewFilters';
|
|
4
|
+
import DataViewToolbar from '../DataViewToolbar';
|
|
5
|
+
import DataViewTextFilter from '../DataViewTextFilter';
|
|
6
|
+
|
|
7
|
+
describe('DataViewFilters component', () => {
|
|
8
|
+
const mockOnChange = jest.fn();
|
|
9
|
+
|
|
10
|
+
it('should render correctly', () => {
|
|
11
|
+
const { container } = render(<DataViewToolbar
|
|
12
|
+
filters={
|
|
13
|
+
<DataViewFilters onChange={mockOnChange} values={{}}>
|
|
14
|
+
<DataViewTextFilter filterId="one" title="One" />
|
|
15
|
+
<DataViewTextFilter filterId="two" title="Two" />
|
|
16
|
+
</DataViewFilters>
|
|
17
|
+
}
|
|
18
|
+
/>);
|
|
19
|
+
expect(container).toMatchSnapshot();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React, { useMemo, useState, useRef, useEffect, ReactElement } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Menu, MenuContent, MenuItem, MenuList, MenuToggle, Popper, ToolbarGroup, ToolbarToggleGroup, ToolbarToggleGroupProps,
|
|
4
|
+
} from '@patternfly/react-core';
|
|
5
|
+
import { FilterIcon } from '@patternfly/react-icons';
|
|
6
|
+
|
|
7
|
+
// helper interface to generate attribute menu
|
|
8
|
+
interface DataViewFilterIdentifiers {
|
|
9
|
+
filterId: string;
|
|
10
|
+
title: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** extends ToolbarToggleGroupProps */
|
|
14
|
+
export interface DataViewFiltersProps<T extends object> extends Omit<ToolbarToggleGroupProps, 'toggleIcon' | 'breakpoint' | 'onChange'> {
|
|
15
|
+
/** Content rendered inside the data view */
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
/** Optional onChange callback shared across filters */
|
|
18
|
+
onChange?: (key: string, newValues: Partial<T>) => void;
|
|
19
|
+
/** Optional values shared across filters */
|
|
20
|
+
values?: T;
|
|
21
|
+
/** Icon for the toolbar toggle group */
|
|
22
|
+
toggleIcon?: ToolbarToggleGroupProps['toggleIcon'];
|
|
23
|
+
/** Breakpoint for the toolbar toggle group */
|
|
24
|
+
breakpoint?: ToolbarToggleGroupProps['breakpoint'];
|
|
25
|
+
/** Custom OUIA ID */
|
|
26
|
+
ouiaId?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
export const DataViewFilters = <T extends object>({
|
|
31
|
+
children,
|
|
32
|
+
ouiaId = 'DataViewFilters',
|
|
33
|
+
toggleIcon = <FilterIcon />,
|
|
34
|
+
breakpoint = 'xl',
|
|
35
|
+
onChange,
|
|
36
|
+
values,
|
|
37
|
+
...props
|
|
38
|
+
}: DataViewFiltersProps<T>) => {
|
|
39
|
+
const [ activeAttributeMenu, setActiveAttributeMenu ] = useState<string>('');
|
|
40
|
+
const [ isAttributeMenuOpen, setIsAttributeMenuOpen ] = useState(false);
|
|
41
|
+
const attributeToggleRef = useRef<HTMLButtonElement>(null);
|
|
42
|
+
const attributeMenuRef = useRef<HTMLDivElement>(null);
|
|
43
|
+
const attributeContainerRef = useRef<HTMLDivElement>(null);
|
|
44
|
+
|
|
45
|
+
const childrenHash = useMemo(() => JSON.stringify(
|
|
46
|
+
React.Children.map(children, (child) =>
|
|
47
|
+
React.isValidElement(child) ? { type: child.type, key: child.key, props: child.props } : child
|
|
48
|
+
)
|
|
49
|
+
), [ children ]);
|
|
50
|
+
|
|
51
|
+
const filterItems: DataViewFilterIdentifiers[] = useMemo(() => React.Children.toArray(children)
|
|
52
|
+
.map(child =>
|
|
53
|
+
React.isValidElement(child) ? { filterId: String(child.props.filterId), title: String(child.props.title) } : undefined
|
|
54
|
+
).filter((item): item is DataViewFilterIdentifiers => !!item), [ childrenHash ]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
55
|
+
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
filterItems.length > 0 && setActiveAttributeMenu(filterItems[0].title);
|
|
58
|
+
}, [ filterItems ]);
|
|
59
|
+
|
|
60
|
+
const attributeToggle = (
|
|
61
|
+
<MenuToggle
|
|
62
|
+
ref={attributeToggleRef}
|
|
63
|
+
onClick={() => setIsAttributeMenuOpen(!isAttributeMenuOpen)}
|
|
64
|
+
isExpanded={isAttributeMenuOpen}
|
|
65
|
+
icon={toggleIcon}
|
|
66
|
+
>
|
|
67
|
+
{activeAttributeMenu}
|
|
68
|
+
</MenuToggle>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const attributeMenu = (
|
|
72
|
+
<Menu
|
|
73
|
+
ref={attributeMenuRef}
|
|
74
|
+
onSelect={(_ev, itemId) => {
|
|
75
|
+
const selectedItem = filterItems.find(item => item.filterId === itemId);
|
|
76
|
+
selectedItem && setActiveAttributeMenu(selectedItem.title);
|
|
77
|
+
setIsAttributeMenuOpen(false);
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
<MenuContent>
|
|
81
|
+
<MenuList>
|
|
82
|
+
{filterItems.map(item => (
|
|
83
|
+
<MenuItem key={item.filterId} itemId={item.filterId}>
|
|
84
|
+
{item.title}
|
|
85
|
+
</MenuItem>
|
|
86
|
+
))}
|
|
87
|
+
</MenuList>
|
|
88
|
+
</MenuContent>
|
|
89
|
+
</Menu>
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<ToolbarToggleGroup data-ouia-component-id={ouiaId} toggleIcon={toggleIcon} breakpoint={breakpoint} {...props}>
|
|
94
|
+
<ToolbarGroup variant="filter-group">
|
|
95
|
+
<div ref={attributeContainerRef}>
|
|
96
|
+
<Popper
|
|
97
|
+
trigger={attributeToggle}
|
|
98
|
+
triggerRef={attributeToggleRef}
|
|
99
|
+
popper={attributeMenu}
|
|
100
|
+
popperRef={attributeMenuRef}
|
|
101
|
+
appendTo={attributeContainerRef.current || undefined}
|
|
102
|
+
isVisible={isAttributeMenuOpen}
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
{React.Children.map(children, (child) => (
|
|
106
|
+
React.isValidElement(child) ? (
|
|
107
|
+
React.cloneElement(child as ReactElement<{
|
|
108
|
+
showToolbarItem: boolean;
|
|
109
|
+
onChange: (_e: unknown, values: unknown) => void;
|
|
110
|
+
value: unknown;
|
|
111
|
+
}>, {
|
|
112
|
+
showToolbarItem: activeAttributeMenu === child.props.title,
|
|
113
|
+
onChange: (event, value) => onChange?.(event, { [child.props.filterId]: value } as Partial<T>),
|
|
114
|
+
value: values?.[child.props.filterId],
|
|
115
|
+
...child.props
|
|
116
|
+
})
|
|
117
|
+
) : child
|
|
118
|
+
))}
|
|
119
|
+
|
|
120
|
+
</ToolbarGroup>
|
|
121
|
+
</ToolbarToggleGroup>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export default DataViewFilters;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`DataViewFilters component should render correctly 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
class="pf-v5-c-toolbar"
|
|
7
|
+
data-ouia-component-id="DataViewToolbar"
|
|
8
|
+
data-ouia-component-type="PF5/Toolbar"
|
|
9
|
+
data-ouia-safe="true"
|
|
10
|
+
id="pf-random-id-0"
|
|
11
|
+
>
|
|
12
|
+
<div
|
|
13
|
+
class="pf-v5-c-toolbar__content"
|
|
14
|
+
>
|
|
15
|
+
<div
|
|
16
|
+
class="pf-v5-c-toolbar__content-section"
|
|
17
|
+
>
|
|
18
|
+
<div
|
|
19
|
+
class="pf-v5-c-toolbar__item pf-m-search-filter"
|
|
20
|
+
>
|
|
21
|
+
<div
|
|
22
|
+
class="pf-v5-c-toolbar__group pf-m-toggle-group pf-m-show-on-xl"
|
|
23
|
+
data-ouia-component-id="DataViewFilters"
|
|
24
|
+
>
|
|
25
|
+
<div
|
|
26
|
+
class="pf-v5-c-toolbar__toggle"
|
|
27
|
+
>
|
|
28
|
+
<button
|
|
29
|
+
aria-disabled="false"
|
|
30
|
+
aria-haspopup="false"
|
|
31
|
+
aria-label="Show Filters"
|
|
32
|
+
class="pf-v5-c-button pf-m-plain"
|
|
33
|
+
data-ouia-component-id="OUIA-Generated-Button-plain-1"
|
|
34
|
+
data-ouia-component-type="PF5/Button"
|
|
35
|
+
data-ouia-safe="true"
|
|
36
|
+
type="button"
|
|
37
|
+
>
|
|
38
|
+
<svg
|
|
39
|
+
aria-hidden="true"
|
|
40
|
+
class="pf-v5-svg"
|
|
41
|
+
fill="currentColor"
|
|
42
|
+
height="1em"
|
|
43
|
+
role="img"
|
|
44
|
+
viewBox="0 0 512 512"
|
|
45
|
+
width="1em"
|
|
46
|
+
>
|
|
47
|
+
<path
|
|
48
|
+
d="M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z"
|
|
49
|
+
/>
|
|
50
|
+
</svg>
|
|
51
|
+
</button>
|
|
52
|
+
</div>
|
|
53
|
+
<div
|
|
54
|
+
class="pf-v5-c-toolbar__group pf-m-filter-group"
|
|
55
|
+
>
|
|
56
|
+
<div>
|
|
57
|
+
<button
|
|
58
|
+
aria-expanded="false"
|
|
59
|
+
class="pf-v5-c-menu-toggle"
|
|
60
|
+
data-ouia-component-id="OUIA-Generated-MenuToggle-1"
|
|
61
|
+
data-ouia-component-type="PF5/MenuToggle"
|
|
62
|
+
data-ouia-safe="true"
|
|
63
|
+
type="button"
|
|
64
|
+
>
|
|
65
|
+
<span
|
|
66
|
+
class="pf-v5-c-menu-toggle__icon"
|
|
67
|
+
>
|
|
68
|
+
<svg
|
|
69
|
+
aria-hidden="true"
|
|
70
|
+
class="pf-v5-svg"
|
|
71
|
+
fill="currentColor"
|
|
72
|
+
height="1em"
|
|
73
|
+
role="img"
|
|
74
|
+
viewBox="0 0 512 512"
|
|
75
|
+
width="1em"
|
|
76
|
+
>
|
|
77
|
+
<path
|
|
78
|
+
d="M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z"
|
|
79
|
+
/>
|
|
80
|
+
</svg>
|
|
81
|
+
</span>
|
|
82
|
+
<span
|
|
83
|
+
class="pf-v5-c-menu-toggle__text"
|
|
84
|
+
>
|
|
85
|
+
One
|
|
86
|
+
</span>
|
|
87
|
+
<span
|
|
88
|
+
class="pf-v5-c-menu-toggle__controls"
|
|
89
|
+
>
|
|
90
|
+
<span
|
|
91
|
+
class="pf-v5-c-menu-toggle__toggle-icon"
|
|
92
|
+
>
|
|
93
|
+
<svg
|
|
94
|
+
aria-hidden="true"
|
|
95
|
+
class="pf-v5-svg"
|
|
96
|
+
fill="currentColor"
|
|
97
|
+
height="1em"
|
|
98
|
+
role="img"
|
|
99
|
+
viewBox="0 0 320 512"
|
|
100
|
+
width="1em"
|
|
101
|
+
>
|
|
102
|
+
<path
|
|
103
|
+
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"
|
|
104
|
+
/>
|
|
105
|
+
</svg>
|
|
106
|
+
</span>
|
|
107
|
+
</span>
|
|
108
|
+
</button>
|
|
109
|
+
</div>
|
|
110
|
+
<div
|
|
111
|
+
class="pf-v5-c-toolbar__item"
|
|
112
|
+
data-ouia-component-id="DataViewTextFilter"
|
|
113
|
+
>
|
|
114
|
+
<div
|
|
115
|
+
class="pf-v5-c-text-input-group"
|
|
116
|
+
data-ouia-component-id="DataViewTextFilter-input"
|
|
117
|
+
>
|
|
118
|
+
<div
|
|
119
|
+
class="pf-v5-c-text-input-group__main pf-m-icon"
|
|
120
|
+
>
|
|
121
|
+
<span
|
|
122
|
+
class="pf-v5-c-text-input-group__text"
|
|
123
|
+
>
|
|
124
|
+
<span
|
|
125
|
+
class="pf-v5-c-text-input-group__icon"
|
|
126
|
+
>
|
|
127
|
+
<svg
|
|
128
|
+
aria-hidden="true"
|
|
129
|
+
class="pf-v5-svg"
|
|
130
|
+
fill="currentColor"
|
|
131
|
+
height="1em"
|
|
132
|
+
role="img"
|
|
133
|
+
viewBox="0 0 512 512"
|
|
134
|
+
width="1em"
|
|
135
|
+
>
|
|
136
|
+
<path
|
|
137
|
+
d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"
|
|
138
|
+
/>
|
|
139
|
+
</svg>
|
|
140
|
+
</span>
|
|
141
|
+
<input
|
|
142
|
+
aria-label="One filter"
|
|
143
|
+
class="pf-v5-c-text-input-group__text-input"
|
|
144
|
+
id="one"
|
|
145
|
+
placeholder="Filter by One"
|
|
146
|
+
type="text"
|
|
147
|
+
value=""
|
|
148
|
+
/>
|
|
149
|
+
</span>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
<div
|
|
159
|
+
class="pf-v5-c-toolbar__content pf-m-hidden"
|
|
160
|
+
hidden=""
|
|
161
|
+
>
|
|
162
|
+
<div
|
|
163
|
+
class="pf-v5-c-toolbar__group"
|
|
164
|
+
/>
|
|
165
|
+
<div
|
|
166
|
+
class="pf-v5-c-toolbar__item"
|
|
167
|
+
>
|
|
168
|
+
<button
|
|
169
|
+
aria-disabled="false"
|
|
170
|
+
class="pf-v5-c-button pf-m-link pf-m-inline"
|
|
171
|
+
data-ouia-component-id="DataViewToolbar-clear-all-filters"
|
|
172
|
+
data-ouia-component-type="PF5/Button"
|
|
173
|
+
data-ouia-safe="true"
|
|
174
|
+
type="button"
|
|
175
|
+
>
|
|
176
|
+
Clear filters
|
|
177
|
+
</button>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
`;
|
|
@@ -8,18 +8,38 @@ import { DataViewTableTree, DataViewTableTreeProps } from '../DataViewTableTree'
|
|
|
8
8
|
import { DataViewTableBasic, DataViewTableBasicProps } from '../DataViewTableBasic';
|
|
9
9
|
|
|
10
10
|
// Table head typings
|
|
11
|
-
export type DataViewTh = ReactNode | {
|
|
11
|
+
export type DataViewTh = ReactNode | {
|
|
12
|
+
/** Table head cell node */
|
|
13
|
+
cell: ReactNode;
|
|
14
|
+
/** Props passed to Th */
|
|
15
|
+
props?: ThProps
|
|
16
|
+
};
|
|
12
17
|
export const isDataViewThObject = (value: DataViewTh): value is { cell: ReactNode; props?: ThProps } => value != null && typeof value === 'object' && 'cell' in value;
|
|
13
18
|
|
|
14
19
|
// Basic table typings
|
|
15
|
-
export interface DataViewTrObject {
|
|
16
|
-
|
|
20
|
+
export interface DataViewTrObject {
|
|
21
|
+
/** Array of rows */
|
|
22
|
+
row: DataViewTd[],
|
|
23
|
+
/** Unique identifier of a row */
|
|
24
|
+
id?: string,
|
|
25
|
+
/** Props passed to Tr */
|
|
26
|
+
props?: TrProps
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type DataViewTd = ReactNode | {
|
|
30
|
+
/** Table body cell node */
|
|
31
|
+
cell: ReactNode;
|
|
32
|
+
/** Props passed to Td */
|
|
33
|
+
props?: TdProps
|
|
34
|
+
};
|
|
35
|
+
|
|
17
36
|
export type DataViewTr = DataViewTd[] | DataViewTrObject;
|
|
18
37
|
|
|
19
38
|
export const isDataViewTdObject = (value: DataViewTd): value is { cell: ReactNode; props?: TdProps } => value != null && typeof value === 'object' && 'cell' in value;
|
|
20
39
|
export const isDataViewTrObject = (value: DataViewTr): value is { row: DataViewTd[], id?: string } => value != null && typeof value === 'object' && 'row' in value;
|
|
21
40
|
|
|
22
41
|
// Tree table typings
|
|
42
|
+
/** extends DataViewTrObject */
|
|
23
43
|
export interface DataViewTrTree extends DataViewTrObject { id: string, children?: DataViewTrTree[] }
|
|
24
44
|
|
|
25
45
|
export type DataViewTableProps =
|
|
@@ -11,6 +11,7 @@ import { DataViewTableHead } from '../DataViewTableHead';
|
|
|
11
11
|
import { DataViewTh, DataViewTr, isDataViewTdObject, isDataViewTrObject } from '../DataViewTable';
|
|
12
12
|
import { DataViewState } from '../DataView/DataView';
|
|
13
13
|
|
|
14
|
+
/** extends TableProps */
|
|
14
15
|
export interface DataViewTableBasicProps extends Omit<TableProps, 'onSelect' | 'rows'> {
|
|
15
16
|
/** Columns definition */
|
|
16
17
|
columns: DataViewTh[];
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import { useInternalContext } from '../InternalContext';
|
|
9
9
|
import { DataViewTh, isDataViewThObject } from '../DataViewTable';
|
|
10
10
|
|
|
11
|
+
/** extends TheadProps */
|
|
11
12
|
export interface DataViewTableHeadProps extends TheadProps {
|
|
12
13
|
/** Indicates whether table is a tree */
|
|
13
14
|
isTreeTable?: boolean;
|
|
@@ -30,6 +30,7 @@ const isNodeChecked = (node: DataViewTrTree, isSelected: (node: DataViewTrTree)
|
|
|
30
30
|
return allSelected;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
/** extends TableProps */
|
|
33
34
|
export interface DataViewTableTreeProps extends Omit<TableProps, 'onSelect' | 'rows'> {
|
|
34
35
|
/** Columns definition */
|
|
35
36
|
columns: DataViewTh[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import DataViewTextFilter, { DataViewTextFilterProps } from './DataViewTextFilter';
|
|
4
|
+
import DataViewToolbar from '../DataViewToolbar';
|
|
5
|
+
|
|
6
|
+
describe('DataViewTextFilter component', () => {
|
|
7
|
+
const mockOnChange = jest.fn();
|
|
8
|
+
|
|
9
|
+
const defaultProps: DataViewTextFilterProps = {
|
|
10
|
+
filterId: 'test-filter',
|
|
11
|
+
title: 'Test Filter',
|
|
12
|
+
value: 'initial value',
|
|
13
|
+
onChange: mockOnChange,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
it('should render correctly', () => {
|
|
17
|
+
const { container } = render(<DataViewToolbar
|
|
18
|
+
filters={
|
|
19
|
+
<DataViewTextFilter {...defaultProps} />
|
|
20
|
+
}
|
|
21
|
+
/>);
|
|
22
|
+
expect(container).toMatchSnapshot();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SearchInput, SearchInputProps, ToolbarFilter, ToolbarFilterProps } from '@patternfly/react-core';
|
|
3
|
+
|
|
4
|
+
/** extends SearchInputProps */
|
|
5
|
+
export interface DataViewTextFilterProps extends SearchInputProps {
|
|
6
|
+
/** Unique key for the filter attribute */
|
|
7
|
+
filterId: string;
|
|
8
|
+
/** Current filter value */
|
|
9
|
+
value?: string;
|
|
10
|
+
/** Filter title displayed in the toolbar */
|
|
11
|
+
title: string;
|
|
12
|
+
/** Callback for when the input value changes */
|
|
13
|
+
onChange?: (event: React.FormEvent<HTMLInputElement> | undefined, value: string) => void;
|
|
14
|
+
/** Controls visibility of the filter in the toolbar */
|
|
15
|
+
showToolbarItem?: ToolbarFilterProps['showToolbarItem'];
|
|
16
|
+
/** Trims input value on change */
|
|
17
|
+
trimValue?: boolean;
|
|
18
|
+
/** Custom OUIA ID */
|
|
19
|
+
ouiaId?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const DataViewTextFilter: React.FC<DataViewTextFilterProps> = ({
|
|
23
|
+
filterId,
|
|
24
|
+
title,
|
|
25
|
+
value = '',
|
|
26
|
+
onChange,
|
|
27
|
+
onClear = () => onChange?.(undefined, ''),
|
|
28
|
+
showToolbarItem,
|
|
29
|
+
trimValue = true,
|
|
30
|
+
ouiaId = 'DataViewTextFilter',
|
|
31
|
+
...props
|
|
32
|
+
}: DataViewTextFilterProps) => (
|
|
33
|
+
<ToolbarFilter
|
|
34
|
+
data-ouia-component-id={ouiaId}
|
|
35
|
+
chips={value.length > 0 ? [ { key: title, node: value } ] : []}
|
|
36
|
+
deleteChip={() => onChange?.(undefined, '')}
|
|
37
|
+
categoryName={title}
|
|
38
|
+
showToolbarItem={showToolbarItem}
|
|
39
|
+
>
|
|
40
|
+
<SearchInput
|
|
41
|
+
searchInputId={filterId}
|
|
42
|
+
value={value}
|
|
43
|
+
onChange={(e, inputValue) => onChange?.(e, trimValue ? inputValue.trim() : inputValue)}
|
|
44
|
+
onClear={onClear}
|
|
45
|
+
placeholder={`Filter by ${title}`}
|
|
46
|
+
aria-label={`${title ?? filterId} filter`}
|
|
47
|
+
data-ouia-component-id={`${ouiaId}-input`}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
</ToolbarFilter>
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
export default DataViewTextFilter;
|