From cfbe8f0fa040d78ce56a8237cb6cc0be44bf6229 Mon Sep 17 00:00:00 2001
From: Filip Hlavac <50696716+fhlavac@users.noreply.github.com>
Date: Wed, 23 Oct 2024 13:24:08 +0200
Subject: [PATCH 01/23] Update Components.md
---
.../extensions/data-view/examples/Components/Components.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md b/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
index a7efd40..6ab0c4d 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
@@ -72,6 +72,8 @@ The `DataViewTable` component accepts the following props:
- optional `props` (`TableProps`) that are passed down to the `
` component, except for `onSelect`, which is managed internally.
+It is also possible to disable row selection using the `isSelectDisabled` function passed to the wrapping data view component.
+
### Tree table example
This example shows the tree table variant with expandable rows, custom icons for leaf and parent nodes. Tree table is turned on by passing `isTreeTable` flag to the `DataViewTable` component. You can pass `collapsedIcon`, `expandedIcon` or `leafIcon` to be displayen rows with given status. The tree table rows have to be defined in a format of object with following keys:
- `row` (`DataViewTd[]`) defining the content for each cell in the row.
From d3af475faac8c72b17891e532310e8c7c2da3101 Mon Sep 17 00:00:00 2001
From: Filip Hlavac <50696716+fhlavac@users.noreply.github.com>
Date: Wed, 23 Oct 2024 15:49:57 +0200
Subject: [PATCH 02/23] Update Components.md
---
.../extensions/data-view/examples/Components/Components.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md b/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
index 6ab0c4d..ab240ed 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
@@ -72,7 +72,7 @@ The `DataViewTable` component accepts the following props:
- optional `props` (`TableProps`) that are passed down to the `` component, except for `onSelect`, which is managed internally.
-It is also possible to disable row selection using the `isSelectDisabled` function passed to the wrapping data view component.
+It is also possible to disable row selection using the `isSelectDisabled` function passed to the wrapping data view component through `selection`.
### Tree table example
This example shows the tree table variant with expandable rows, custom icons for leaf and parent nodes. Tree table is turned on by passing `isTreeTable` flag to the `DataViewTable` component. You can pass `collapsedIcon`, `expandedIcon` or `leafIcon` to be displayen rows with given status. The tree table rows have to be defined in a format of object with following keys:
@@ -80,7 +80,7 @@ This example shows the tree table variant with expandable rows, custom icons for
- `id` (`string`) for the row (used to match items in selection end expand the rows).
- optional `children` (`DataViewTrTree[]`) defining the children rows.
-It is also possible to disable row selection using the `isSelectDisabled` function passed to the wrapping data view component.
+It is also possible to disable row selection using the `isSelectDisabled` function passed to the wrapping data view component through `selection`.
```js file="./DataViewTableTreeExample.tsx"
From 1253b5b75ab358676f4b4c24c38d3611924594ea Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Fri, 1 Nov 2024 14:12:01 +0100
Subject: [PATCH 03/23] fix(DataView): Extend StackProps in DataViewProps
---
packages/module/src/DataView/DataView.tsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/packages/module/src/DataView/DataView.tsx b/packages/module/src/DataView/DataView.tsx
index 094d594..201a586 100644
--- a/packages/module/src/DataView/DataView.tsx
+++ b/packages/module/src/DataView/DataView.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Stack, StackItem } from '@patternfly/react-core';
+import { Stack, StackItem, StackProps } from '@patternfly/react-core';
import { DataViewSelection, InternalContextProvider } from '../InternalContext';
export const DataViewState = {
@@ -10,7 +10,8 @@ export const DataViewState = {
export type DataViewState = typeof DataViewState[keyof typeof DataViewState];
-export interface DataViewProps {
+/** extends StackProps */
+export interface DataViewProps extends StackProps {
/** Content rendered inside the data view */
children: React.ReactNode;
/** Custom OUIA ID */
From 756ed012c993af57ce495bbf29309edd365abd6b Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Fri, 1 Nov 2024 14:12:32 +0100
Subject: [PATCH 04/23] fix(DataView): Update example to not trigger rowClick
on select/action
---
.../examples/EventsContext/EventsContext.md | 1 +
.../examples/EventsContext/EventsExample.tsx | 32 ++++++++++++++++---
2 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsContext.md b/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsContext.md
index 2c0cfe4..293a1a0 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsContext.md
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsContext.md
@@ -18,6 +18,7 @@ import { Table, Tbody, Th, Thead, Tr, Td } from '@patternfly/react-table';
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
import { useDataViewEventsContext, DataViewEventsContext, DataViewEventsProvider, EventTypes } from '@patternfly/react-data-view/dist/dynamic/DataViewEventsContext';
+import { useDataViewSelection } from '@patternfly/react-data-view/dist/dynamic/Hooks';
import { Drawer, DrawerContent, DrawerContentBody } from '@patternfly/react-core';
The **data view events context** provides a way of listening to the data view events from the outside of the component.
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsExample.tsx b/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsExample.tsx
index 19e09be..d3ccfad 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsExample.tsx
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsExample.tsx
@@ -3,6 +3,8 @@ import { Drawer, DrawerActions, DrawerCloseButton, DrawerContent, DrawerContentB
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
import { DataViewEventsProvider, EventTypes, useDataViewEventsContext } from '@patternfly/react-data-view/dist/dynamic/DataViewEventsContext';
+import { useDataViewSelection } from '@patternfly/react-data-view/dist/dynamic/Hooks';
+import { ActionsColumn } from '@patternfly/react-table';
interface Repository {
name: string;
@@ -64,25 +66,45 @@ interface RepositoriesTableProps {
selectedRepo?: Repository;
}
+const rowActions = [
+ {
+ title: 'Some action',
+ onClick: () => console.log('clicked on Some action') // eslint-disable-line no-console
+ },
+ {
+ title: Another action
,
+ onClick: () => console.log('clicked on Another action') // eslint-disable-line no-console
+ },
+ {
+ isSeparator: true
+ },
+ {
+ title: 'Third action',
+ onClick: () => console.log('clicked on Third action') // eslint-disable-line no-console
+ }
+];
+
const RepositoriesTable: React.FunctionComponent = ({ selectedRepo = undefined }) => {
+ const selection = useDataViewSelection({ matchOption: (a, b) => a.row[0] === b.row[0] });
const { trigger } = useDataViewEventsContext();
const rows = useMemo(() => {
- const handleRowClick = (repo: Repository | undefined) => {
- trigger(EventTypes.rowClick, repo);
+ const handleRowClick = (event, repo: Repository | undefined) => {
+ // prevents drawer toggle on actions or checkbox click
+ event.target.matches('td') && trigger(EventTypes.rowClick, repo);
};
return repositories.map(repo => ({
- row: Object.values(repo),
+ row: [ ...Object.values(repo), { cell: , props: { isActionCell: true } } ],
props: {
isClickable: true,
- onRowClick: () => handleRowClick(selectedRepo?.name === repo.name ? undefined : repo),
+ onRowClick: (event) => handleRowClick(event, selectedRepo?.name === repo.name ? undefined : repo),
isRowSelected: selectedRepo?.name === repo.name
}
}));
}, [ selectedRepo?.name, trigger ]);
return (
-
+
);
From 5a6ae92874d9f5c0c07672cb47eba1e0c664c5d7 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Fri, 1 Nov 2024 14:27:36 +0100
Subject: [PATCH 05/23] fix(DataView): Allow rowClick on Tr as well
---
.../data-view/examples/EventsContext/EventsExample.tsx | 2 +-
packages/module/patternfly-docs/generated/index.js | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsExample.tsx b/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsExample.tsx
index d3ccfad..2afd6fb 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsExample.tsx
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/EventsContext/EventsExample.tsx
@@ -90,7 +90,7 @@ const RepositoriesTable: React.FunctionComponent = ({ se
const rows = useMemo(() => {
const handleRowClick = (event, repo: Repository | undefined) => {
// prevents drawer toggle on actions or checkbox click
- event.target.matches('td') && trigger(EventTypes.rowClick, repo);
+ (event.target.matches('td') || event.target.matches('tr')) && trigger(EventTypes.rowClick, repo);
};
return repositories.map(repo => ({
diff --git a/packages/module/patternfly-docs/generated/index.js b/packages/module/patternfly-docs/generated/index.js
index 851e24a..278a0b3 100644
--- a/packages/module/patternfly-docs/generated/index.js
+++ b/packages/module/patternfly-docs/generated/index.js
@@ -49,8 +49,8 @@ module.exports = {
'/extensions/data-view/components/react': {
id: "Components",
title: "Components",
- toc: [{"text":"Data view toolbar"},[{"text":"Basic toolbar example"}],{"text":"Data view table"},[{"text":"Rows and columns customization"},{"text":"Tree table example"},{"text":"Empty state example"}]],
- examples: ["Basic toolbar example","Rows and columns customization","Tree table example","Empty state example"],
+ toc: [{"text":"Data view toolbar"},[{"text":"Basic toolbar example"},{"text":"Actions configuration"},{"text":"Actions example"}],{"text":"Data view table"},[{"text":"Rows and columns customization"},{"text":"Tree table example"},{"text":"Empty state example"},{"text":"Error state example"},{"text":"Loading state example"}]],
+ examples: ["Basic toolbar example","Actions example","Rows and columns customization","Tree table example","Empty state example","Error state example","Loading state example"],
section: "extensions",
subsection: "Data view",
source: "react",
From f9bfa0607462f05010d46c47108bb0f274f739e0 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Tue, 29 Oct 2024 13:47:38 +0100
Subject: [PATCH 06/23] fix(docs): Display extended interfaces in the docs
---
.../src/DataViewTable/DataViewTable.tsx | 26 ++++++++++++++++---
.../DataViewTableBasic/DataViewTableBasic.tsx | 1 +
.../DataViewTableHead/DataViewTableHead.tsx | 1 +
.../DataViewTableTree/DataViewTableTree.tsx | 1 +
packages/module/src/Hooks/pagination.ts | 1 +
packages/module/src/Hooks/selection.ts | 5 ++--
.../src/InternalContext/InternalContext.tsx | 1 +
7 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/packages/module/src/DataViewTable/DataViewTable.tsx b/packages/module/src/DataViewTable/DataViewTable.tsx
index f7a0697..97a4260 100644
--- a/packages/module/src/DataViewTable/DataViewTable.tsx
+++ b/packages/module/src/DataViewTable/DataViewTable.tsx
@@ -8,18 +8,38 @@ import { DataViewTableTree, DataViewTableTreeProps } from '../DataViewTableTree'
import { DataViewTableBasic, DataViewTableBasicProps } from '../DataViewTableBasic';
// Table head typings
-export type DataViewTh = ReactNode | { cell: ReactNode; props?: ThProps };
+export type DataViewTh = ReactNode | {
+ /** Table head cell node */
+ cell: ReactNode;
+ /** Props passed to Th */
+ props?: ThProps
+};
export const isDataViewThObject = (value: DataViewTh): value is { cell: ReactNode; props?: ThProps } => value != null && typeof value === 'object' && 'cell' in value;
// Basic table typings
-export interface DataViewTrObject { row: DataViewTd[], id?: string, props?: TrProps }
-export type DataViewTd = ReactNode | { cell: ReactNode; props?: TdProps };
+export interface DataViewTrObject {
+ /** Array of rows */
+ row: DataViewTd[],
+ /** Unique identifier of a row */
+ id?: string,
+ /** Props passed to Tr */
+ props?: TrProps
+}
+
+export type DataViewTd = ReactNode | {
+ /** Table body cell node */
+ cell: ReactNode;
+ /** Props passed to Td */
+ props?: TdProps
+};
+
export type DataViewTr = DataViewTd[] | DataViewTrObject;
export const isDataViewTdObject = (value: DataViewTd): value is { cell: ReactNode; props?: TdProps } => value != null && typeof value === 'object' && 'cell' in value;
export const isDataViewTrObject = (value: DataViewTr): value is { row: DataViewTd[], id?: string } => value != null && typeof value === 'object' && 'row' in value;
// Tree table typings
+/** extends DataViewTrObject */
export interface DataViewTrTree extends DataViewTrObject { id: string, children?: DataViewTrTree[] }
export type DataViewTableProps =
diff --git a/packages/module/src/DataViewTableBasic/DataViewTableBasic.tsx b/packages/module/src/DataViewTableBasic/DataViewTableBasic.tsx
index d2f1ac8..2b32cae 100644
--- a/packages/module/src/DataViewTableBasic/DataViewTableBasic.tsx
+++ b/packages/module/src/DataViewTableBasic/DataViewTableBasic.tsx
@@ -11,6 +11,7 @@ import { DataViewTableHead } from '../DataViewTableHead';
import { DataViewTh, DataViewTr, isDataViewTdObject, isDataViewTrObject } from '../DataViewTable';
import { DataViewState } from '../DataView/DataView';
+/** extends TableProps */
export interface DataViewTableBasicProps extends Omit {
/** Columns definition */
columns: DataViewTh[];
diff --git a/packages/module/src/DataViewTableHead/DataViewTableHead.tsx b/packages/module/src/DataViewTableHead/DataViewTableHead.tsx
index 8466389..d1073d4 100644
--- a/packages/module/src/DataViewTableHead/DataViewTableHead.tsx
+++ b/packages/module/src/DataViewTableHead/DataViewTableHead.tsx
@@ -8,6 +8,7 @@ import {
import { useInternalContext } from '../InternalContext';
import { DataViewTh, isDataViewThObject } from '../DataViewTable';
+/** extends TheadProps */
export interface DataViewTableHeadProps extends TheadProps {
/** Indicates whether table is a tree */
isTreeTable?: boolean;
diff --git a/packages/module/src/DataViewTableTree/DataViewTableTree.tsx b/packages/module/src/DataViewTableTree/DataViewTableTree.tsx
index a5643f8..a743295 100644
--- a/packages/module/src/DataViewTableTree/DataViewTableTree.tsx
+++ b/packages/module/src/DataViewTableTree/DataViewTableTree.tsx
@@ -30,6 +30,7 @@ const isNodeChecked = (node: DataViewTrTree, isSelected: (node: DataViewTrTree)
return allSelected;
};
+/** extends TableProps */
export interface DataViewTableTreeProps extends Omit {
/** Columns definition */
columns: DataViewTh[];
diff --git a/packages/module/src/Hooks/pagination.ts b/packages/module/src/Hooks/pagination.ts
index 9f48c52..4209f66 100644
--- a/packages/module/src/Hooks/pagination.ts
+++ b/packages/module/src/Hooks/pagination.ts
@@ -15,6 +15,7 @@ export interface UseDataViewPaginationProps {
perPageParam?: string;
}
+/** extends UseDataViewPaginationProps */
export interface DataViewPaginationProps extends UseDataViewPaginationProps {
/** Current page number */
page: number;
diff --git a/packages/module/src/Hooks/selection.ts b/packages/module/src/Hooks/selection.ts
index d5858ae..2ba443f 100644
--- a/packages/module/src/Hooks/selection.ts
+++ b/packages/module/src/Hooks/selection.ts
@@ -8,8 +8,9 @@ export interface UseDataViewSelectionProps {
initialSelected?: (any)[];
}
-export const useDataViewSelection = ({ matchOption, initialSelected = [] }: UseDataViewSelectionProps) => {
- const [ selected, setSelected ] = useState(initialSelected);
+export const useDataViewSelection = (props?: UseDataViewSelectionProps) => {
+ const [ selected, setSelected ] = useState(props?.initialSelected ?? []);
+ const matchOption = props?.matchOption ? props.matchOption : (option, another) => (option === another);
const onSelect = (isSelecting: boolean, items?: any[] | any) => {
isSelecting && items ?
diff --git a/packages/module/src/InternalContext/InternalContext.tsx b/packages/module/src/InternalContext/InternalContext.tsx
index bef1b22..740c1a8 100644
--- a/packages/module/src/InternalContext/InternalContext.tsx
+++ b/packages/module/src/InternalContext/InternalContext.tsx
@@ -17,6 +17,7 @@ export interface InternalContextProps {
activeState?: DataViewState | string;
}
+/** extends InternalContextProps */
export interface InternalContextValue extends InternalContextProps {
/** Flag indicating if data view is selectable (auto-calculated) */
isSelectable: boolean;
From ec73d468fff55d8e0a3747db07832c693612a1f3 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Tue, 5 Nov 2024 00:30:15 +0100
Subject: [PATCH 07/23] feat(filters): Implement DataViewFilters and text
filter
---
.../src/DataViewFilters/DataViewFilters.tsx | 119 ++++++++++++++++++
packages/module/src/DataViewFilters/index.tsx | 2 +
.../DataViewTextFilter/DataViewTextFilter.tsx | 53 ++++++++
.../module/src/DataViewTextFilter/index.ts | 2 +
.../src/DataViewToolbar/DataViewToolbar.tsx | 75 ++++++-----
packages/module/src/Hooks/filters.ts | 96 ++++++++++++++
packages/module/src/Hooks/index.ts | 1 +
packages/module/src/index.ts | 3 +
8 files changed, 323 insertions(+), 28 deletions(-)
create mode 100644 packages/module/src/DataViewFilters/DataViewFilters.tsx
create mode 100644 packages/module/src/DataViewFilters/index.tsx
create mode 100644 packages/module/src/DataViewTextFilter/DataViewTextFilter.tsx
create mode 100644 packages/module/src/DataViewTextFilter/index.ts
create mode 100644 packages/module/src/Hooks/filters.ts
diff --git a/packages/module/src/DataViewFilters/DataViewFilters.tsx b/packages/module/src/DataViewFilters/DataViewFilters.tsx
new file mode 100644
index 0000000..1dc9958
--- /dev/null
+++ b/packages/module/src/DataViewFilters/DataViewFilters.tsx
@@ -0,0 +1,119 @@
+import React, { useMemo, useState, useRef, useEffect, ReactElement } from 'react';
+import {
+ Menu, MenuContent, MenuItem, MenuList, MenuToggle, Popper, ToolbarGroup, ToolbarToggleGroup, ToolbarToggleGroupProps,
+} from '@patternfly/react-core';
+import { FilterIcon } from '@patternfly/react-icons';
+
+// helper interface to generate attribute menu
+interface DataViewFilterIdentifiers {
+ filterId: string;
+ title: string;
+}
+
+/** extends ToolbarToggleGroupProps */
+export interface DataViewFiltersProps extends Omit {
+ /** Content rendered inside the data view */
+ children: React.ReactNode;
+ /** Optional onChange callback shared across filters */
+ onChange?: (key: string, newValues: Partial) => void;
+ /** Optional values shared across filters */
+ values?: T;
+ /** Icon for the toolbar toggle group */
+ toggleIcon?: ToolbarToggleGroupProps['toggleIcon'];
+ /** Breakpoint for the toolbar toggle group */
+ breakpoint?: ToolbarToggleGroupProps['breakpoint'];
+ /** Custom OUIA ID */
+ ouiaId?: string;
+};
+
+
+export const DataViewFilters = ({
+ children,
+ ouiaId = 'DataViewFilters',
+ toggleIcon = ,
+ breakpoint = 'xl',
+ onChange,
+ values,
+ ...props
+}: DataViewFiltersProps) => {
+ const [ activeAttributeMenu, setActiveAttributeMenu ] = useState('');
+ const [ isAttributeMenuOpen, setIsAttributeMenuOpen ] = useState(false);
+ const attributeToggleRef = useRef(null);
+ const attributeMenuRef = useRef(null);
+ const attributeContainerRef = useRef(null);
+
+ const filterItems: DataViewFilterIdentifiers[] = useMemo(() => React.Children.toArray(children)
+ .map(child =>
+ React.isValidElement(child) ? { filterId: String(child.props.filterId), title: String(child.props.title) } : undefined
+ ).filter((item): item is DataViewFilterIdentifiers => !!item), []); // eslint-disable-line react-hooks/exhaustive-deps
+
+ useEffect(() => {
+ filterItems.length > 0 && setActiveAttributeMenu(filterItems[0].title);
+ }, [ filterItems ]);
+
+ const attributeToggle = (
+ setIsAttributeMenuOpen(!isAttributeMenuOpen)}
+ isExpanded={isAttributeMenuOpen}
+ icon={toggleIcon}
+ >
+ {activeAttributeMenu}
+
+ );
+
+ const attributeMenu = (
+ {
+ const selectedItem = filterItems.find(item => item.filterId === itemId);
+ selectedItem && setActiveAttributeMenu(selectedItem.title);
+ setIsAttributeMenuOpen(false);
+ }}
+ >
+
+
+ {filterItems.map(item => (
+
+ {item.title}
+
+ ))}
+
+
+
+ );
+
+ return (
+
+
+
+ {React.Children.map(children, (child) => (
+ React.isValidElement(child) ? (
+ React.cloneElement(child as ReactElement<{
+ showToolbarItem: boolean;
+ onChange: (_e: unknown, values: unknown) => void;
+ value: unknown;
+ }>, {
+ showToolbarItem: activeAttributeMenu === child.props.title,
+ onChange: (event, value) => onChange?.(event, { [child.props.filterId]: value } as Partial),
+ value: values?.[child.props.filterId],
+ ...child.props
+ })
+ ) : child
+ ))}
+
+
+
+ );
+};
+
+export default DataViewFilters;
diff --git a/packages/module/src/DataViewFilters/index.tsx b/packages/module/src/DataViewFilters/index.tsx
new file mode 100644
index 0000000..ba0ff37
--- /dev/null
+++ b/packages/module/src/DataViewFilters/index.tsx
@@ -0,0 +1,2 @@
+export { default } from './DataViewFilters';
+export * from './DataViewFilters';
diff --git a/packages/module/src/DataViewTextFilter/DataViewTextFilter.tsx b/packages/module/src/DataViewTextFilter/DataViewTextFilter.tsx
new file mode 100644
index 0000000..e2d1e43
--- /dev/null
+++ b/packages/module/src/DataViewTextFilter/DataViewTextFilter.tsx
@@ -0,0 +1,53 @@
+import React from 'react';
+import { SearchInput, SearchInputProps, ToolbarFilter, ToolbarFilterProps } from '@patternfly/react-core';
+
+/** extends SearchInputProps */
+export interface DataViewTextFilterProps extends SearchInputProps {
+ /** Unique key for the filter attribute */
+ filterId: string;
+ /** Current filter value */
+ value?: string;
+ /** Filter title displayed in the toolbar */
+ title: string;
+ /** Callback for when the input value changes */
+ onChange?: (event: React.FormEvent | undefined, value: string) => void;
+ /** Controls visibility of the filter in the toolbar */
+ showToolbarItem?: ToolbarFilterProps['showToolbarItem'];
+ /** Trims input value on change */
+ trimValue?: boolean;
+ /** Custom OUIA ID */
+ ouiaId?: string;
+}
+
+export const DataViewTextFilter: React.FC = ({
+ filterId,
+ title,
+ value = '',
+ onChange,
+ onClear = () => onChange?.(undefined, ''),
+ showToolbarItem,
+ trimValue = true,
+ ouiaId = 'DataViewTextFilter',
+ ...props
+}: DataViewTextFilterProps) => (
+ 0 ? [ { key: title, node: value } ] : []}
+ deleteChip={() => onChange?.(undefined, '')}
+ categoryName={title}
+ showToolbarItem={showToolbarItem}
+ >
+ onChange?.(e, trimValue ? inputValue.trim() : inputValue)}
+ onClear={onClear}
+ placeholder={`Filter by ${title}`}
+ aria-label={`${title ?? filterId} filter`}
+ data-ouia-component-id={`${ouiaId}-input`}
+ {...props}
+ />
+
+);
+
+export default DataViewTextFilter;
diff --git a/packages/module/src/DataViewTextFilter/index.ts b/packages/module/src/DataViewTextFilter/index.ts
new file mode 100644
index 0000000..fd2e65a
--- /dev/null
+++ b/packages/module/src/DataViewTextFilter/index.ts
@@ -0,0 +1,2 @@
+export { default } from './DataViewTextFilter';
+export * from './DataViewTextFilter';
diff --git a/packages/module/src/DataViewToolbar/DataViewToolbar.tsx b/packages/module/src/DataViewToolbar/DataViewToolbar.tsx
index c2f6f1d..bdb962d 100644
--- a/packages/module/src/DataViewToolbar/DataViewToolbar.tsx
+++ b/packages/module/src/DataViewToolbar/DataViewToolbar.tsx
@@ -1,41 +1,60 @@
-import React, { PropsWithChildren } from 'react';
-import { Toolbar, ToolbarContent, ToolbarItem, ToolbarItemVariant } from '@patternfly/react-core';
+import React, { PropsWithChildren, useRef } from 'react';
+import { Button, Toolbar, ToolbarContent, ToolbarItem, ToolbarItemVariant, ToolbarProps } from '@patternfly/react-core';
-export interface DataViewToolbarProps extends PropsWithChildren {
+/** extends ToolbarProps */
+export interface DataViewToolbarProps extends Omit, 'ref'> {
/** Toolbar className */
className?: string;
/** Custom OUIA ID */
ouiaId?: string;
- /** React component to display bulk select */
+ /** React node to display bulk select */
bulkSelect?: React.ReactNode;
- /** React component to display pagination */
+ /** React node to display pagination */
pagination?: React.ReactNode;
- /** React component to display actions */
+ /** React node to display actions */
actions?: React.ReactNode;
+ /** React node to display filters */
+ filters?: React.ReactNode;
+ /** React node to display custom filter chips */
+ customChipGroupContent?: React.ReactNode;
}
-export const DataViewToolbar: React.FC = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, actions, pagination, children, ...props }: DataViewToolbarProps) => (
-
-
- {bulkSelect && (
-
- {bulkSelect}
-
- )}
- {actions && (
-
- {actions}
-
- )}
- {pagination && (
-
- {pagination}
-
- )}
- {children}
-
-
-)
+export const DataViewToolbar: React.FC = ({ className, ouiaId = 'DataViewToolbar', bulkSelect, actions, pagination, filters, customChipGroupContent, clearAllFilters, children, ...props }: DataViewToolbarProps) => {
+ const defaultClearFilters = useRef(
+
+
+ Clear filters
+
+
+ );
+ return (
+
+
+ {bulkSelect && (
+
+ {bulkSelect}
+
+ )}
+ {actions && (
+
+ {actions}
+
+ )}
+ {filters && (
+
+ {filters}
+
+ )}
+ {pagination && (
+
+ {pagination}
+
+ )}
+ {children}
+
+
+ )
+};
export default DataViewToolbar;
diff --git a/packages/module/src/Hooks/filters.ts b/packages/module/src/Hooks/filters.ts
new file mode 100644
index 0000000..4f81e17
--- /dev/null
+++ b/packages/module/src/Hooks/filters.ts
@@ -0,0 +1,96 @@
+import { useState, useCallback, useEffect, useMemo } from "react";
+
+export interface UseDataViewFiltersProps {
+ /** Initial filters object */
+ initialFilters?: T;
+ /** Current search parameters as a string */
+ searchParams?: URLSearchParams;
+ /** Function to set search parameters */
+ setSearchParams?: (params: URLSearchParams) => void;
+};
+
+export const useDataViewFilters = ({
+ initialFilters = {} as T,
+ searchParams,
+ setSearchParams,
+}: UseDataViewFiltersProps) => {
+ const isUrlSyncEnabled = useMemo(() => searchParams && !!setSearchParams, [ searchParams, setSearchParams ]);
+
+ const getInitialFilters = useCallback((): T => isUrlSyncEnabled ? Object.keys(initialFilters).reduce((loadedFilters, key) => {
+ const urlValue = searchParams?.get(key);
+ loadedFilters[key as keyof T] = urlValue
+ ? (urlValue as T[keyof T] | T[keyof T])
+ : initialFilters[key as keyof T];
+ return loadedFilters;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, { ...initialFilters }) : initialFilters, [ isUrlSyncEnabled, JSON.stringify(initialFilters), searchParams?.toString() ]);
+
+ const [ filters, setFilters ] = useState(getInitialFilters());
+
+ const updateSearchParams = useCallback(
+ (newFilters: T) => {
+ if (isUrlSyncEnabled) {
+ const params = new URLSearchParams(searchParams);
+ Object.entries(newFilters).forEach(([ key, value ]) => {
+ if (value) {
+ params.set(key, Array.isArray(value) ? value.join(',') : value);
+ } else {
+ params.delete(key);
+ }
+ });
+ setSearchParams?.(params);
+ }
+ },
+ [ isUrlSyncEnabled, searchParams, setSearchParams ]
+ );
+
+ useEffect(() => {
+ isUrlSyncEnabled && setFilters(getInitialFilters())
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
+
+ const onSetFilters = useCallback(
+ (newFilters: Partial) => {
+ setFilters(prevFilters => {
+ const updatedFilters = { ...prevFilters, ...newFilters };
+ isUrlSyncEnabled && updateSearchParams(updatedFilters);
+ return updatedFilters;
+ });
+ },
+ [ isUrlSyncEnabled, updateSearchParams ]
+ );
+
+ // helper function to reset filters
+ const resetFilterValues = useCallback((filters: Partial): Partial => Object.entries(filters).reduce((acc, [ key, value ]) => {
+ if (Array.isArray(value)) {
+ acc[key as keyof T] = [] as T[keyof T];
+ } else {
+ acc[key as keyof T] = '' as T[keyof T];
+ }
+ return acc;
+ }, {} as Partial), []);
+
+ const onDeleteFilters = useCallback(
+ (filtersToDelete: Partial) => {
+ setFilters(prevFilters => {
+ const updatedFilters = { ...prevFilters,...resetFilterValues(filtersToDelete) };
+ isUrlSyncEnabled && updateSearchParams(updatedFilters);
+ return updatedFilters;
+ });
+ },
+ [ isUrlSyncEnabled, updateSearchParams, resetFilterValues ]
+ );
+
+ const clearAllFilters = useCallback(() => {
+ const clearedFilters = resetFilterValues(filters) as T;
+
+ setFilters(clearedFilters);
+ isUrlSyncEnabled && updateSearchParams(clearedFilters);
+ }, [ filters, isUrlSyncEnabled, updateSearchParams, resetFilterValues ]);
+
+ return {
+ filters,
+ onSetFilters,
+ onDeleteFilters,
+ clearAllFilters,
+ };
+};
diff --git a/packages/module/src/Hooks/index.ts b/packages/module/src/Hooks/index.ts
index 4ed29ea..546a0da 100644
--- a/packages/module/src/Hooks/index.ts
+++ b/packages/module/src/Hooks/index.ts
@@ -1,2 +1,3 @@
export * from './pagination';
export * from './selection';
+export * from './filters';
diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts
index 1ce1801..a34586c 100644
--- a/packages/module/src/index.ts
+++ b/packages/module/src/index.ts
@@ -7,6 +7,9 @@ export * from './Hooks';
export { default as DataViewToolbar } from './DataViewToolbar';
export * from './DataViewToolbar';
+export { default as DataViewTextFilter } from './DataViewTextFilter';
+export * from './DataViewTextFilter';
+
export { default as DataViewTableTree } from './DataViewTableTree';
export * from './DataViewTableTree';
From f51f1a106885c07bb44f9f4bab96316fb1b92ffa Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Tue, 5 Nov 2024 00:30:49 +0100
Subject: [PATCH 08/23] feat(filters): Test DataView filters
---
cypress/component/DataViewFilters.cy.tsx | 111 ++++++++++
cypress/component/DataViewTextFilter.cy.tsx | 75 +++++++
.../DataViewFilters/DataViewFilters.test.tsx | 21 ++
.../DataViewFilters.test.tsx.snap | 182 ++++++++++++++++
.../DataViewTextFilter.test.tsx | 24 +++
.../DataViewTextFilter.test.tsx.snap | 196 ++++++++++++++++++
.../DataViewToolbar.test.tsx.snap | 14 ++
packages/module/src/Hooks/filters.test.tsx | 62 ++++++
8 files changed, 685 insertions(+)
create mode 100644 cypress/component/DataViewFilters.cy.tsx
create mode 100644 cypress/component/DataViewTextFilter.cy.tsx
create mode 100644 packages/module/src/DataViewFilters/DataViewFilters.test.tsx
create mode 100644 packages/module/src/DataViewFilters/__snapshots__/DataViewFilters.test.tsx.snap
create mode 100644 packages/module/src/DataViewTextFilter/DataViewTextFilter.test.tsx
create mode 100644 packages/module/src/DataViewTextFilter/__snapshots__/DataViewTextFilter.test.tsx.snap
create mode 100644 packages/module/src/Hooks/filters.test.tsx
diff --git a/cypress/component/DataViewFilters.cy.tsx b/cypress/component/DataViewFilters.cy.tsx
new file mode 100644
index 0000000..cd6d058
--- /dev/null
+++ b/cypress/component/DataViewFilters.cy.tsx
@@ -0,0 +1,111 @@
+import React from 'react';
+import { useDataViewFilters } from '@patternfly/react-data-view/dist/dynamic/Hooks';
+import { DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters';
+import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
+import { DataViewToolbar } from '@patternfly/react-data-view/dist/esm/DataViewToolbar';
+import { FilterIcon } from '@patternfly/react-icons';
+
+const filtersProps = {
+ ouiaId: 'DataViewFilters',
+ toggleIcon: ,
+ values: { name: '', branch: '' }
+};
+
+interface RepositoryFilters {
+ name: string,
+ branch: string
+};
+
+const DataViewToolbarWithState = (props: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
+ const { filters, onSetFilters, clearAllFilters } = useDataViewFilters({ initialFilters: { name: '', branch: '' } });
+
+ return (
+ onSetFilters(values)} values={filters} {...props}>
+
+
+
+ }
+ />
+ );
+};
+
+describe('DataViewFilters', () => {
+ it('renders DataViewFilters with menu and filter items', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewFilters"]').should('exist');
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+
+ cy.contains('Name').should('exist');
+ cy.contains('Branch').should('exist');
+ });
+
+ it('can select a filter option', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewFilters"]').should('contain.text', 'Name');
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+ cy.contains('Branch').click();
+
+ cy.get('[data-ouia-component-id="DataViewFilters"]').should('contain.text', 'Branch');
+ });
+
+ it('responds to input and clears the filters', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+ cy.contains('Name').click();
+
+ cy.get('input[placeholder="Filter by name"]').type('Repository one');
+ cy.get('.pf-v5-c-chip__text').should('have.length', 1);
+ cy.get('input[placeholder="Filter by name"]').clear();
+ cy.get('.pf-v5-c-chip__text').should('have.length', 0);
+ });
+
+ it('displays chips for selected filters', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+ cy.contains('Name').click();
+ cy.get('input[placeholder="Filter by name"]').type('Repository one');
+
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+ cy.contains('Branch').click();
+ cy.get('input[placeholder="Filter by branch"]').type('Main branch');
+
+ cy.get('.pf-v5-c-chip__text').should('have.length', 2);
+ cy.get('.pf-v5-c-chip__text').eq(0).should('contain.text', 'Repository one');
+ cy.get('.pf-v5-c-chip__text').eq(1).should('contain.text', 'Main branch');
+ });
+
+ it('removes filters by clicking individual chips', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+ cy.contains('Name').click();
+ cy.get('input[placeholder="Filter by name"]').type('Repository one');
+
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+ cy.contains('Branch').click();
+ cy.get('input[placeholder="Filter by branch"]').type('Main branch');
+
+ cy.get('[data-ouia-component-id="close"]').should('have.length', 2);
+
+ cy.get('[data-ouia-component-id="close"]').first().click();
+ cy.get('[data-ouia-component-id="close"]').last().click();
+
+ cy.get('[data-ouia-component-id="close"]').should('have.length', 0);
+ });
+
+ it('clears all filters using the clear-all button', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+ cy.contains('Name').click();
+ cy.get('input[placeholder="Filter by name"]').type('Repository one');
+
+ cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
+ cy.contains('Branch').click();
+ cy.get('input[placeholder="Filter by branch"]').type('Main branch');
+
+ cy.get('[data-ouia-component-id="FiltersExampleHeader-clear-all-filters"]').should('exist').click();
+ });
+});
diff --git a/cypress/component/DataViewTextFilter.cy.tsx b/cypress/component/DataViewTextFilter.cy.tsx
new file mode 100644
index 0000000..8d67ca4
--- /dev/null
+++ b/cypress/component/DataViewTextFilter.cy.tsx
@@ -0,0 +1,75 @@
+import React, { useState } from 'react';
+import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
+import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
+
+const defaultProps = {
+ filterId: 'name',
+ title: 'Name',
+ value: '',
+ ouiaId: 'DataViewTextFilter',
+ placeholder: 'Filter by name'
+};
+
+const DataViewToolbarWithState = (props: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
+ const [ value, setValue ] = useState('Repository one');
+
+ return (
+ setValue('')}>
+ setValue('')} {...props} />
+
+ );
+};
+
+describe('DataViewTextFilter', () => {
+
+ it('renders DataViewTextFilter with correct initial values', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewTextFilter"]').should('exist');
+ cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input')
+ .should('have.attr', 'placeholder', 'Filter by name')
+ .and('have.value', '');
+ });
+
+ it('accepts input when passed', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input')
+ .type('Repository one')
+ .should('have.value', 'Repository one');
+ });
+
+ it('displays a chip when value is present and removes it on delete', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input').should('have.value', 'Repository one');
+
+ cy.get('.pf-v5-c-chip__text').contains('Repository one');
+ cy.get('.pf-m-chip-group button.pf-v5-c-button.pf-m-plain').click();
+
+ cy.get('.pf-v5-c-chip__text').should('not.exist');
+ cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input').should('have.value', '');
+ });
+
+ it('clears input when the clear button is clicked', () => {
+ cy.mount( );
+ cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input').should('have.value', 'Repository one');
+
+ cy.get('[data-ouia-component-id="DataViewToolbar-clear-all-filters"]').click();
+
+ cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input').should('have.value', '');
+ });
+
+ it('hides or shows the toolbar item based on showToolbarItem prop', () => {
+ cy.mount(
+
+
+
+ );
+ cy.get('[data-ouia-component-id="DataViewTextFilter"]').should('not.exist');
+
+ cy.mount(
+
+
+
+ );
+ cy.get('[data-ouia-component-id="DataViewTextFilter"]').should('exist');
+ });
+});
diff --git a/packages/module/src/DataViewFilters/DataViewFilters.test.tsx b/packages/module/src/DataViewFilters/DataViewFilters.test.tsx
new file mode 100644
index 0000000..9f9cb5a
--- /dev/null
+++ b/packages/module/src/DataViewFilters/DataViewFilters.test.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import DataViewFilters from './DataViewFilters';
+import DataViewToolbar from '../DataViewToolbar';
+import DataViewTextFilter from '../DataViewTextFilter';
+
+describe('DataViewFilters component', () => {
+ const mockOnChange = jest.fn();
+
+ it('should render correctly', () => {
+ const { container } = render(
+
+
+
+ }
+ />);
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/packages/module/src/DataViewFilters/__snapshots__/DataViewFilters.test.tsx.snap b/packages/module/src/DataViewFilters/__snapshots__/DataViewFilters.test.tsx.snap
new file mode 100644
index 0000000..b8861d0
--- /dev/null
+++ b/packages/module/src/DataViewFilters/__snapshots__/DataViewFilters.test.tsx.snap
@@ -0,0 +1,182 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DataViewFilters component should render correctly 1`] = `
+
+`;
diff --git a/packages/module/src/DataViewTextFilter/DataViewTextFilter.test.tsx b/packages/module/src/DataViewTextFilter/DataViewTextFilter.test.tsx
new file mode 100644
index 0000000..5630735
--- /dev/null
+++ b/packages/module/src/DataViewTextFilter/DataViewTextFilter.test.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import DataViewTextFilter, { DataViewTextFilterProps } from './DataViewTextFilter';
+import DataViewToolbar from '../DataViewToolbar';
+
+describe('DataViewTextFilter component', () => {
+ const mockOnChange = jest.fn();
+
+ const defaultProps: DataViewTextFilterProps = {
+ filterId: 'test-filter',
+ title: 'Test Filter',
+ value: 'initial value',
+ onChange: mockOnChange,
+ };
+
+ it('should render correctly', () => {
+ const { container } = render(
+ }
+ />);
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/packages/module/src/DataViewTextFilter/__snapshots__/DataViewTextFilter.test.tsx.snap b/packages/module/src/DataViewTextFilter/__snapshots__/DataViewTextFilter.test.tsx.snap
new file mode 100644
index 0000000..2091670
--- /dev/null
+++ b/packages/module/src/DataViewTextFilter/__snapshots__/DataViewTextFilter.test.tsx.snap
@@ -0,0 +1,196 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DataViewTextFilter component should render correctly 1`] = `
+
+`;
diff --git a/packages/module/src/DataViewToolbar/__snapshots__/DataViewToolbar.test.tsx.snap b/packages/module/src/DataViewToolbar/__snapshots__/DataViewToolbar.test.tsx.snap
index 0573355..deb8cc9 100644
--- a/packages/module/src/DataViewToolbar/__snapshots__/DataViewToolbar.test.tsx.snap
+++ b/packages/module/src/DataViewToolbar/__snapshots__/DataViewToolbar.test.tsx.snap
@@ -526,6 +526,20 @@ exports[`DataViewToolbar component should render correctly 1`] = `
+
+
+ Clear filters
+
+
,
diff --git a/packages/module/src/Hooks/filters.test.tsx b/packages/module/src/Hooks/filters.test.tsx
new file mode 100644
index 0000000..d3ea7a8
--- /dev/null
+++ b/packages/module/src/Hooks/filters.test.tsx
@@ -0,0 +1,62 @@
+import '@testing-library/jest-dom';
+import { renderHook, act } from '@testing-library/react';
+import { useDataViewFilters, UseDataViewFiltersProps } from './filters';
+
+describe('useDataViewFilters', () => {
+ const initialFilters = { search: 'test', tags: [ 'tag1', 'tag2' ] };
+
+ it('should initialize with provided initial filters', () => {
+ const { result } = renderHook(() => useDataViewFilters({ initialFilters }));
+ expect(result.current.filters).toEqual(initialFilters);
+ });
+
+ it('should initialize with empty filters if no initialFilters provided', () => {
+ const { result } = renderHook(() => useDataViewFilters({}));
+ expect(result.current.filters).toEqual({});
+ });
+
+ it('should set filters correctly', () => {
+ const { result } = renderHook(() => useDataViewFilters({ initialFilters }));
+ const newFilters = { search: 'new search' };
+ act(() => result.current.onSetFilters(newFilters));
+
+ expect(result.current.filters).toEqual({ ...initialFilters, ...newFilters });
+ });
+
+ it('should delete specific filters without removing keys', () => {
+ const { result } = renderHook(() => useDataViewFilters({ initialFilters }));
+ const filtersToDelete = { search: 'test' };
+ act(() => result.current.onDeleteFilters(filtersToDelete));
+
+ expect(result.current.filters).toEqual({ search: '', tags: [ 'tag1', 'tag2' ] });
+ });
+
+ it('should clear all filters', () => {
+ const { result } = renderHook(() => useDataViewFilters({ initialFilters }));
+ act(() => result.current.clearAllFilters());
+
+ expect(result.current.filters).toEqual({ search: '', tags: [] });
+ });
+
+ it('should sync with URL search params if isUrlSyncEnabled', () => {
+ const searchParams = new URLSearchParams();
+ const setSearchParams = jest.fn();
+ const props: UseDataViewFiltersProps = {
+ initialFilters,
+ searchParams,
+ setSearchParams,
+ };
+
+ const { result } = renderHook(() => useDataViewFilters(props));
+ act(() => result.current.onSetFilters({ search: 'new search' }));
+
+ expect(setSearchParams).toHaveBeenCalled();
+ });
+
+ it('should reset filters to default values when clearAllFilters is called', () => {
+ const { result } = renderHook(() => useDataViewFilters({ initialFilters }));
+ act(() => result.current.clearAllFilters());
+
+ expect(result.current.filters).toEqual({ search: '', tags: [] });
+ });
+});
From bdd75fcc619d9739bad0bec45e320818cc3eab39 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Tue, 5 Nov 2024 00:31:01 +0100
Subject: [PATCH 09/23] feat(filters): Document DataView filters
---
.../examples/Components/Components.md | 4 +-
.../examples/Functionality/FiltersExample.tsx | 92 +++++++++++++++++++
.../examples/Functionality/Functionality.md | 37 +++++++-
3 files changed, 129 insertions(+), 4 deletions(-)
create mode 100644 packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md b/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
index ab240ed..628ecd3 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
@@ -11,7 +11,7 @@ source: react
# If you use typescript, the name of the interface to display props for
# These are found through the sourceProps function provided in patternfly-docs.source.js
sortValue: 4
-propComponents: ['DataViewToolbar', 'DataViewTableBasic', 'DataViewTableTree']
+propComponents: ['DataViewToolbar', 'DataViewTableBasic', 'DataViewTableTree', 'DataViewTrTree', 'DataViewTrObject']
sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/module/patternfly-docs/content/extensions/data-view/examples/Components/Components.md
---
import { Button, EmptyState, EmptyStateActions, EmptyStateBody, EmptyStateFooter } from '@patternfly/react-core';
@@ -26,7 +26,7 @@ import { DataView, DataViewState } from '@patternfly/react-data-view/dist/dynami
The **data view toolbar** component renders a default opinionated data view toolbar above or below the data section.
-Data view toolbar can contain a `pagination`, `bulkSelect`, `actions` or other children content passed. The preffered way of passing children toolbar items is using the [toolbar item](/components/toolbar#toolbar-items) component.
+Data view toolbar can contain a `pagination`, `bulkSelect`, `filters`, `actions` or other children content passed. The preffered way of passing children toolbar items is using the [toolbar item](/components/toolbar#toolbar-items) component.
### Basic toolbar example
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
new file mode 100644
index 0000000..46cec1e
--- /dev/null
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
@@ -0,0 +1,92 @@
+import React, { useMemo } from 'react';
+import { Pagination } from '@patternfly/react-core';
+import { BrowserRouter, useSearchParams } from 'react-router-dom';
+import { useDataViewFilters, useDataViewPagination } from '@patternfly/react-data-view/dist/dynamic/Hooks';
+import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
+import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
+import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
+import { DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters';
+import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
+
+const perPageOptions = [
+ { title: '5', value: 5 },
+ { title: '10', value: 10 }
+];
+
+interface Repository {
+ name: string;
+ branch: string | null;
+ prs: string | null;
+ workspaces: string;
+ lastCommit: string;
+}
+
+interface RepositoryFilters {
+ name: string,
+ branch: string
+}
+
+const repositories: Repository[] = [
+ { name: 'Repository one', branch: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
+ { name: 'Repository two', branch: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
+ { name: 'Repository three', branch: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
+ { name: 'Repository four', branch: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
+ { name: 'Repository five', branch: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
+ { name: 'Repository six', branch: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
+];
+
+const columns = [ 'Name', 'Branch', 'Pull requests', 'Workspaces', 'Last commit' ];
+
+const ouiaId = 'LayoutExample';
+
+const MyTable: React.FunctionComponent = () => {
+ const [ searchParams, setSearchParams ] = useSearchParams();
+ const pagination = useDataViewPagination({ perPage: 5 });
+ const { page, perPage } = pagination;
+ const { filters, onSetFilters, clearAllFilters } = useDataViewFilters({ initialFilters: { name: '', branch: '' }, searchParams, setSearchParams });
+
+ const pageRows = useMemo(() => repositories
+ .filter(item => (!filters.name || item.name?.toLocaleLowerCase().includes(filters.name?.toLocaleLowerCase())) && (!filters.branch || item.branch?.toLocaleLowerCase().includes(filters.branch?.toLocaleLowerCase())))
+ .slice((page - 1) * perPage, ((page - 1) * perPage) + perPage)
+ .map(item => Object.values(item)), [ page, perPage, filters ]);
+
+ return (
+
+
+ }
+ filters={
+ onSetFilters(values)} values={filters}>
+
+
+
+ }
+ />
+
+
+ }
+ />
+
+ );
+}
+
+export const BasicExample: React.FunctionComponent = () => (
+
+
+
+)
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
index c788309..1ec4901 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
@@ -11,16 +11,18 @@ source: react
# If you use typescript, the name of the interface to display props for
# These are found through the sourceProps function provided in patternfly-docs.source.js
sortValue: 3
+propComponents: ['DataViewFilters', 'DataViewTextFilter']
sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
---
import { useMemo } from 'react';
import { BrowserRouter, useSearchParams } from 'react-router-dom';
-import { useDataViewPagination, useDataViewSelection } from '@patternfly/react-data-view/dist/dynamic/Hooks';
+import { useDataViewPagination, useDataViewSelection, useDataViewFilters } from '@patternfly/react-data-view/dist/dynamic/Hooks';
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
import { BulkSelect, BulkSelectValue } from '@patternfly/react-component-groups/dist/dynamic/BulkSelect';
import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
-
+import { DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters';
+import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
This is a list of functionality you can use to manage data displayed in the **data view**.
@@ -83,3 +85,34 @@ The `useDataViewSelection` hook manages the selection state of the data view.
```js file="./SelectionExample.tsx"
```
+
+# Filters
+Enables filtering of data records in the data view and displays the applied filter chips.
+
+### Toolbar usage
+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.
+
+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.
+
+### Filters state
+
+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.
+
+**Initial values:**
+- `initialFilters` object with default filter values
+- optional `searchParams` object for managing URL-based filter state
+- optional `setSearchParams` function to update the URL when filters are modified
+
+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.
+
+**Return values:**
+- `filters` object representing the current filter values
+- `onSetFilters` function to update the filter state
+- `clearAllFilters` function to reset all filters to their initial values
+
+### Filtering example
+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.
+
+```js file="./FiltersExample.tsx"
+
+```
From bd99c199e8d2965fef7d0eb1e783a25e9834a7fc Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Tue, 5 Nov 2024 16:56:02 +0100
Subject: [PATCH 10/23] fix(filters): Support changing filters dynamically
---
packages/module/src/DataViewFilters/DataViewFilters.tsx | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/packages/module/src/DataViewFilters/DataViewFilters.tsx b/packages/module/src/DataViewFilters/DataViewFilters.tsx
index 1dc9958..29e950e 100644
--- a/packages/module/src/DataViewFilters/DataViewFilters.tsx
+++ b/packages/module/src/DataViewFilters/DataViewFilters.tsx
@@ -42,10 +42,16 @@ export const DataViewFilters = ({
const attributeMenuRef = useRef(null);
const attributeContainerRef = useRef(null);
+ const childrenHash = useMemo(() => JSON.stringify(
+ React.Children.map(children, (child) =>
+ React.isValidElement(child) ? { type: child.type, key: child.key, props: child.props } : child
+ )
+ ), [ children ]);
+
const filterItems: DataViewFilterIdentifiers[] = useMemo(() => React.Children.toArray(children)
.map(child =>
React.isValidElement(child) ? { filterId: String(child.props.filterId), title: String(child.props.title) } : undefined
- ).filter((item): item is DataViewFilterIdentifiers => !!item), []); // eslint-disable-line react-hooks/exhaustive-deps
+ ).filter((item): item is DataViewFilterIdentifiers => !!item), [ childrenHash ]); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => {
filterItems.length > 0 && setActiveAttributeMenu(filterItems[0].title);
From 2b4e9fca0fa3e754d91bae13750de9f053a91020 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Fri, 8 Nov 2024 20:34:24 +0100
Subject: [PATCH 11/23] fix: fix tree table data selection
---
.../DataViewTableTree/DataViewTableTree.tsx | 57 +++++++++++++------
1 file changed, 39 insertions(+), 18 deletions(-)
diff --git a/packages/module/src/DataViewTableTree/DataViewTableTree.tsx b/packages/module/src/DataViewTableTree/DataViewTableTree.tsx
index a743295..d4aaab8 100644
--- a/packages/module/src/DataViewTableTree/DataViewTableTree.tsx
+++ b/packages/module/src/DataViewTableTree/DataViewTableTree.tsx
@@ -12,24 +12,45 @@ import { DataViewTableHead } from '../DataViewTableHead';
import { DataViewTh, DataViewTrTree, isDataViewTdObject } from '../DataViewTable';
import { DataViewState } from '../DataView/DataView';
-const getDescendants = (node: DataViewTrTree): DataViewTrTree[] => (!node.children || !node.children.length) ? [ node ] : node.children.flatMap(getDescendants);
-
-const isNodeChecked = (node: DataViewTrTree, isSelected: (node: DataViewTrTree) => boolean) => {
- let allSelected = true;
- let someSelected = false;
-
- for (const descendant of getDescendants(node)) {
- const selected = !!isSelected?.(descendant);
-
- someSelected ||= selected;
- allSelected &&= selected;
-
- if (!allSelected && someSelected) { return null }
- }
-
- return allSelected;
+const getNodesAffectedBySelection = (
+ allRows: DataViewTrTree[],
+ node: DataViewTrTree,
+ isChecking: boolean,
+ isSelected?: (item: DataViewTrTree) => boolean
+): DataViewTrTree[] => {
+
+ const getDescendants = (node: DataViewTrTree): DataViewTrTree[] =>
+ node.children ? node.children.flatMap(getDescendants).concat(node) : [ node ];
+
+ const findParent = (child: DataViewTrTree, rows: DataViewTrTree[]): DataViewTrTree | undefined =>
+ rows.find(row => row.children?.some(c => c === child)) ??
+ rows.flatMap(row => row.children ?? []).map(c => findParent(child, [ c ])).find(p => p);
+
+ const getAncestors = (node: DataViewTrTree): DataViewTrTree[] => {
+ const ancestors: DataViewTrTree[] = [];
+ let parent = findParent(node, allRows);
+ while (parent) {
+ ancestors.push(parent);
+ parent = findParent(parent, allRows);
+ }
+ return ancestors;
+ };
+
+ const affectedNodes = new Set([ node, ...getDescendants(node) ]);
+
+ getAncestors(node).forEach(ancestor => {
+ const allChildrenSelected = ancestor.children?.every(child => isSelected?.(child) || affectedNodes.has(child));
+ const anyChildAffected = ancestor.children?.some(child => affectedNodes.has(child) || child.id === node.id);
+
+ if (isChecking ? !isSelected?.(ancestor) && allChildrenSelected : isSelected?.(ancestor) && anyChildAffected) {
+ affectedNodes.add(ancestor);
+ }
+ });
+
+ return Array.from(affectedNodes);
};
+
/** extends TableProps */
export interface DataViewTableTreeProps extends Omit {
/** Columns definition */
@@ -83,7 +104,7 @@ export const DataViewTableTree: React.FC = ({
}
const isExpanded = expandedNodeIds.includes(node.id);
const isDetailsExpanded = expandedDetailsNodeNames.includes(node.id);
- const isChecked = isSelected && isNodeChecked(node, isSelected);
+ const isChecked = isSelected?.(node);
let icon = leafIcon;
if (node.children) {
icon = isExpanded ? expandedIcon : collapsedIcon;
@@ -100,7 +121,7 @@ export const DataViewTableTree: React.FC = ({
const otherDetailsExpandedNodeIds = prevDetailsExpanded.filter(id => id !== node.id);
return isDetailsExpanded ? otherDetailsExpandedNodeIds : [ ...otherDetailsExpandedNodeIds, node.id ];
}),
- onCheckChange: (isSelectDisabled?.(node) || !onSelect) ? undefined : (_event, isChecking) => onSelect?.(isChecking, getDescendants(node)),
+ onCheckChange: (isSelectDisabled?.(node) || !onSelect) ? undefined : (_event, isChecking) => onSelect?.(isChecking, getNodesAffectedBySelection(rows, node, isChecking, isSelected)),
rowIndex,
props: {
isExpanded,
From f83558beea1ddcc7cf018813bc51aeef0d4b4a37 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Sat, 16 Nov 2024 21:51:09 +0100
Subject: [PATCH 12/23] fix: update hook for filters
---
packages/module/src/Hooks/filters.ts | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/packages/module/src/Hooks/filters.ts b/packages/module/src/Hooks/filters.ts
index 4f81e17..177e5f3 100644
--- a/packages/module/src/Hooks/filters.ts
+++ b/packages/module/src/Hooks/filters.ts
@@ -16,15 +16,19 @@ export const useDataViewFilters = ({
}: UseDataViewFiltersProps) => {
const isUrlSyncEnabled = useMemo(() => searchParams && !!setSearchParams, [ searchParams, setSearchParams ]);
- const getInitialFilters = useCallback((): T => isUrlSyncEnabled ? Object.keys(initialFilters).reduce((loadedFilters, key) => {
- const urlValue = searchParams?.get(key);
- loadedFilters[key as keyof T] = urlValue
- ? (urlValue as T[keyof T] | T[keyof T])
- : initialFilters[key as keyof T];
- return loadedFilters;
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, { ...initialFilters }) : initialFilters, [ isUrlSyncEnabled, JSON.stringify(initialFilters), searchParams?.toString() ]);
+ const getInitialFilters = useCallback((): T => isUrlSyncEnabled
+ ? Object.keys(initialFilters).reduce((loadedFilters, key) => {
+ const urlValue = searchParams?.get(key);
+ const isArrayFilter = Array.isArray(initialFilters[key]);
+ // eslint-disable-next-line no-nested-ternary
+ loadedFilters[key] = urlValue
+ ? (isArrayFilter && !Array.isArray(urlValue) ? [ urlValue ] : urlValue)
+ : initialFilters[key];
+
+ return loadedFilters;
+ }, { ...initialFilters })
+ : initialFilters, [ isUrlSyncEnabled, initialFilters, searchParams ]);
const [ filters, setFilters ] = useState(getInitialFilters());
const updateSearchParams = useCallback(
@@ -32,11 +36,8 @@ export const useDataViewFilters = ({
if (isUrlSyncEnabled) {
const params = new URLSearchParams(searchParams);
Object.entries(newFilters).forEach(([ key, value ]) => {
- if (value) {
- params.set(key, Array.isArray(value) ? value.join(',') : value);
- } else {
- params.delete(key);
- }
+ params.delete(key);
+ (Array.isArray(value) ? value : [ value ]).forEach((val) => value && params.append(key, val));
});
setSearchParams?.(params);
}
From db235556a58a52165e8caa920629ccdf6debc8fb Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Sat, 16 Nov 2024 21:51:51 +0100
Subject: [PATCH 13/23] fix: close filter dropdown after click outside
---
.../src/DataViewFilters/DataViewFilters.tsx | 33 +++++++++++++++----
.../DataViewTextFilter/DataViewTextFilter.tsx | 1 +
2 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/packages/module/src/DataViewFilters/DataViewFilters.tsx b/packages/module/src/DataViewFilters/DataViewFilters.tsx
index 29e950e..addc63f 100644
--- a/packages/module/src/DataViewFilters/DataViewFilters.tsx
+++ b/packages/module/src/DataViewFilters/DataViewFilters.tsx
@@ -1,9 +1,16 @@
-import React, { useMemo, useState, useRef, useEffect, ReactElement } from 'react';
+import React, { useMemo, useState, useRef, useEffect, ReactElement, ReactNode } from 'react';
import {
Menu, MenuContent, MenuItem, MenuList, MenuToggle, Popper, ToolbarGroup, ToolbarToggleGroup, ToolbarToggleGroupProps,
} from '@patternfly/react-core';
import { FilterIcon } from '@patternfly/react-icons';
+export interface DataViewFilterOption {
+ /** Filter option label */
+ label: ReactNode;
+ /** Filter option value */
+ value: string;
+}
+
// helper interface to generate attribute menu
interface DataViewFilterIdentifiers {
filterId: string;
@@ -57,6 +64,19 @@ export const DataViewFilters = ({
filterItems.length > 0 && setActiveAttributeMenu(filterItems[0].title);
}, [ filterItems ]);
+ const handleClickOutside = (event: MouseEvent) =>
+ isAttributeMenuOpen &&
+ !attributeMenuRef.current?.contains(event.target as Node) &&
+ !attributeToggleRef.current?.contains(event.target as Node)
+ && setIsAttributeMenuOpen(false);
+
+ useEffect(() => {
+ window.addEventListener('click', handleClickOutside);
+ return () => {
+ window.removeEventListener('click', handleClickOutside);
+ };
+ }, [ isAttributeMenuOpen ]); // eslint-disable-line react-hooks/exhaustive-deps
+
const attributeToggle = (
({
isVisible={isAttributeMenuOpen}
/>
- {React.Children.map(children, (child) => (
- React.isValidElement(child) ? (
- React.cloneElement(child as ReactElement<{
+ {React.Children.map(children, (child) =>
+ React.isValidElement(child)
+ ? React.cloneElement(child as ReactElement<{
showToolbarItem: boolean;
onChange: (_e: unknown, values: unknown) => void;
value: unknown;
@@ -114,9 +134,8 @@ export const DataViewFilters = ({
value: values?.[child.props.filterId],
...child.props
})
- ) : child
- ))}
-
+ : child
+ )}
);
diff --git a/packages/module/src/DataViewTextFilter/DataViewTextFilter.tsx b/packages/module/src/DataViewTextFilter/DataViewTextFilter.tsx
index e2d1e43..ce49a3d 100644
--- a/packages/module/src/DataViewTextFilter/DataViewTextFilter.tsx
+++ b/packages/module/src/DataViewTextFilter/DataViewTextFilter.tsx
@@ -31,6 +31,7 @@ export const DataViewTextFilter: React.FC = ({
...props
}: DataViewTextFilterProps) => (
0 ? [ { key: title, node: value } ] : []}
deleteChip={() => onChange?.(undefined, '')}
From 99a2f5c39ef3a74303225cec08c5126e95c21cc0 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Sat, 16 Nov 2024 21:52:11 +0100
Subject: [PATCH 14/23] feat: add checkbox filter
---
.../examples/Functionality/FiltersExample.tsx | 45 +++--
.../DataViewCheckboxFilter.tsx | 175 ++++++++++++++++++
.../src/DataViewCheckboxFilter/index.ts | 2 +
3 files changed, 207 insertions(+), 15 deletions(-)
create mode 100644 packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.tsx
create mode 100644 packages/module/src/DataViewCheckboxFilter/index.ts
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
index 46cec1e..14497a6 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
@@ -5,8 +5,9 @@ import { useDataViewFilters, useDataViewPagination } from '@patternfly/react-dat
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
-import { DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters';
+import { DataViewFilterOption, DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters';
import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
+import { DataViewCheckboxFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewCheckboxFilter';
const perPageOptions = [
{ title: '5', value: 5 },
@@ -17,38 +18,51 @@ interface Repository {
name: string;
branch: string | null;
prs: string | null;
- workspaces: string;
+ workspace: string;
lastCommit: string;
}
interface RepositoryFilters {
name: string,
- branch: string
+ branch: string,
+ workspace: string[]
}
const repositories: Repository[] = [
- { name: 'Repository one', branch: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
- { name: 'Repository two', branch: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
- { name: 'Repository three', branch: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
- { name: 'Repository four', branch: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
- { name: 'Repository five', branch: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
- { name: 'Repository six', branch: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
+ { name: 'Repository one', branch: 'Branch one', prs: 'Pull request one', workspace: 'Workspace one', lastCommit: 'Timestamp one' },
+ { name: 'Repository two', branch: 'Branch two', prs: 'Pull request two', workspace: 'Workspace two', lastCommit: 'Timestamp two' },
+ { name: 'Repository three', branch: 'Branch three', prs: 'Pull request three', workspace: 'Workspace one', lastCommit: 'Timestamp three' },
+ { name: 'Repository four', branch: 'Branch four', prs: 'Pull request four', workspace: 'Workspace one', lastCommit: 'Timestamp four' },
+ { name: 'Repository five', branch: 'Branch five', prs: 'Pull request five', workspace: 'Workspace two', lastCommit: 'Timestamp five' },
+ { name: 'Repository six', branch: 'Branch six', prs: 'Pull request six', workspace: 'Workspace three', lastCommit: 'Timestamp six' }
];
-const columns = [ 'Name', 'Branch', 'Pull requests', 'Workspaces', 'Last commit' ];
+const filterOptions: DataViewFilterOption[] = [
+ { label: 'Workspace one', value: 'workspace-one' },
+ { label: 'Workspace two', value: 'workspace-two' },
+ { label: 'Workspace three', value: 'workspace-three' }
+];
+
+const columns = [ 'Name', 'Branch', 'Pull requests', 'Workspace', 'Last commit' ];
const ouiaId = 'LayoutExample';
const MyTable: React.FunctionComponent = () => {
const [ searchParams, setSearchParams ] = useSearchParams();
+ const { filters, onSetFilters, clearAllFilters } = useDataViewFilters({ initialFilters: { name: '', branch: '', workspace: [] }, searchParams, setSearchParams });
const pagination = useDataViewPagination({ perPage: 5 });
const { page, perPage } = pagination;
- const { filters, onSetFilters, clearAllFilters } = useDataViewFilters({ initialFilters: { name: '', branch: '' }, searchParams, setSearchParams });
- const pageRows = useMemo(() => repositories
- .filter(item => (!filters.name || item.name?.toLocaleLowerCase().includes(filters.name?.toLocaleLowerCase())) && (!filters.branch || item.branch?.toLocaleLowerCase().includes(filters.branch?.toLocaleLowerCase())))
+ const filteredData = useMemo(() => repositories.filter(item =>
+ (!filters.name || item.name?.toLocaleLowerCase().includes(filters.name?.toLocaleLowerCase())) &&
+ (!filters.branch || item.branch?.toLocaleLowerCase().includes(filters.branch?.toLocaleLowerCase())) &&
+ (!filters.workspace || filters.workspace.length === 0 || filters.workspace.includes(String(filterOptions.find(option => option.label === item.workspace)?.value)))
+ ), [ filters ]);
+
+ const pageRows = useMemo(() => filteredData
.slice((page - 1) * perPage, ((page - 1) * perPage) + perPage)
- .map(item => Object.values(item)), [ page, perPage, filters ]);
+ .map(item => Object.values(item)),
+ [ page, perPage, filteredData ]);
return (
@@ -66,6 +80,7 @@ const MyTable: React.FunctionComponent = () => {
onSetFilters(values)} values={filters}>
+
}
/>
@@ -76,7 +91,7 @@ const MyTable: React.FunctionComponent = () => {
}
diff --git a/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.tsx b/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.tsx
new file mode 100644
index 0000000..7235165
--- /dev/null
+++ b/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.tsx
@@ -0,0 +1,175 @@
+import React from 'react';
+import {
+ Badge,
+ Menu,
+ MenuContent,
+ MenuItem,
+ MenuList,
+ MenuProps,
+ MenuToggle,
+ Popper,
+ ToolbarChip,
+ ToolbarFilter,
+} from '@patternfly/react-core';
+import { FilterIcon } from '@patternfly/react-icons';
+import { DataViewFilterOption } from '../DataViewFilters';
+
+const isToolbarChip = (chip: string | ToolbarChip): chip is ToolbarChip =>
+ typeof chip === 'object' && 'key' in chip;
+
+export const isDataViewFilterOption = (obj: unknown): obj is DataViewFilterOption =>
+ !!obj &&
+ typeof obj === 'object' &&
+ 'label' in obj &&
+ 'value' in obj &&
+ typeof (obj as DataViewFilterOption).value === 'string';
+
+/** extends MenuProps */
+export interface DataViewCheckboxFilterProps extends Omit {
+ /** Unique key for the filter attribute */
+ filterId: string;
+ /** Array of current filter values */
+ value?: string[];
+ /** Filter title displayed in the toolbar */
+ title: string;
+ /** Placeholder text of the menu */
+ placeholder?: string;
+ /** Filter options displayed */
+ options: (DataViewFilterOption | string)[];
+ /** Callback for updating when item selection changes. */
+ onChange?: (event?: React.MouseEvent, values?: string[]) => void;
+ /** Controls visibility of the filter in the toolbar */
+ showToolbarItem?: boolean;
+ /** Controls visibility of the filter icon */
+ showIcon?: boolean;
+ /** Controls visibility of the selected items badge */
+ showBadge?: boolean;
+ /** Custom OUIA ID */
+ ouiaId?: string;
+}
+
+export const DataViewCheckboxFilter: React.FC = ({
+ filterId,
+ title,
+ value = [],
+ onChange,
+ placeholder,
+ options = [],
+ showToolbarItem,
+ showIcon = !placeholder,
+ showBadge = !placeholder,
+ ouiaId = 'DataViewCheckboxFilter',
+ ...props
+}: DataViewCheckboxFilterProps) => {
+ const [ isOpen, setIsOpen ] = React.useState(false);
+ const toggleRef = React.useRef(null);
+ const menuRef = React.useRef(null);
+ const containerRef = React.useRef(null);
+
+ const normalizeOptions = React.useMemo(
+ () =>
+ options.map(option =>
+ typeof option === 'string'
+ ? { label: option, value: option }
+ : option
+ ),
+ [ options ]
+ );
+
+ const handleToggleClick = (event: React.MouseEvent) => {
+ event.stopPropagation();
+ setTimeout(() => {
+ const firstElement = menuRef.current?.querySelector('li > button:not(:disabled)') as HTMLElement;
+ firstElement?.focus();
+ }, 0);
+ setIsOpen(prev => !prev);
+ };
+
+ const handleSelect = (event?: React.MouseEvent, itemId?: string | number) => {
+ const activeItem = String(itemId);
+ const isSelected = value.includes(activeItem);
+
+ onChange?.(
+ event,
+ isSelected ? value.filter(item => item !== activeItem) : [ activeItem, ...value ]
+ );
+ };
+
+ const handleClickOutside = (event: MouseEvent) =>
+ isOpen &&
+ menuRef.current && toggleRef.current &&
+ !menuRef.current.contains(event.target as Node) && !toggleRef.current.contains(event.target as Node)
+ && setIsOpen(false);
+
+
+ React.useEffect(() => {
+ window.addEventListener('click', handleClickOutside);
+ return () => {
+ window.removeEventListener('click', handleClickOutside);
+ };
+ }, [ isOpen ]); // eslint-disable-line react-hooks/exhaustive-deps
+
+ return (
+ {
+ const activeOption = normalizeOptions.find(option => option.value === item);
+ return ({ key: activeOption?.value as string, node: activeOption?.label })
+ })}
+ deleteChip={(_, chip) =>
+ onChange?.(undefined, value.filter(item => item !== (isToolbarChip(chip) ? chip.key : chip)))
+ }
+ categoryName={title}
+ showToolbarItem={showToolbarItem}
+ >
+ : undefined}
+ badge={value.length > 0 && showBadge ? {value.length} : undefined}
+ style={{ width: '200px' }}
+ >
+ {placeholder ?? title}
+
+ }
+ triggerRef={toggleRef}
+ popper={
+
+
+
+ {normalizeOptions.map(option => (
+
+ {option.label}
+
+ ))}
+
+
+
+ }
+ popperRef={menuRef}
+ appendTo={containerRef.current || undefined}
+ aria-label={`${title ?? filterId} filter`}
+ isVisible={isOpen}
+ />
+
+ );
+};
+
+export default DataViewCheckboxFilter;
diff --git a/packages/module/src/DataViewCheckboxFilter/index.ts b/packages/module/src/DataViewCheckboxFilter/index.ts
new file mode 100644
index 0000000..218b16f
--- /dev/null
+++ b/packages/module/src/DataViewCheckboxFilter/index.ts
@@ -0,0 +1,2 @@
+export { default } from './DataViewCheckboxFilter';
+export * from './DataViewCheckboxFilter';
From c19beddd9a6655db67d87c285f02cfb9818d8358 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Sat, 16 Nov 2024 21:52:44 +0100
Subject: [PATCH 15/23] feat: enhance documentation with checkbox filter
---
.../data-view/examples/Functionality/Functionality.md | 7 ++++---
packages/module/src/index.ts | 3 +++
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
index 1ec4901..05dcebd 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
@@ -11,7 +11,7 @@ source: react
# If you use typescript, the name of the interface to display props for
# These are found through the sourceProps function provided in patternfly-docs.source.js
sortValue: 3
-propComponents: ['DataViewFilters', 'DataViewTextFilter']
+propComponents: ['DataViewFilters', 'DataViewTextFilter', 'DataViewCheckboxFilter']
sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
---
import { useMemo } from 'react';
@@ -23,6 +23,7 @@ import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataVi
import { DataViewTable } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
import { DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters';
import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
+import { DataViewCheckboxFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewCheckboxFilter';
This is a list of functionality you can use to manage data displayed in the **data view**.
@@ -90,7 +91,7 @@ The `useDataViewSelection` hook manages the selection state of the data view.
Enables filtering of data records in the data view and displays the applied filter chips.
### Toolbar usage
-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.
+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`, `DataViewTextFilter` and `DataViewCheckboxFilter` 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`, `DataViewCheckboxFilter` or a different filter component alone. Props of these filter components are listed at the bottom of this page.
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.
@@ -99,7 +100,7 @@ You can decide between passing `value` and `onChange` event to every filter sepa
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.
**Initial values:**
-- `initialFilters` object with default filter values
+- `initialFilters` object with default filter values (if the filter param allows multiple values, pass an array)
- optional `searchParams` object for managing URL-based filter state
- optional `setSearchParams` function to update the URL when filters are modified
diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts
index a34586c..aca7f76 100644
--- a/packages/module/src/index.ts
+++ b/packages/module/src/index.ts
@@ -25,5 +25,8 @@ export * from './DataViewTable';
export { default as DataViewEventsContext } from './DataViewEventsContext';
export * from './DataViewEventsContext';
+export { default as DataViewCheckboxFilter } from './DataViewCheckboxFilter';
+export * from './DataViewCheckboxFilter';
+
export { default as DataView } from './DataView';
export * from './DataView';
From 9e73530fb8efc49499754f803192946b5ff79157 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Sat, 16 Nov 2024 21:53:02 +0100
Subject: [PATCH 16/23] feat: add tests for checkbox filter
---
.../component/DataViewCheckboxFilter.cy.tsx | 66 ++++++
.../DataViewCheckboxFilter.test.tsx | 24 +++
.../DataViewCheckboxFilter.test.tsx.snap | 194 ++++++++++++++++++
3 files changed, 284 insertions(+)
create mode 100644 cypress/component/DataViewCheckboxFilter.cy.tsx
create mode 100644 packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.test.tsx
create mode 100644 packages/module/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap
diff --git a/cypress/component/DataViewCheckboxFilter.cy.tsx b/cypress/component/DataViewCheckboxFilter.cy.tsx
new file mode 100644
index 0000000..eab26fb
--- /dev/null
+++ b/cypress/component/DataViewCheckboxFilter.cy.tsx
@@ -0,0 +1,66 @@
+import React from 'react';
+import { DataViewCheckboxFilter, DataViewCheckboxFilterProps } from '@patternfly/react-data-view/dist/dynamic/DataViewCheckboxFilter';
+import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
+
+describe('DataViewCheckboxFilter component', () => {
+ const defaultProps: DataViewCheckboxFilterProps = {
+ filterId: 'test-checkbox-filter',
+ title: 'Test checkbox filter',
+ value: [ 'workspace-one' ],
+ options: [
+ { label: 'Workspace one', value: 'workspace-one' },
+ { label: 'Workspace two', value: 'workspace-two' },
+ { label: 'Workspace three', value: 'workspace-three' },
+ ],
+ };
+
+ it('renders a checkbox filter with options', () => {
+ const onChange = cy.stub().as('onChange');
+
+ cy.mount(
+ } />
+ );
+
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-toggle"]')
+ .contains('Test checkbox filter')
+ .should('be.visible');
+
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-badge"]')
+ .should('exist')
+ .contains('1');
+
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-toggle"]').click();
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-menu"]').should('be.visible');
+
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-menu"]')
+ .find('li')
+ .should('have.length', 3)
+ .first()
+ .contains('Workspace one');
+
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-menu"]')
+ .find('li')
+ .first()
+ .find('input[type="checkbox"]')
+ .should('be.checked');
+
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-menu"]')
+ .find('li')
+ .eq(1)
+ .find('input[type="checkbox"]')
+ .click();
+
+ cy.get('@onChange').should('have.been.calledWith', Cypress.sinon.match.object, [ 'workspace-two', 'workspace-one' ]);
+ });
+
+ it('renders a checkbox filter with no options selected', () => {
+ const emptyProps = { ...defaultProps, value: [] };
+
+ cy.mount(
+ } />
+ );
+
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-toggle"]').contains('Test checkbox filter');
+ cy.get('[data-ouia-component-id="DataViewCheckboxFilter-badge"]').should('not.exist');
+ });
+});
diff --git a/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.test.tsx b/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.test.tsx
new file mode 100644
index 0000000..2290651
--- /dev/null
+++ b/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.test.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import DataViewCheckboxFilter, { DataViewCheckboxFilterProps } from './DataViewCheckboxFilter';
+import DataViewToolbar from '../DataViewToolbar';
+
+describe('DataViewCheckboxFilter component', () => {
+ const defaultProps: DataViewCheckboxFilterProps = {
+ filterId: 'test-checkbox-filter',
+ title: 'Test Checkbox Filter',
+ value: [ 'workspace-one' ],
+ options: [
+ { label: 'Workspace one', value: 'workspace-one' },
+ { label: 'Workspace two', value: 'workspace-two' },
+ { label: 'Workspace three', value: 'workspace-three' },
+ ],
+ };
+
+ it('should render correctly', () => {
+ const { container } = render(
+ } />
+ );
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/packages/module/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap b/packages/module/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap
new file mode 100644
index 0000000..e6cede5
--- /dev/null
+++ b/packages/module/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap
@@ -0,0 +1,194 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DataViewCheckboxFilter component should render correctly 1`] = `
+
+`;
From 8a31667d57f933b9d507a72b06c3d8d08a5ab890 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Sat, 16 Nov 2024 21:58:30 +0100
Subject: [PATCH 17/23] fix: fix pagination in filtering example
---
.../data-view/examples/Functionality/FiltersExample.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
index 14497a6..afdbcac 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/FiltersExample.tsx
@@ -72,7 +72,7 @@ const MyTable: React.FunctionComponent = () => {
pagination={
}
From fe4882fa75e1382c79e20d1354a44a183aac34ae Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Wed, 20 Nov 2024 18:06:52 +0100
Subject: [PATCH 18/23] feat: add helper hook for sorting
---
packages/module/src/Hooks/index.ts | 1 +
packages/module/src/Hooks/sort.ts | 87 ++++++++++++++++++++++++++++++
2 files changed, 88 insertions(+)
create mode 100644 packages/module/src/Hooks/sort.ts
diff --git a/packages/module/src/Hooks/index.ts b/packages/module/src/Hooks/index.ts
index 546a0da..3ce609c 100644
--- a/packages/module/src/Hooks/index.ts
+++ b/packages/module/src/Hooks/index.ts
@@ -1,3 +1,4 @@
export * from './pagination';
export * from './selection';
export * from './filters';
+export * from './sort';
diff --git a/packages/module/src/Hooks/sort.ts b/packages/module/src/Hooks/sort.ts
new file mode 100644
index 0000000..ed06f22
--- /dev/null
+++ b/packages/module/src/Hooks/sort.ts
@@ -0,0 +1,87 @@
+import { ISortBy } from "@patternfly/react-table";
+import { useState, useEffect, useMemo } from "react";
+
+export enum DataViewSortParams {
+ SORT_BY = 'sortBy',
+ DIRECTION = 'direction'
+};
+
+const validateDirection = (direction: string | null | undefined, defaultDirection: ISortBy['direction']): ISortBy['direction'] => (
+ direction === 'asc' || direction === 'desc' ? direction : defaultDirection
+);
+
+export interface DataViewSortConfig {
+ /** Attribute to sort the entries by */
+ sortBy: string | undefined;
+ /** Sort direction */
+ direction: ISortBy['direction'];
+};
+
+export interface UseDataViewSortProps {
+ /** Initial sort config */
+ initialSort?: DataViewSortConfig;
+ /** Current search parameters as a string */
+ searchParams?: URLSearchParams;
+ /** Function to set search parameters */
+ setSearchParams?: (params: URLSearchParams) => void;
+ /** Default direction */
+ defaultDirection?: ISortBy['direction'];
+ /** Sort by URL param name */
+ sortByParam?: string;
+ /** Direction URL param name */
+ directionParam?: string;
+};
+
+export const useDataViewSort = (props?: UseDataViewSortProps) => {
+ const {
+ initialSort,
+ searchParams,
+ setSearchParams,
+ defaultDirection = 'asc',
+ sortByParam = DataViewSortParams.SORT_BY,
+ directionParam = DataViewSortParams.DIRECTION
+ } = props ?? {};
+
+ const isUrlSyncEnabled = useMemo(() => searchParams && !!setSearchParams, [ searchParams, setSearchParams ]);
+
+ const [ state, setState ] = useState({
+ sortBy: searchParams?.get(sortByParam) ?? initialSort?.sortBy,
+ direction: validateDirection(searchParams?.get(directionParam) as ISortBy['direction'], initialSort?.direction),
+ });
+
+ const updateSearchParams = (sortBy: string, direction: ISortBy['direction']) => {
+ if (isUrlSyncEnabled && sortBy) {
+ const params = new URLSearchParams(searchParams);
+ params.set(sortByParam, `${sortBy}`);
+ params.set(directionParam, `${direction}`);
+ setSearchParams?.(params);
+ }
+ };
+
+ useEffect(() => {
+ state.sortBy && state.direction && updateSearchParams(state.sortBy, state.direction);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ useEffect(() => {
+ const currentSortBy = searchParams?.get(sortByParam) || state.sortBy;
+ const currentDirection = searchParams?.get(directionParam) as ISortBy['direction'] || state.direction;
+ const validDirection = validateDirection(currentDirection, defaultDirection);
+ currentSortBy !== state.sortBy || validDirection !== state.direction && setState({ sortBy: currentSortBy, direction: validDirection });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [ searchParams?.toString() ]);
+
+ const onSort = (
+ _event: React.MouseEvent | React.KeyboardEvent | MouseEvent | undefined,
+ newSortBy: string,
+ newSortDirection: ISortBy['direction']
+ ) => {
+ setState({ sortBy: newSortBy, direction: newSortDirection });
+ updateSearchParams(newSortBy, newSortDirection);
+ };
+
+ return {
+ ...state,
+ onSort
+ };
+};
From c6a8cc56e024a71f7c762fc711a7a2e3aed94f5d Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Wed, 20 Nov 2024 18:07:20 +0100
Subject: [PATCH 19/23] feat: add example and docs for sorting hook
---
.../examples/Functionality/Functionality.md | 33 ++++++-
.../examples/Functionality/SortingExample.tsx | 87 +++++++++++++++++++
2 files changed, 119 insertions(+), 1 deletion(-)
create mode 100644 packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/SortingExample.tsx
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
index 05dcebd..066c0e1 100644
--- a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/Functionality.md
@@ -16,7 +16,7 @@ sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/mod
---
import { useMemo } from 'react';
import { BrowserRouter, useSearchParams } from 'react-router-dom';
-import { useDataViewPagination, useDataViewSelection, useDataViewFilters } from '@patternfly/react-data-view/dist/dynamic/Hooks';
+import { useDataViewPagination, useDataViewSelection, useDataViewFilters, useDataViewSort } from '@patternfly/react-data-view/dist/dynamic/Hooks';
import { DataView } from '@patternfly/react-data-view/dist/dynamic/DataView';
import { BulkSelect, BulkSelectValue } from '@patternfly/react-component-groups/dist/dynamic/BulkSelect';
import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
@@ -117,3 +117,34 @@ This example demonstrates the setup and usage of filters within the data view. I
```js file="./FiltersExample.tsx"
```
+
+### Sort state
+
+The `useDataViewSort` hook manages the sorting state of a data view. It provides an easy way to handle sorting logic, including synchronization with URL parameters and defining default sorting behavior.
+
+**Initial values:**
+- `initialSort` object to set default `sortBy` and `direction` values:
+ - `sortBy`: key of the initial column to sort.
+ - `direction`: default sorting direction (`asc` or `desc`).
+- Optional `searchParams` object to manage URL-based synchronization of sort state.
+- Optional `setSearchParams` function to update the URL parameters when sorting changes.
+- `defaultDirection` to set the default direction when no direction is specified.
+- Customizable parameter names for the URL:
+ - `sortByParam`: name of the URL parameter for the column key.
+ - `directionParam`: name of the URL parameter for the sorting direction.
+
+The `useDataViewSort` hook integrates seamlessly with React Router to manage sort state via URL parameters. Alternatively, you can use `URLSearchParams` and `window.history.pushState` APIs, or other routing libraries. If URL synchronization is not configured, the sort state is managed internally within the component.
+
+**Return values:**
+- `sortBy`: key of the column currently being sorted.
+- `direction`: current sorting direction (`asc` or `desc`).
+- `onSort`: function to handle sorting changes programmatically or via user interaction.
+
+### Sorting example
+
+This example demonstrates how to set up and use sorting functionality within a data view. The implementation includes dynamic sorting by column with persistence of sort state in the URL using React Router.
+
+
+```js file="./SortingExample.tsx"
+
+```
diff --git a/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/SortingExample.tsx b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/SortingExample.tsx
new file mode 100644
index 0000000..879f1cd
--- /dev/null
+++ b/packages/module/patternfly-docs/content/extensions/data-view/examples/Functionality/SortingExample.tsx
@@ -0,0 +1,87 @@
+/* eslint-disable no-nested-ternary */
+import React, { useMemo } from 'react';
+import { useDataViewSort } from '@patternfly/react-data-view/dist/dynamic/Hooks';
+import { DataViewTable, DataViewTr, DataViewTh } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
+import { ThProps } from '@patternfly/react-table';
+import { BrowserRouter, useSearchParams } from 'react-router-dom';
+
+interface Repository {
+ name: string;
+ branches: string;
+ prs: string;
+ workspaces: string;
+ lastCommit: string;
+};
+
+const COLUMNS = [
+ { label: 'Repository', key: 'name', index: 0 },
+ { label: 'Branch', key: 'branches', index: 1 },
+ { label: 'Pull request', key: 'prs', index: 2 },
+ { label: 'Workspace', key: 'workspaces', index: 3 },
+ { label: 'Last commit', key: 'lastCommit', index: 4 }
+];
+
+const repositories: Repository[] = [
+ { name: 'Repository one', branches: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: 'Timestamp one' },
+ { name: 'Repository two', branches: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: 'Timestamp two' },
+ { name: 'Repository three', branches: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: 'Timestamp three' },
+ { name: 'Repository four', branches: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: 'Timestamp four' },
+ { name: 'Repository five', branches: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: 'Timestamp five' },
+ { name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: 'Timestamp six' }
+];
+
+const sortData = (data: Repository[], sortBy: string | undefined, direction: 'asc' | 'desc' | undefined) =>
+ sortBy && direction
+ ? [ ...data ].sort((a, b) =>
+ direction === 'asc'
+ ? a[sortBy] < b[sortBy] ? -1 : a[sortBy] > b[sortBy] ? 1 : 0
+ : a[sortBy] > b[sortBy] ? -1 : a[sortBy] < b[sortBy] ? 1 : 0
+ )
+ : data;
+
+const ouiaId = 'TableExample';
+
+export const MyTable: React.FunctionComponent = () => {
+ const [ searchParams, setSearchParams ] = useSearchParams();
+ const { sortBy, direction, onSort } = useDataViewSort({ searchParams, setSearchParams });
+ const sortByIndex = useMemo(() => COLUMNS.findIndex(item => item.key === sortBy), [ sortBy ]);
+
+ const getSortParams = (columnIndex: number): ThProps['sort'] => ({
+ sortBy: {
+ index: sortByIndex,
+ direction,
+ defaultDirection: 'asc'
+ },
+ onSort: (_event, index, direction) => onSort(_event, COLUMNS[index].key, direction),
+ columnIndex
+ });
+
+ const columns: DataViewTh[] = COLUMNS.map((column, index) => ({
+ cell: column.label,
+ props: { sort: getSortParams(index) }
+ }));
+
+ const rows: DataViewTr[] = useMemo(() => sortData(repositories, sortBy, direction).map(({ name, branches, prs, workspaces, lastCommit }) => [
+ name,
+ branches,
+ prs,
+ workspaces,
+ lastCommit,
+ ]), [ sortBy, direction ]);
+
+ return (
+
+ );
+};
+
+export const BasicExample: React.FunctionComponent = () => (
+
+
+
+)
+
From 6f95550542edaa3c009908dca2b00a12cd6e9126 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Wed, 20 Nov 2024 18:08:30 +0100
Subject: [PATCH 20/23] feat: add unit and component tests for sorting
---
cypress/component/DataViewTableSorting.cy.tsx | 109 ++++++++++++++++++
packages/module/src/Hooks/sort.test.tsx | 84 ++++++++++++++
2 files changed, 193 insertions(+)
create mode 100644 cypress/component/DataViewTableSorting.cy.tsx
create mode 100644 packages/module/src/Hooks/sort.test.tsx
diff --git a/cypress/component/DataViewTableSorting.cy.tsx b/cypress/component/DataViewTableSorting.cy.tsx
new file mode 100644
index 0000000..4b27d3e
--- /dev/null
+++ b/cypress/component/DataViewTableSorting.cy.tsx
@@ -0,0 +1,109 @@
+/* eslint-disable no-nested-ternary */
+import React from 'react';
+import { useDataViewSort } from '@patternfly/react-data-view/dist/dynamic/Hooks';
+import { DataViewTable, DataViewTr, DataViewTh } from '@patternfly/react-data-view/dist/dynamic/DataViewTable';
+import { BrowserRouter, useSearchParams } from 'react-router-dom';
+import { ThProps } from '@patternfly/react-table';
+
+interface Repository {
+ name: string;
+ branches: string;
+ prs: string;
+ workspaces: string;
+ lastCommit: string;
+}
+
+const COLUMNS = [
+ { label: 'Repository', key: 'name', index: 0 },
+ { label: 'Branch', key: 'branches', index: 1 },
+ { label: 'Pull request', key: 'prs', index: 2 },
+ { label: 'Workspace', key: 'workspaces', index: 3 },
+ { label: 'Last commit', key: 'lastCommit', index: 4 },
+];
+
+const repositories: Repository[] = [
+ { name: 'Repository one', branches: 'Branch one', prs: 'Pull request one', workspaces: 'Workspace one', lastCommit: '2023-11-01' },
+ { name: 'Repository six', branches: 'Branch six', prs: 'Pull request six', workspaces: 'Workspace six', lastCommit: '2023-11-06' },
+ { name: 'Repository two', branches: 'Branch two', prs: 'Pull request two', workspaces: 'Workspace two', lastCommit: '2023-11-02' },
+ { name: 'Repository five', branches: 'Branch five', prs: 'Pull request five', workspaces: 'Workspace five', lastCommit: '2023-11-05' },
+ { name: 'Repository three', branches: 'Branch three', prs: 'Pull request three', workspaces: 'Workspace three', lastCommit: '2023-11-03' },
+ { name: 'Repository four', branches: 'Branch four', prs: 'Pull request four', workspaces: 'Workspace four', lastCommit: '2023-11-04' },
+];
+
+const sortData = (data: Repository[], sortBy: keyof Repository | undefined, direction: 'asc' | 'desc' | undefined) =>
+ sortBy && direction
+ ? [ ...data ].sort((a, b) =>
+ direction === 'asc'
+ ? a[sortBy] < b[sortBy] ? -1 : a[sortBy] > b[sortBy] ? 1 : 0
+ : a[sortBy] > b[sortBy] ? -1 : a[sortBy] < b[sortBy] ? 1 : 0
+ )
+ : data;
+
+const TestableTable: React.FunctionComponent = () => {
+ const [ searchParams, setSearchParams ] = useSearchParams();
+ const { sortBy, direction, onSort } = useDataViewSort({ searchParams, setSearchParams });
+ const sortByIndex = React.useMemo(() => COLUMNS.findIndex(item => item.key === sortBy), [ sortBy ]);
+
+ const getSortParams = (columnIndex: number): ThProps['sort'] => ({
+ sortBy: {
+ index: sortByIndex,
+ direction,
+ defaultDirection: 'asc',
+ },
+ onSort: (_event, index, direction) => onSort(_event, COLUMNS[index].key, direction),
+ columnIndex,
+ });
+
+ const columns: DataViewTh[] = COLUMNS.map((column, index) => ({
+ cell: column.label,
+ props: { sort: getSortParams(index) },
+ }));
+
+ const rows: DataViewTr[] = React.useMemo(
+ () =>
+ sortData(repositories, sortBy ? sortBy as keyof Repository : undefined, direction).map(({ name, branches, prs, workspaces, lastCommit }) => [
+ name,
+ branches,
+ prs,
+ workspaces,
+ lastCommit,
+ ]),
+ [ sortBy, direction ]
+ );
+
+ return ;
+};
+
+describe('DataViewTable Sorting with Hook', () => {
+ it('sorts by repository name in ascending and descending order', () => {
+ cy.mount(
+
+
+
+ );
+
+ cy.get('[data-ouia-component-id="test-table-th-0"]').click();
+ cy.get('[data-ouia-component-id="test-table-td-0-0"]').should('contain', 'Repository five');
+ cy.get('[data-ouia-component-id="test-table-td-5-0"]').should('contain', 'Repository two');
+
+ cy.get('[data-ouia-component-id="test-table-th-0"]').click();
+ cy.get('[data-ouia-component-id="test-table-td-0-0"]').should('contain', 'Repository two');
+ cy.get('[data-ouia-component-id="test-table-td-5-0"]').should('contain', 'Repository five');
+ });
+
+ it('sorts by last commit date in ascending and descending order', () => {
+ cy.mount(
+
+
+
+ );
+
+ cy.get('[data-ouia-component-id="test-table-th-4"]').click();
+ cy.get('[data-ouia-component-id="test-table-td-0-4"]').should('contain', '2023-11-01');
+ cy.get('[data-ouia-component-id="test-table-td-5-4"]').should('contain', '2023-11-06');
+
+ cy.get('[data-ouia-component-id="test-table-th-4"]').click();
+ cy.get('[data-ouia-component-id="test-table-td-0-4"]').should('contain', '2023-11-06');
+ cy.get('[data-ouia-component-id="test-table-td-5-4"]').should('contain', '2023-11-01');
+ });
+});
diff --git a/packages/module/src/Hooks/sort.test.tsx b/packages/module/src/Hooks/sort.test.tsx
new file mode 100644
index 0000000..473924d
--- /dev/null
+++ b/packages/module/src/Hooks/sort.test.tsx
@@ -0,0 +1,84 @@
+import '@testing-library/jest-dom';
+import { renderHook, act } from '@testing-library/react';
+import { useDataViewSort, UseDataViewSortProps, DataViewSortConfig, DataViewSortParams } from './sort';
+
+describe('useDataViewSort', () => {
+ const initialSort: DataViewSortConfig = { sortBy: 'name', direction: 'asc' };
+
+ it('should initialize with provided initial sort config', () => {
+ const { result } = renderHook(() => useDataViewSort({ initialSort }));
+ expect(result.current).toEqual(expect.objectContaining(initialSort));
+ });
+
+ it('should initialize with empty sort config if no initialSort is provided', () => {
+ const { result } = renderHook(() => useDataViewSort());
+ expect(result.current).toEqual(expect.objectContaining({ sortBy: undefined, direction: 'asc' }));
+ });
+
+ it('should update sort state when onSort is called', () => {
+ const { result } = renderHook(() => useDataViewSort({ initialSort }));
+ act(() => {
+ result.current.onSort(undefined, 'age', 'desc');
+ });
+ expect(result.current).toEqual(expect.objectContaining({ sortBy: 'age', direction: 'desc' }));
+ });
+
+ it('should sync with URL search params if isUrlSyncEnabled', () => {
+ const searchParams = new URLSearchParams();
+ const setSearchParams = jest.fn();
+ const props: UseDataViewSortProps = {
+ initialSort,
+ searchParams,
+ setSearchParams,
+ };
+
+ const { result } = renderHook(() => useDataViewSort(props));
+
+ expect(setSearchParams).toHaveBeenCalledTimes(1);
+ expect(result.current).toEqual(expect.objectContaining(initialSort));
+ });
+
+ it('should validate direction and fallback to default direction if invalid direction is provided', () => {
+ const searchParams = new URLSearchParams();
+ searchParams.set(DataViewSortParams.SORT_BY, 'name');
+ searchParams.set(DataViewSortParams.DIRECTION, 'invalid-direction');
+ const { result } = renderHook(() => useDataViewSort({ searchParams, defaultDirection: 'desc' }));
+
+ expect(result.current).toEqual(expect.objectContaining({ sortBy: 'name', direction: 'desc' }));
+ });
+
+ it('should update search params when URL sync is enabled and sort changes', () => {
+ const searchParams = new URLSearchParams();
+ const setSearchParams = jest.fn();
+ const props: UseDataViewSortProps = {
+ initialSort,
+ searchParams,
+ setSearchParams,
+ };
+
+ const { result } = renderHook(() => useDataViewSort(props));
+ act(() => {
+ expect(setSearchParams).toHaveBeenCalledTimes(1);
+ result.current.onSort(undefined, 'priority', 'desc');
+ });
+
+ expect(setSearchParams).toHaveBeenCalledTimes(2);
+ expect(result.current).toEqual(expect.objectContaining({ sortBy: 'priority', direction: 'desc' }));
+ });
+
+ it('should prioritize searchParams values', () => {
+ const searchParams = new URLSearchParams();
+ searchParams.set(DataViewSortParams.SORT_BY, 'category');
+ searchParams.set(DataViewSortParams.DIRECTION, 'desc');
+
+ const { result } = renderHook(
+ (props: UseDataViewSortProps) => useDataViewSort(props),
+ { initialProps: { initialSort, searchParams } }
+ );
+
+ expect(result.current).toEqual(expect.objectContaining({
+ sortBy: 'category',
+ direction: 'desc',
+ }));
+ });
+});
From 8de74b498374ee72023cfd7ebe9acb4f7ae6baf0 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Wed, 20 Nov 2024 18:10:40 +0100
Subject: [PATCH 21/23] fix: clean the code
---
cypress/component/DataViewTableSorting.cy.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cypress/component/DataViewTableSorting.cy.tsx b/cypress/component/DataViewTableSorting.cy.tsx
index 4b27d3e..79cae0f 100644
--- a/cypress/component/DataViewTableSorting.cy.tsx
+++ b/cypress/component/DataViewTableSorting.cy.tsx
@@ -39,7 +39,7 @@ const sortData = (data: Repository[], sortBy: keyof Repository | undefined, dire
)
: data;
-const TestableTable: React.FunctionComponent = () => {
+const TestTable: React.FunctionComponent = () => {
const [ searchParams, setSearchParams ] = useSearchParams();
const { sortBy, direction, onSort } = useDataViewSort({ searchParams, setSearchParams });
const sortByIndex = React.useMemo(() => COLUMNS.findIndex(item => item.key === sortBy), [ sortBy ]);
@@ -78,7 +78,7 @@ describe('DataViewTable Sorting with Hook', () => {
it('sorts by repository name in ascending and descending order', () => {
cy.mount(
-
+
);
@@ -94,7 +94,7 @@ describe('DataViewTable Sorting with Hook', () => {
it('sorts by last commit date in ascending and descending order', () => {
cy.mount(
-
+
);
From 317462fc860d0aa4a832217d1a52ba32b3707b20 Mon Sep 17 00:00:00 2001
From: Filip Hlavac
Date: Fri, 22 Nov 2024 09:38:18 +0100
Subject: [PATCH 22/23] fix: make the changes work with v6
---
package-lock.json | 1848 ++++++++++++-----
package.json | 2 +-
.../DataViewCheckboxFilter.tsx | 8 +-
.../DataViewCheckboxFilter.test.tsx.snap | 135 +-
.../DataViewFilters.test.tsx.snap | 110 +-
.../DataViewTextFilter/DataViewTextFilter.tsx | 4 +-
.../DataViewTextFilter.test.tsx.snap | 161 +-
.../src/DataViewToolbar/DataViewToolbar.tsx | 6 +-
.../DataViewToolbar.test.tsx.snap | 50 +-
9 files changed, 1622 insertions(+), 702 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index f0480dd..0cb7794 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,10 +19,10 @@
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@octokit/rest": "^20.1.1",
- "@patternfly/documentation-framework": "6.0.0-alpha.117",
- "@swc/core": "1.6.1",
+ "@patternfly/documentation-framework": "6.0.6",
+ "@swc/core": "1.9.1",
"@testing-library/dom": "^10.1.0",
- "@testing-library/jest-dom": "^6.4.6",
+ "@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "14.5.2",
"@types/jest": "^29.5.13",
@@ -31,18 +31,18 @@
"babel-jest": "^29.7.0",
"babel-polyfill": "6.26.0",
"chokidar": "^3.6.0",
- "concurrently": "^8.2.2",
- "cypress": "^13.11.0",
+ "concurrently": "^9.1.0",
+ "cypress": "^13.15.2",
"eslint": "^8.57.0",
"eslint-config-prettier": "9.1.0",
"eslint-config-standard-with-typescript": "^23.0.0",
- "eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-import": "^2.31.0",
"eslint-plugin-markdown": "^1.0.2",
"eslint-plugin-n": "^15.7.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.2.0",
"eslint-plugin-react": "^7.34.3",
- "eslint-plugin-react-hooks": "^4.6.2",
+ "eslint-plugin-react-hooks": "^5.0.0",
"fs-extra": "^11.2.0",
"glob": "^10.4.1",
"identity-obj-proxy": "^3.0.0",
@@ -53,7 +53,7 @@
"react": "^18",
"react-dom": "^18",
"rimraf": "^5.0.7",
- "sass": "^1.77.6",
+ "sass": "^1.80.7",
"sass-loader": "^14.2.1",
"serve": "^14.2.3",
"start-server-and-test": "^2.0.4",
@@ -2068,9 +2068,9 @@
}
},
"node_modules/@cypress/request": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.5.tgz",
- "integrity": "sha512-v+XHd9XmWbufxF1/bTaVm2yhbxY+TB4YtWRqF2zaXBlDNMkls34KiATz0AVDLavL3iB6bQk9/7n3oY1EoLSWGA==",
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz",
+ "integrity": "sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -2089,7 +2089,7 @@
"performance-now": "^2.1.0",
"qs": "6.13.0",
"safe-buffer": "^5.1.2",
- "tough-cookie": "^4.1.3",
+ "tough-cookie": "^5.0.0",
"tunnel-agent": "^0.6.0",
"uuid": "^8.3.2"
},
@@ -2097,6 +2097,19 @@
"node": ">= 6"
}
},
+ "node_modules/@cypress/request/node_modules/tough-cookie": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz",
+ "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tldts": "^6.1.32"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/@cypress/xvfb": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz",
@@ -2144,17 +2157,20 @@
"license": "MIT"
},
"node_modules/@eslint-community/eslint-utils": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
- "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+ "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "eslint-visitor-keys": "^3.3.0"
+ "eslint-visitor-keys": "^3.4.3"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
@@ -3517,6 +3533,7 @@
"integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==",
"dev": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
"detect-libc": "^1.0.3",
"is-glob": "^4.0.3",
@@ -3798,9 +3815,9 @@
}
},
"node_modules/@patternfly/ast-helpers": {
- "version": "1.4.0-alpha.106",
- "resolved": "https://registry.npmjs.org/@patternfly/ast-helpers/-/ast-helpers-1.4.0-alpha.106.tgz",
- "integrity": "sha512-5Xfi2r2oudTvPYjoMGlJKSDlAf95GCTr8ely/F/pNiyV28EdNPJ9cKIVWstZex1wxvyxtvp5wOfpRh2fWE1Khg==",
+ "version": "1.4.0-alpha.125",
+ "resolved": "https://registry.npmjs.org/@patternfly/ast-helpers/-/ast-helpers-1.4.0-alpha.125.tgz",
+ "integrity": "sha512-WvN5CYFmTYOztt3wMidJq8xLdu6jhpHzjPvYxMN2wlh7v0QJEHaplvJGZH/E8ZUcri/ni2OoLVIe2KcuRwrxng==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3812,9 +3829,9 @@
}
},
"node_modules/@patternfly/documentation-framework": {
- "version": "6.0.0-alpha.117",
- "resolved": "https://registry.npmjs.org/@patternfly/documentation-framework/-/documentation-framework-6.0.0-alpha.117.tgz",
- "integrity": "sha512-npVzrFElVEuDBSvu4yiF5BK3c1x9RwjD1G+bbtLbbb8uffPul88zeThuA7vpi02sQc1z1cV6XGJo6ZZ8OQ1OjQ==",
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/@patternfly/documentation-framework/-/documentation-framework-6.0.6.tgz",
+ "integrity": "sha512-YXXzj7K2lmAZbvgTDSTd4AJTW6xpJ6G/C3jCMxGGMXevYJ1wGHQQnBVbGQvQcZPgIwU5nv3+FmnyfldJhRwQtw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3822,7 +3839,7 @@
"@babel/preset-env": "^7.24.3",
"@babel/preset-react": "^7.24.1",
"@mdx-js/util": "1.6.16",
- "@patternfly/ast-helpers": "^1.4.0-alpha.106",
+ "@patternfly/ast-helpers": "^1.4.0-alpha.122",
"@reach/router": "npm:@gatsbyjs/reach-router@1.3.9",
"autoprefixer": "9.8.6",
"babel-loader": "^9.1.3",
@@ -3885,10 +3902,10 @@
"pf-docs-framework": "scripts/cli/cli.js"
},
"peerDependencies": {
- "@patternfly/patternfly": "6.0.0-prerelease.15",
- "@patternfly/react-code-editor": "6.0.0-prerelease.21",
- "@patternfly/react-core": "6.0.0-prerelease.21",
- "@patternfly/react-table": "6.0.0-prerelease.22",
+ "@patternfly/patternfly": "^6.0.0",
+ "@patternfly/react-code-editor": "^6.0.0",
+ "@patternfly/react-core": "^6.0.0",
+ "@patternfly/react-table": "^6.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
}
@@ -4296,265 +4313,260 @@
}
},
"node_modules/@patternfly/patternfly": {
- "version": "6.0.0-prerelease.15",
- "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-6.0.0-prerelease.15.tgz",
- "integrity": "sha512-7/tRjaWBMX9bvMhIexdAONgxKiVbOCuFffLEKq+p+Q4t8Qq8fqGM7eAznzOx3YbLKIzqVtmbRrgTAIkpsSe1aw==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-6.0.0.tgz",
+ "integrity": "sha512-Mn92Tt/4okSj1COGCJrgUgh390OOaFCWf0tL0WmigDNUecSHNn1D6Vhpd1hxHQBXvre9eWorzxV2b9yhSEl79Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@patternfly/patternfly-a11y": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@patternfly/patternfly-a11y/-/patternfly-a11y-4.3.1.tgz",
- "integrity": "sha512-WBdiCJsfEo+cLgtLPDyvOtvRewzWqUvymLOx+Hj/jFoMI7hbotoZSBl4GUZDtFDOHXN4/vfu16eZy9DQHTY/Ew==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/patternfly-a11y/-/patternfly-a11y-5.0.0.tgz",
+ "integrity": "sha512-2GSzO6rSo/8Qg5IBvZeRtJp9tLj6XZGMD0HkENMBkHKDXBdUvCLftsu91E9408qAqgxDx1DrO3nhB3spo5LfiA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "axe-core": "^4.4.1",
- "chromedriver": "^101.0.0",
- "commander": "^5.1.0",
- "fs-extra": "^10.0.0",
+ "axe-core": "^4.10.2",
+ "chromedriver": "^130.0.1",
+ "commander": "^12.1.0",
+ "fs-extra": "^11.2.0",
"junit-xml": "^1.2.0",
- "puppeteer": "^14.2.0",
- "puppeteer-cluster": "^0.23.0",
- "xmldoc": "^1.1.2"
+ "puppeteer": "^23.6.1",
+ "puppeteer-cluster": "^0.24.0",
+ "xmldoc": "^1.3.0"
},
"bin": {
"patternfly-a11y": "cli.js"
+ },
+ "peerDependencies": {
+ "victory-bar": "^37.1.1",
+ "victory-core": "^37.1.1",
+ "victory-create-container": "^37.1.1",
+ "victory-cursor-container": "^37.1.1",
+ "victory-group": "^37.1.1",
+ "victory-legend": "^37.1.1",
+ "victory-line": "^37.1.1",
+ "victory-pie": "^37.1.1",
+ "victory-scatter": "^37.1.1",
+ "victory-stack": "^37.1.1",
+ "victory-tooltip": "^37.1.1",
+ "victory-voronoi-container": "^37.1.1"
+ }
+ },
+ "node_modules/@patternfly/patternfly-a11y/node_modules/@puppeteer/browsers": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.1.tgz",
+ "integrity": "sha512-0kdAbmic3J09I6dT8e9vE2JOCSt13wHCW5x/ly8TSt2bDtuIWe2TgLZZDHdcziw9AVCzflMAXCrVyRIhIs44Ng==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "^4.3.7",
+ "extract-zip": "^2.0.1",
+ "progress": "^2.0.3",
+ "proxy-agent": "^6.4.0",
+ "semver": "^7.6.3",
+ "tar-fs": "^3.0.6",
+ "unbzip2-stream": "^1.4.3",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "browsers": "lib/cjs/main-cli.js"
+ },
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@patternfly/patternfly-a11y/node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "node_modules/@patternfly/patternfly-a11y/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
- "license": "MIT",
+ "license": "Python-2.0"
+ },
+ "node_modules/@patternfly/patternfly-a11y/node_modules/chromium-bidi": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.8.0.tgz",
+ "integrity": "sha512-uJydbGdTw0DEUjhoogGveneJVWX/9YuqkWePzMmkBYwtdAqo5d3J/ovNKFr+/2hWXYmYCr6it8mSSTIj6SS6Ug==",
+ "dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
+ "mitt": "3.0.1",
+ "urlpattern-polyfill": "10.0.0",
+ "zod": "3.23.8"
+ },
+ "peerDependencies": {
+ "devtools-protocol": "*"
}
},
"node_modules/@patternfly/patternfly-a11y/node_modules/commander": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
- "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 6"
+ "node": ">=18"
}
},
- "node_modules/@patternfly/patternfly-a11y/node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "node_modules/@patternfly/patternfly-a11y/node_modules/cosmiconfig": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
+ "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ms": "2.1.2"
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
},
"engines": {
- "node": ">=6.0"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
},
"peerDependenciesMeta": {
- "supports-color": {
+ "typescript": {
"optional": true
}
}
},
"node_modules/@patternfly/patternfly-a11y/node_modules/devtools-protocol": {
- "version": "0.0.1001819",
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1001819.tgz",
- "integrity": "sha512-G6OsIFnv/rDyxSqBa2lDLR6thp9oJioLsb2Gl+LbQlyoA9/OBAkrTU9jiCcQ8Pnh7z4d6slDiLaogR5hzgJLmQ==",
+ "version": "0.0.1367902",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz",
+ "integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==",
"dev": true,
"license": "BSD-3-Clause"
},
- "node_modules/@patternfly/patternfly-a11y/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "node_modules/@patternfly/patternfly-a11y/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@patternfly/patternfly-a11y/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
+ "argparse": "^2.0.1"
},
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/@patternfly/patternfly-a11y/node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "node_modules/@patternfly/patternfly-a11y/node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"dev": true,
"license": "MIT"
},
- "node_modules/@patternfly/patternfly-a11y/node_modules/pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "node_modules/@patternfly/patternfly-a11y/node_modules/puppeteer": {
+ "version": "23.9.0",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.9.0.tgz",
+ "integrity": "sha512-WfB8jGwFV+qrD9dcJJVvWPFJBU6kxeu2wxJz9WooDGfM3vIiKLgzImEDBxUQnCBK/2cXB3d4dV6gs/LLpgfLDg==",
"dev": true,
- "license": "MIT",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
"dependencies": {
- "find-up": "^4.0.0"
+ "@puppeteer/browsers": "2.4.1",
+ "chromium-bidi": "0.8.0",
+ "cosmiconfig": "^9.0.0",
+ "devtools-protocol": "0.0.1367902",
+ "puppeteer-core": "23.9.0",
+ "typed-query-selector": "^2.12.0"
+ },
+ "bin": {
+ "puppeteer": "lib/cjs/puppeteer/node/cli.js"
},
"engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
- "node_modules/@patternfly/patternfly-a11y/node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@patternfly/patternfly-a11y/node_modules/puppeteer": {
- "version": "14.4.1",
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-14.4.1.tgz",
- "integrity": "sha512-+H0Gm84aXUvSLdSiDROtLlOofftClgw2TdceMvvCU9UvMryappoeS3+eOLfKvoy4sm8B8MWnYmPhWxVFudAOFQ==",
- "deprecated": "< 22.8.2 is no longer supported",
+ "node_modules/@patternfly/patternfly-a11y/node_modules/puppeteer-cluster": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/puppeteer-cluster/-/puppeteer-cluster-0.24.0.tgz",
+ "integrity": "sha512-zHPoNsrwkFLKFtgJJv2aC13EbMASQsE048uZd7CyikEXcl+sc1Nf6PMFb9kMoZI7/zMYxvuP658o2mw079ZZyQ==",
"dev": true,
- "hasInstallScript": true,
- "license": "Apache-2.0",
+ "license": "MIT",
"dependencies": {
- "cross-fetch": "3.1.5",
- "debug": "4.3.4",
- "devtools-protocol": "0.0.1001819",
- "extract-zip": "2.0.1",
- "https-proxy-agent": "5.0.1",
- "pkg-dir": "4.2.0",
- "progress": "2.0.3",
- "proxy-from-env": "1.1.0",
- "rimraf": "3.0.2",
- "tar-fs": "2.1.1",
- "unbzip2-stream": "1.4.3",
- "ws": "8.7.0"
+ "debug": "^4.3.4"
},
- "engines": {
- "node": ">=14.1.0"
+ "peerDependencies": {
+ "puppeteer": ">=22.0.0"
}
},
- "node_modules/@patternfly/patternfly-a11y/node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "node_modules/@patternfly/patternfly-a11y/node_modules/puppeteer-core": {
+ "version": "23.9.0",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.9.0.tgz",
+ "integrity": "sha512-hLVrav2HYMVdK0YILtfJwtnkBAwNOztUdR4aJ5YKDvgsbtagNr6urUJk9HyjRA9e+PaLI3jzJ0wM7A4jSZ7Qxw==",
"dev": true,
- "license": "MIT",
+ "license": "Apache-2.0",
"dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
+ "@puppeteer/browsers": "2.4.1",
+ "chromium-bidi": "0.8.0",
+ "debug": "^4.3.7",
+ "devtools-protocol": "0.0.1367902",
+ "typed-query-selector": "^2.12.0",
+ "ws": "^8.18.0"
},
"engines": {
- "node": ">= 6"
+ "node": ">=18"
}
},
- "node_modules/@patternfly/patternfly-a11y/node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "node_modules/@patternfly/patternfly-a11y/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
"license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
"bin": {
- "rimraf": "bin.js"
+ "semver": "bin/semver.js"
},
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/@patternfly/patternfly-a11y/node_modules/tar-fs": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
- "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
+ "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
"pump": "^3.0.0",
- "tar-stream": "^2.1.4"
+ "tar-stream": "^3.1.5"
+ },
+ "optionalDependencies": {
+ "bare-fs": "^2.1.1",
+ "bare-path": "^2.1.0"
}
},
"node_modules/@patternfly/patternfly-a11y/node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
+ "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@patternfly/patternfly-a11y/node_modules/ws": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
- "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
+ "b4a": "^1.6.4",
+ "fast-fifo": "^1.2.0",
+ "streamx": "^2.15.0"
}
},
"node_modules/@patternfly/react-code-editor": {
- "version": "6.0.0-prerelease.21",
- "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-6.0.0-prerelease.21.tgz",
- "integrity": "sha512-t9/8Uk3sbPaXasZXHaIxvcAGRWAlep9L0Gsy1vA+vzmpU8Igk1GO2JNMVr9ux4ScLEuMnzp0Rbq++VbxtDNdwA==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-code-editor/-/react-code-editor-6.0.0.tgz",
+ "integrity": "sha512-TnI/NNkizzWTzdVZWmpyEPKXgsOoUeklk8Xlgtl7II/+5juLjlt0wXTMhL35F59Rzd0YohGs251zXAwJbn6vIQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@monaco-editor/react": "^4.6.0",
- "@patternfly/react-core": "^6.0.0-prerelease.21",
- "@patternfly/react-icons": "^6.0.0-prerelease.7",
- "@patternfly/react-styles": "^6.0.0-prerelease.6",
+ "@patternfly/react-core": "^6.0.0",
+ "@patternfly/react-icons": "^6.0.0",
+ "@patternfly/react-styles": "^6.0.0",
"react-dropzone": "14.2.3",
"tslib": "^2.7.0"
},
@@ -4564,14 +4576,14 @@
}
},
"node_modules/@patternfly/react-component-groups": {
- "version": "6.0.0-prerelease.7",
- "resolved": "https://registry.npmjs.org/@patternfly/react-component-groups/-/react-component-groups-6.0.0-prerelease.7.tgz",
- "integrity": "sha512-+JYabo0L8ASWSiYHA6mzDrAdPABdcmaEk2Ts06PuGb/nrZdOLvdAHRFpzcnjFva9+tkeItHvAXAT7bK5WVAEEg==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-component-groups/-/react-component-groups-6.0.0.tgz",
+ "integrity": "sha512-q4dQj4b/Yf8fW3ZXWZhXrX8xE73JpRAFF5wydDx6OZe3oZXucUgldghupavbyhY/oYM2V89/P67w24poH6iOqA==",
"license": "MIT",
"dependencies": {
- "@patternfly/react-core": "^6.0.0-prerelease.21",
- "@patternfly/react-icons": "^6.0.0-prerelease.7",
- "@patternfly/react-table": "^6.0.0-prerelease.22",
+ "@patternfly/react-core": "^6.0.0",
+ "@patternfly/react-icons": "^6.0.0",
+ "@patternfly/react-table": "^6.0.0",
"clsx": "^2.1.1",
"react-jss": "^10.10.0"
},
@@ -4581,14 +4593,14 @@
}
},
"node_modules/@patternfly/react-core": {
- "version": "6.0.0-prerelease.21",
- "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-6.0.0-prerelease.21.tgz",
- "integrity": "sha512-EaGcKUPeeR253vY4N0Ahm9oOVtltoI6JycfclwmzjevOzpYvuLj1jcsVwL8wqgWYQVpURoBm1yxIdx34fo5UHA==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-6.0.0.tgz",
+ "integrity": "sha512-UKFj9+YzBY+FfEDsLONgOM4N0e8SPV/27/UzNRiJ0gpgqbw2POuXwLpjGSRTTIUuCaLaGGM5PeTSj7mMB73ykw==",
"license": "MIT",
"dependencies": {
- "@patternfly/react-icons": "^6.0.0-prerelease.7",
- "@patternfly/react-styles": "^6.0.0-prerelease.6",
- "@patternfly/react-tokens": "^6.0.0-prerelease.7",
+ "@patternfly/react-icons": "^6.0.0",
+ "@patternfly/react-styles": "^6.0.0",
+ "@patternfly/react-tokens": "^6.0.0",
"focus-trap": "7.6.0",
"react-dropzone": "^14.2.3",
"tslib": "^2.7.0"
@@ -4603,9 +4615,9 @@
"link": true
},
"node_modules/@patternfly/react-icons": {
- "version": "6.0.0-prerelease.7",
- "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.0.0-prerelease.7.tgz",
- "integrity": "sha512-DQmecVgXRIiD3ww4KUuJ0qO76TmYMDEJ1ao1+DYuTSP+FzeJLJKuE9QxvL8qn3anyKtuORBuHdTIjM52mVq5Vg==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-6.0.0.tgz",
+ "integrity": "sha512-ZFrsBVKrAp0DZrPOss98OA/EVUL4F0frXhR1uBId9+3ZrRArdKTgYgmQUCeSzMbxnSlxpmm3a2L05XQ36VUVbw==",
"license": "MIT",
"peerDependencies": {
"react": "^17 || ^18",
@@ -4613,21 +4625,21 @@
}
},
"node_modules/@patternfly/react-styles": {
- "version": "6.0.0-prerelease.6",
- "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-6.0.0-prerelease.6.tgz",
- "integrity": "sha512-tI28gIJFgbgVQs7Xj705csfl6T92dr5Bh7ynR5gN4+QdTWCUWmSctp46G2ZewXdrIN+C+2zUPE86o77aFp4CWw==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-6.0.0.tgz",
+ "integrity": "sha512-fJFMB89sTRGlZTzTLmpRmthgOXqcN078scHMFJ3ttfi2D2btnem5oZrxmQ/gPZkZOxR+9MqwKDB6l3F5x1SqLQ==",
"license": "MIT"
},
"node_modules/@patternfly/react-table": {
- "version": "6.0.0-prerelease.22",
- "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-6.0.0-prerelease.22.tgz",
- "integrity": "sha512-vGDWr14YATIY9RnxaOpyjkPlw4aKBM7dhHJRPXY0cwCFehSGwwzQpialZyi+92I2WfBF1Cb75doDAtxTSi8UZQ==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-6.0.0.tgz",
+ "integrity": "sha512-LvWMzjcQZHdFUpK8fjj5EAFrNxqB8/MFd7gUUZu7AgYt6rmS2im4xk6yb7h0K7cAhY085oPeRF9lkYSCgzlRDg==",
"license": "MIT",
"dependencies": {
- "@patternfly/react-core": "^6.0.0-prerelease.21",
- "@patternfly/react-icons": "^6.0.0-prerelease.7",
- "@patternfly/react-styles": "^6.0.0-prerelease.6",
- "@patternfly/react-tokens": "^6.0.0-prerelease.7",
+ "@patternfly/react-core": "^6.0.0",
+ "@patternfly/react-icons": "^6.0.0",
+ "@patternfly/react-styles": "^6.0.0",
+ "@patternfly/react-tokens": "^6.0.0",
"lodash": "^4.17.21",
"tslib": "^2.7.0"
},
@@ -4637,9 +4649,9 @@
}
},
"node_modules/@patternfly/react-tokens": {
- "version": "6.0.0-prerelease.7",
- "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-6.0.0-prerelease.7.tgz",
- "integrity": "sha512-SLgVwbIgVx26LCjaXkpNlPIZYqWpHJkw3QX/n3URLmIcRlCw536/rKO1PzXaeuCCqhuSq66J6R125zM2eJjM6A==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-6.0.0.tgz",
+ "integrity": "sha512-xd0ynDkiIW2rp8jz4TNvR4Dyaw9kSMkZdsuYcLlFXCVmvX//Mnl4rhBnid/2j2TaqK0NbkyTTPnPY/BU7SfLVQ==",
"license": "MIT"
},
"node_modules/@pkgjs/parseargs": {
@@ -4840,9 +4852,9 @@
}
},
"node_modules/@remix-run/router": {
- "version": "1.20.0",
- "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz",
- "integrity": "sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==",
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz",
+ "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4908,15 +4920,15 @@
}
},
"node_modules/@swc/core": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.6.1.tgz",
- "integrity": "sha512-Yz5uj5hNZpS5brLtBvKY0L4s2tBAbQ4TjmW8xF1EC3YLFxQRrUjMP49Zm1kp/KYyYvTkSaG48Ffj2YWLu9nChw==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.9.1.tgz",
+ "integrity": "sha512-OnPc+Kt5oy3xTvr/KCUOqE9ptJcWbyQgAUr1ydh9EmbBcmJTaO1kfQCxm/axzJi6sKeDTxL9rX5zvLOhoYIaQw==",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@swc/counter": "^0.1.3",
- "@swc/types": "^0.1.8"
+ "@swc/types": "^0.1.14"
},
"engines": {
"node": ">=10"
@@ -4926,16 +4938,16 @@
"url": "https://opencollective.com/swc"
},
"optionalDependencies": {
- "@swc/core-darwin-arm64": "1.6.1",
- "@swc/core-darwin-x64": "1.6.1",
- "@swc/core-linux-arm-gnueabihf": "1.6.1",
- "@swc/core-linux-arm64-gnu": "1.6.1",
- "@swc/core-linux-arm64-musl": "1.6.1",
- "@swc/core-linux-x64-gnu": "1.6.1",
- "@swc/core-linux-x64-musl": "1.6.1",
- "@swc/core-win32-arm64-msvc": "1.6.1",
- "@swc/core-win32-ia32-msvc": "1.6.1",
- "@swc/core-win32-x64-msvc": "1.6.1"
+ "@swc/core-darwin-arm64": "1.9.1",
+ "@swc/core-darwin-x64": "1.9.1",
+ "@swc/core-linux-arm-gnueabihf": "1.9.1",
+ "@swc/core-linux-arm64-gnu": "1.9.1",
+ "@swc/core-linux-arm64-musl": "1.9.1",
+ "@swc/core-linux-x64-gnu": "1.9.1",
+ "@swc/core-linux-x64-musl": "1.9.1",
+ "@swc/core-win32-arm64-msvc": "1.9.1",
+ "@swc/core-win32-ia32-msvc": "1.9.1",
+ "@swc/core-win32-x64-msvc": "1.9.1"
},
"peerDependencies": {
"@swc/helpers": "*"
@@ -4947,9 +4959,9 @@
}
},
"node_modules/@swc/core-darwin-arm64": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.6.1.tgz",
- "integrity": "sha512-u6GdwOXsOEdNAdSI6nWq6G2BQw5HiSNIZVcBaH1iSvBnxZvWbnIKyDiZKaYnDwTLHLzig2GuUjjE2NaCJPy4jg==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.9.1.tgz",
+ "integrity": "sha512-2/ncHSCdAh5OHem1fMITrWEzzl97OdMK1PHc9CkxSJnphLjRubfxB5sbc5tDhcO68a5tVy+DxwaBgDec3PXnOg==",
"cpu": [
"arm64"
],
@@ -4964,9 +4976,9 @@
}
},
"node_modules/@swc/core-darwin-x64": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.6.1.tgz",
- "integrity": "sha512-/tXwQibkDNLVbAtr7PUQI0iQjoB708fjhDDDfJ6WILSBVZ3+qs/LHjJ7jHwumEYxVq1XA7Fv2Q7SE/ZSQoWHcQ==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.9.1.tgz",
+ "integrity": "sha512-4MDOFC5zmNqRJ9RGFOH95oYf27J9HniLVpB1pYm2gGeNHdl2QvDMtx2QTuMHQ6+OTn/3y1BHYuhBGp7d405oLA==",
"cpu": [
"x64"
],
@@ -4981,9 +4993,9 @@
}
},
"node_modules/@swc/core-linux-arm-gnueabihf": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.6.1.tgz",
- "integrity": "sha512-aDgipxhJTms8iH78emHVutFR2c16LNhO+NTRCdYi+X4PyIn58/DyYTH6VDZ0AeEcS5f132ZFldU5AEgExwihXA==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.9.1.tgz",
+ "integrity": "sha512-eVW/BjRW8/HpLe3+1jRU7w7PdRLBgnEEYTkHJISU8805/EKT03xNZn6CfaBpKfeAloY4043hbGzE/NP9IahdpQ==",
"cpu": [
"arm"
],
@@ -4998,9 +5010,9 @@
}
},
"node_modules/@swc/core-linux-arm64-gnu": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.6.1.tgz",
- "integrity": "sha512-XkJ+eO4zUKG5g458RyhmKPyBGxI0FwfWFgpfIj5eDybxYJ6s4HBT5MoxyBLorB5kMlZ0XoY/usUMobPVY3nL0g==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.9.1.tgz",
+ "integrity": "sha512-8m3u1v8R8NgI/9+cHMkzk14w87blSy3OsQPWPfhOL+XPwhyLPvat+ahQJb2nZmltjTgkB4IbzKFSfbuA34LmNA==",
"cpu": [
"arm64"
],
@@ -5015,9 +5027,9 @@
}
},
"node_modules/@swc/core-linux-arm64-musl": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.6.1.tgz",
- "integrity": "sha512-dr6YbLBg/SsNxs1hDqJhxdcrS8dGMlOXJwXIrUvACiA8jAd6S5BxYCaqsCefLYXtaOmu0bbx1FB/evfodqB70Q==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.9.1.tgz",
+ "integrity": "sha512-hpT0sQAZnW8l02I289yeyFfT9llGO9PzKDxUq8pocKtioEHiElRqR53juCWoSmzuWi+6KX7zUJ0NKCBrc8pmDg==",
"cpu": [
"arm64"
],
@@ -5032,9 +5044,9 @@
}
},
"node_modules/@swc/core-linux-x64-gnu": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.6.1.tgz",
- "integrity": "sha512-A0b/3V+yFy4LXh3O9umIE7LXPC7NBWdjl6AQYqymSMcMu0EOb1/iygA6s6uWhz9y3e172Hpb9b/CGsuD8Px/bg==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.9.1.tgz",
+ "integrity": "sha512-sGFdpdAYusk/ropHiwtXom2JrdaKPxl8MqemRv6dvxZq1Gm/GdmOowxdXIPjCgBGMgoXVcgNviH6CgiO5q+UtA==",
"cpu": [
"x64"
],
@@ -5049,9 +5061,9 @@
}
},
"node_modules/@swc/core-linux-x64-musl": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.6.1.tgz",
- "integrity": "sha512-5dJjlzZXhC87nZZZWbpiDP8kBIO0ibis893F/rtPIQBI5poH+iJuA32EU3wN4/WFHeK4et8z6SGSVghPtWyk4g==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.9.1.tgz",
+ "integrity": "sha512-YtNLNwIWs0Z2+XgBs6+LrCIGtfCDtNr4S4b6Q5HDOreEIGzSvhkef8eyBI5L+fJ2eGov4b7iEo61C4izDJS5RA==",
"cpu": [
"x64"
],
@@ -5066,9 +5078,9 @@
}
},
"node_modules/@swc/core-win32-arm64-msvc": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.6.1.tgz",
- "integrity": "sha512-HBi1ZlwvfcUibLtT3g/lP57FaDPC799AD6InolB2KSgkqyBbZJ9wAXM8/CcH67GLIP0tZ7FqblrJTzGXxetTJQ==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.9.1.tgz",
+ "integrity": "sha512-qSxD3uZW2vSiHqUt30vUi0PB92zDh9bjqh5YKpfhhVa7h1vt/xXhlid8yMvSNToTfzhRrTEffOAPUr7WVoyQUA==",
"cpu": [
"arm64"
],
@@ -5083,9 +5095,9 @@
}
},
"node_modules/@swc/core-win32-ia32-msvc": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.6.1.tgz",
- "integrity": "sha512-AKqHohlWERclexar5y6ux4sQ8yaMejEXNxeKXm7xPhXrp13/1p4/I3E5bPVX/jMnvpm4HpcKSP0ee2WsqmhhPw==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.9.1.tgz",
+ "integrity": "sha512-C3fPEwyX/WRPlX6zIToNykJuz1JkZX0sk8H1QH2vpnKuySUkt/Ur5K2FzLgSWzJdbfxstpgS151/es0VGAD+ZA==",
"cpu": [
"ia32"
],
@@ -5100,9 +5112,9 @@
}
},
"node_modules/@swc/core-win32-x64-msvc": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.6.1.tgz",
- "integrity": "sha512-0dLdTLd+ONve8kgC5T6VQ2Y5G+OZ7y0ujjapnK66wpvCBM6BKYGdT/OKhZKZydrC5gUKaxFN6Y5oOt9JOFUrOQ==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.9.1.tgz",
+ "integrity": "sha512-2XZ+U1AyVsOAXeH6WK1syDm7+gwTjA8fShs93WcbxnK7HV+NigDlvr4124CeJLTHyh3fMh1o7+CnQnaBJhlysQ==",
"cpu": [
"x64"
],
@@ -5124,9 +5136,9 @@
"license": "Apache-2.0"
},
"node_modules/@swc/types": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz",
- "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==",
+ "version": "0.1.17",
+ "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz",
+ "integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -5237,9 +5249,9 @@
}
},
"node_modules/@testing-library/jest-dom": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz",
- "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==",
+ "version": "6.6.3",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz",
+ "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5389,6 +5401,13 @@
"node": ">= 10"
}
},
+ "node_modules/@tootallnate/quickjs-emscripten": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
+ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/aria-query": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
@@ -5483,6 +5502,87 @@
"@types/node": "*"
}
},
+ "node_modules/@types/d3-array": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
+ "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
+ "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz",
+ "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz",
+ "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@types/eslint": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
@@ -7159,9 +7259,9 @@
"license": "MIT"
},
"node_modules/axe-core": {
- "version": "4.10.0",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz",
- "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==",
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz",
+ "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==",
"dev": true,
"license": "MPL-2.0",
"engines": {
@@ -7550,6 +7650,16 @@
],
"license": "MIT"
},
+ "node_modules/basic-ftp": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
+ "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -8411,60 +8521,38 @@
}
},
"node_modules/chromedriver": {
- "version": "101.0.0",
- "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-101.0.0.tgz",
- "integrity": "sha512-LkkWxy6KM/0YdJS8qBeg5vfkTZTRamhBfOttb4oic4echDgWvCU1E8QcBbUBOHqZpSrYMyi7WMKmKMhXFUaZ+w==",
- "deprecated": "Chromedriver download url has changed. Use version 114.0.2 or newer.",
+ "version": "130.0.4",
+ "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-130.0.4.tgz",
+ "integrity": "sha512-lpR+PWXszij1k4Ig3t338Zvll9HtCTiwoLM7n4pCCswALHxzmgwaaIFBh3rt9+5wRk9D07oFblrazrBxwaYYAQ==",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@testim/chrome-version": "^1.1.2",
- "axios": "^0.24.0",
- "del": "^6.0.0",
+ "@testim/chrome-version": "^1.1.4",
+ "axios": "^1.7.4",
+ "compare-versions": "^6.1.0",
"extract-zip": "^2.0.1",
- "https-proxy-agent": "^5.0.0",
+ "proxy-agent": "^6.4.0",
"proxy-from-env": "^1.1.0",
- "tcp-port-used": "^1.0.1"
+ "tcp-port-used": "^1.0.2"
},
"bin": {
"chromedriver": "bin/chromedriver"
},
"engines": {
- "node": ">=10"
+ "node": ">=18"
}
},
"node_modules/chromedriver/node_modules/axios": {
- "version": "0.24.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
- "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.14.4"
- }
- },
- "node_modules/chromedriver/node_modules/del": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz",
- "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==",
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
+ "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "globby": "^11.0.1",
- "graceful-fs": "^4.2.4",
- "is-glob": "^4.0.1",
- "is-path-cwd": "^2.2.0",
- "is-path-inside": "^3.0.2",
- "p-map": "^4.0.0",
- "rimraf": "^3.0.2",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
}
},
"node_modules/chromedriver/node_modules/follow-redirects": {
@@ -8488,44 +8576,6 @@
}
}
},
- "node_modules/chromedriver/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/chromedriver/node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/chromedriver/node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -8533,23 +8583,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/chromedriver/node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/chromium-bidi": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.7.tgz",
@@ -9127,6 +9160,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/compare-versions": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
+ "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/compressible": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
@@ -9217,18 +9257,16 @@
}
},
"node_modules/concurrently": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz",
- "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==",
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.0.tgz",
+ "integrity": "sha512-VxkzwMAn4LP7WyMnJNbHN5mKV9L2IbyDjpzemKr99sXNR3GqRNMMHdm7prV1ws9wg7ETj6WUkNOigZVsptwbgg==",
"dev": true,
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2",
- "date-fns": "^2.30.0",
"lodash": "^4.17.21",
"rxjs": "^7.8.1",
"shell-quote": "^1.8.1",
- "spawn-command": "0.0.2",
"supports-color": "^8.1.1",
"tree-kill": "^1.2.2",
"yargs": "^17.7.2"
@@ -9238,7 +9276,7 @@
"concurrently": "dist/bin/concurrently.js"
},
"engines": {
- "node": "^14.13.0 || >=16.0.0"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
@@ -9964,14 +10002,14 @@
"license": "MIT"
},
"node_modules/cypress": {
- "version": "13.15.0",
- "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.15.0.tgz",
- "integrity": "sha512-53aO7PwOfi604qzOkCSzNlWquCynLlKE/rmmpSPcziRH6LNfaDUAklQT6WJIsD8ywxlIy+uVZsnTMCCQVd2kTw==",
+ "version": "13.16.0",
+ "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.16.0.tgz",
+ "integrity": "sha512-g6XcwqnvzXrqiBQR/5gN+QsyRmKRhls1y5E42fyOvsmU7JuY+wM6uHJWj4ZPttjabzbnRvxcik2WemR8+xT6FA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "@cypress/request": "^3.0.4",
+ "@cypress/request": "^3.0.6",
"@cypress/xvfb": "^1.2.4",
"@types/sinonjs__fake-timers": "8.1.1",
"@types/sizzle": "^2.3.2",
@@ -9982,6 +10020,7 @@
"cachedir": "^2.3.0",
"chalk": "^4.1.0",
"check-more-types": "^2.24.0",
+ "ci-info": "^4.0.0",
"cli-cursor": "^3.1.0",
"cli-table3": "~0.6.1",
"commander": "^6.2.1",
@@ -9996,7 +10035,6 @@
"figures": "^3.2.0",
"fs-extra": "^9.1.0",
"getos": "^3.2.1",
- "is-ci": "^3.0.1",
"is-installed-globally": "~0.4.0",
"lazy-ass": "^1.6.0",
"listr2": "^3.8.3",
@@ -10011,6 +10049,7 @@
"semver": "^7.5.3",
"supports-color": "^8.1.1",
"tmp": "~0.2.3",
+ "tree-kill": "1.2.2",
"untildify": "^4.0.0",
"yauzl": "^2.10.0"
},
@@ -10067,6 +10106,22 @@
"node": ">=8"
}
},
+ "node_modules/cypress/node_modules/ci-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz",
+ "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/cypress/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -10120,36 +10175,179 @@
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=8"
+ }
+ },
+ "node_modules/cypress/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cypress/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
}
},
- "node_modules/cypress/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
"dev": true,
"license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
+ "peer": true,
+ "dependencies": {
+ "d3-array": "2 - 3"
},
"engines": {
- "node": ">=10"
+ "node": ">=12"
}
},
- "node_modules/cypress/node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
+ "peer": true,
"dependencies": {
- "has-flag": "^4.0.0"
+ "d3-time": "1 - 3"
},
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
}
},
"node_modules/dashdash": {
@@ -10165,6 +10363,16 @@
"node": ">=0.10"
}
},
+ "node_modules/data-uri-to-buffer": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
+ "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/data-urls": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz",
@@ -10260,23 +10468,6 @@
"semver": "bin/semver"
}
},
- "node_modules/date-fns": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
- "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.21.0"
- },
- "engines": {
- "node": ">=0.11"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/date-fns"
- }
- },
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
@@ -10473,6 +10664,34 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/degenerator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
+ "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ast-types": "^0.13.4",
+ "escodegen": "^2.1.0",
+ "esprima": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/degenerator/node_modules/ast-types": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/del": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
@@ -10568,6 +10787,25 @@
"rimraf": "bin.js"
}
},
+ "node_modules/delaunator": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz",
+ "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true
+ },
+ "node_modules/delaunay-find": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/delaunay-find/-/delaunay-find-0.0.6.tgz",
+ "integrity": "sha512-1+almjfrnR7ZamBk0q3Nhg6lqSe6Le4vL0WJDSMx4IDbQwTpUTXPjxC00lqLBT8MYsJpPCbI16sIkw9cPsbi7Q==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "delaunator": "^4.0.0"
+ }
+ },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -10636,6 +10874,7 @@
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
"dev": true,
"license": "Apache-2.0",
+ "optional": true,
"bin": {
"detect-libc": "bin/detect-libc.js"
},
@@ -11030,6 +11269,16 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/envinfo": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz",
@@ -11383,7 +11632,27 @@
"eslint": ">=7.0.0"
}
},
- "node_modules/eslint-config-standard": {
+ "node_modules/eslint-config-standard-with-typescript": {
+ "version": "23.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-23.0.0.tgz",
+ "integrity": "sha512-iaaWifImn37Z1OXbNW1es7KI+S7D408F9ys0bpaQf2temeBWlvb0Nc5qHkOgYaRb5QxTZT32GGeN1gtswASOXA==",
+ "deprecated": "Please use eslint-config-love, instead.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint-config-standard": "17.0.0"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
+ "eslint": "^8.0.1",
+ "eslint-plugin-import": "^2.25.2",
+ "eslint-plugin-n": "^15.0.0",
+ "eslint-plugin-promise": "^6.0.0",
+ "typescript": "*"
+ }
+ },
+ "node_modules/eslint-config-standard-with-typescript/node_modules/eslint-config-standard": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz",
"integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==",
@@ -11410,26 +11679,6 @@
"eslint-plugin-promise": "^6.0.0"
}
},
- "node_modules/eslint-config-standard-with-typescript": {
- "version": "23.0.0",
- "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-23.0.0.tgz",
- "integrity": "sha512-iaaWifImn37Z1OXbNW1es7KI+S7D408F9ys0bpaQf2temeBWlvb0Nc5qHkOgYaRb5QxTZT32GGeN1gtswASOXA==",
- "deprecated": "Please use eslint-config-love, instead.",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/parser": "^5.0.0",
- "eslint-config-standard": "17.0.0"
- },
- "peerDependencies": {
- "@typescript-eslint/eslint-plugin": "^5.0.0",
- "eslint": "^8.0.1",
- "eslint-plugin-import": "^2.25.2",
- "eslint-plugin-n": "^15.0.0",
- "eslint-plugin-promise": "^6.0.0",
- "typescript": "*"
- }
- },
"node_modules/eslint-import-resolver-node": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
@@ -11871,16 +12120,16 @@
}
},
"node_modules/eslint-plugin-react-hooks": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz",
- "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz",
+ "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
}
},
"node_modules/eslint-plugin-react/node_modules/doctrine": {
@@ -13392,6 +13641,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-uri": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz",
+ "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "basic-ftp": "^5.0.2",
+ "data-uri-to-buffer": "^6.0.2",
+ "debug": "^4.3.4",
+ "fs-extra": "^11.2.0"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/getos": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz",
@@ -14416,9 +14681,9 @@
}
},
"node_modules/immutable": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz",
- "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==",
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz",
+ "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
"dev": true,
"license": "MIT"
},
@@ -14741,6 +15006,17 @@
"node": ">= 0.4"
}
},
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/interpret": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz",
@@ -14768,6 +15044,34 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/ip-address": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
+ "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jsbn": "1.1.0",
+ "sprintf-js": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/ip-address/node_modules/jsbn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ip-address/node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/ip-regex": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
@@ -14944,19 +15248,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-ci": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
- "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ci-info": "^3.2.0"
- },
- "bin": {
- "is-ci": "bin.js"
- }
- },
"node_modules/is-core-module": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
@@ -19671,6 +19962,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/netmask": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
+ "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/netrc": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/netrc/-/netrc-0.1.4.tgz",
@@ -19720,7 +20021,8 @@
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true
},
"node_modules/node-dir": {
"version": "0.1.17",
@@ -20427,7 +20729,123 @@
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">=6"
+ }
+ },
+ "node_modules/pac-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@tootallnate/quickjs-emscripten": "^0.23.0",
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "get-uri": "^6.0.1",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.5",
+ "pac-resolver": "^7.0.1",
+ "socks-proxy-agent": "^8.0.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/socks": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
+ "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ip-address": "^9.0.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/socks-proxy-agent": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
+ "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.1",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-resolver": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
+ "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "degenerator": "^5.0.0",
+ "netmask": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 14"
}
},
"node_modules/package-json": {
@@ -21454,6 +21872,125 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-agent": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
+ "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "^7.0.1",
+ "https-proxy-agent": "^7.0.3",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "^7.0.1",
+ "proxy-from-env": "^1.1.0",
+ "socks-proxy-agent": "^8.0.2"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/https-proxy-agent": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/proxy-agent/node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/socks": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
+ "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ip-address": "^9.0.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/socks-proxy-agent": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
+ "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.1",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/proxy-from-env": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
@@ -21965,6 +22502,14 @@
"react": ">= 16.8 || 18.0.0"
}
},
+ "node_modules/react-fast-compare": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
+ "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -22002,13 +22547,13 @@
"license": "MIT"
},
"node_modules/react-router": {
- "version": "6.27.0",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz",
- "integrity": "sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==",
+ "version": "6.28.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz",
+ "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@remix-run/router": "1.20.0"
+ "@remix-run/router": "1.21.0"
},
"engines": {
"node": ">=14.0.0"
@@ -22018,14 +22563,14 @@
}
},
"node_modules/react-router-dom": {
- "version": "6.27.0",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.27.0.tgz",
- "integrity": "sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==",
+ "version": "6.28.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz",
+ "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@remix-run/router": "1.20.0",
- "react-router": "6.27.0"
+ "@remix-run/router": "1.21.0",
+ "react-router": "6.28.0"
},
"engines": {
"node": ">=14.0.0"
@@ -23066,15 +23611,14 @@
"license": "MIT"
},
"node_modules/sass": {
- "version": "1.79.5",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.5.tgz",
- "integrity": "sha512-W1h5kp6bdhqFh2tk3DsI771MoEJjvrSY/2ihJRJS4pjIyfJCw0nTsxqhnrUzaLMOJjFchj8rOvraI/YUVjtx5g==",
+ "version": "1.81.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.81.0.tgz",
+ "integrity": "sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@parcel/watcher": "^2.4.1",
"chokidar": "^4.0.0",
- "immutable": "^4.0.0",
+ "immutable": "^5.0.2",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
@@ -23082,6 +23626,9 @@
},
"engines": {
"node": ">=14.0.0"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher": "^2.4.1"
}
},
"node_modules/sass-loader": {
@@ -24081,12 +24628,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/spawn-command": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz",
- "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==",
- "dev": true
- },
"node_modules/spdx-correct": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
@@ -25468,6 +26009,26 @@
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
"license": "MIT"
},
+ "node_modules/tldts": {
+ "version": "6.1.62",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.62.tgz",
+ "integrity": "sha512-TF+wo3MgTLbf37keEwQD0IxvOZO8UZxnpPJDg5iFGAASGxYzbX/Q0y944ATEjrfxG/pF1TWRHCPbFp49Mz1Y1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tldts-core": "^6.1.62"
+ },
+ "bin": {
+ "tldts": "bin/cli.js"
+ }
+ },
+ "node_modules/tldts-core": {
+ "version": "6.1.62",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.62.tgz",
+ "integrity": "sha512-ohONqbfobpuaylhqFbtCzc0dFFeNz85FVKSesgT8DS9OV3a25Yj730pTj7/dDtCqmgoCgEj6gDiU9XxgHKQlBw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/tmp": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
@@ -25921,6 +26482,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/typed-query-selector": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
+ "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
@@ -26617,6 +27185,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/urlpattern-polyfill": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz",
+ "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -26823,6 +27398,289 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/victory-bar": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-bar/-/victory-bar-37.3.2.tgz",
+ "integrity": "sha512-inqb9HLgxheidOAJw7jTMBBR18I7rCgtfH4WuCSMPPtZtUBAEDYFIJzAKzL/LrpC/sWi91fQC2tzmphTD3DS+Q==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2",
+ "victory-vendor": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-brush-container": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-brush-container/-/victory-brush-container-37.3.2.tgz",
+ "integrity": "sha512-SZ4LuM8l3tpGkcnTaGGYREs8gz9E17/c9k3X8uObnXGpz9M3RXkL5hEP0ewtcCjbTr1nwRK3hB4tc1b5BTDj9w==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "react-fast-compare": "^3.2.0",
+ "victory-core": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-core": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-core/-/victory-core-37.3.2.tgz",
+ "integrity": "sha512-ez/QW9OGltj0uo9EzsRrGEu/hS49dXoraQKblQJO4PEUkDZclV3Gy3CJ2cRW2qBM3ljTsVITiQvKt3urVj+RDw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.21",
+ "react-fast-compare": "^3.2.0",
+ "victory-vendor": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-create-container": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-create-container/-/victory-create-container-37.3.2.tgz",
+ "integrity": "sha512-+hEHeTzeANX1knGOqbeykN1mPUy+zQ8A6LLUSiF8dER+DO2IcF/521LHjBSCRcyjUDik75shfhMc//wryxGBmQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-brush-container": "37.3.2",
+ "victory-core": "37.3.2",
+ "victory-cursor-container": "37.3.2",
+ "victory-selection-container": "37.3.2",
+ "victory-voronoi-container": "37.3.2",
+ "victory-zoom-container": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-cursor-container": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-cursor-container/-/victory-cursor-container-37.3.2.tgz",
+ "integrity": "sha512-PpBIexoxV/D9S0JTwgI/AmGC5PEjVFbBg+dxbr0iBskXtIckIdXYg11Tejk4iatvUIuvXrJALMjH+y4Jhl+bGw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-group": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-group/-/victory-group-37.3.2.tgz",
+ "integrity": "sha512-TB0ClboJsCR+ATIwUMgSdkdmau4XUiVaZtc5vehZYB7j50lv3SUtltc4qpztOrilsp1osoKHgUHpj7J8yhRtMw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "react-fast-compare": "^3.2.0",
+ "victory-core": "37.3.2",
+ "victory-shared-events": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-legend": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-legend/-/victory-legend-37.3.2.tgz",
+ "integrity": "sha512-NrXnStmdqWtfA2AkwOVVWGwXswN9C9TNnmUKzXY52BMWR4OQfIaeO0etRV3vSrv8yUD/rt+rm0UOAAI7pSb1Tw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-line": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-line/-/victory-line-37.3.2.tgz",
+ "integrity": "sha512-ZA6A3te2A+egmSPG7jTRu/ZetRE66ggUix11yPaf+7DMZSnRw9f6KXduiUV+fz1otwefJ9pL6vMpXo2SIt9jFQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2",
+ "victory-vendor": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-pie": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-pie/-/victory-pie-37.3.2.tgz",
+ "integrity": "sha512-et7Z9d1paoqXdSL8yNpdTadhhhpPgQTrqO5n7vISNJsjOmt0FTLe4/VeKIyugIhERirVkU5Va0CMlMInbNIysw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2",
+ "victory-vendor": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-scatter": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-scatter/-/victory-scatter-37.3.2.tgz",
+ "integrity": "sha512-mFFIvFC5U+AX1uAgl19HI21L4Mf1rt2YlnjjzPFkJcgy0a2Fv6otjUd4qeqA6pAkVU4e/Dqj8ZZPV2PtfXNeyQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-selection-container": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-selection-container/-/victory-selection-container-37.3.2.tgz",
+ "integrity": "sha512-g/26Xo4Rxco91GPjZ4jgIQDm95AT4zdG2RqXdQTWEgLbWi+Z/Tk1nodhr1jVjwIjZ6RNMeXcAtcVhFjIPLsWzQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-shared-events": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-shared-events/-/victory-shared-events-37.3.2.tgz",
+ "integrity": "sha512-L/p/JzbP7O0x/DrWZicVByyiq0YMsDsvc2uinUCoI+XMAXbp7flxC2lbd7YBq41Sg13BHoPBiEoCXH4nKmo8hw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "json-stringify-safe": "^5.0.1",
+ "lodash": "^4.17.19",
+ "react-fast-compare": "^3.2.0",
+ "victory-core": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-stack": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-stack/-/victory-stack-37.3.2.tgz",
+ "integrity": "sha512-lD8EyzYKTPyWam7h++6VfPxOw4Soj5kYjHqPlbjFjdxoGWYquHrcbHhJ4ra1p+Il9k6iDhy0lIU2DbLa2Ff0wA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "react-fast-compare": "^3.2.0",
+ "victory-core": "37.3.2",
+ "victory-shared-events": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-tooltip": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-tooltip/-/victory-tooltip-37.3.2.tgz",
+ "integrity": "sha512-UsEIGY5lqf3pOGr3ikB7oHw+QZtS+Qui/vqLPhoAL1YJ2bQ0WkIhVx2jLTlyCLIrj6aCvyvdePppApFF43E7Zg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-vendor": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.2.tgz",
+ "integrity": "sha512-2N8j0DIHocffTo2UeZbcd8fcB5+CrQq2KMOSbyTIzYuCVHP10XoS0R/ln7YOU5WoNS6/6L3GEdFWBaGYAAMErQ==",
+ "dev": true,
+ "license": "MIT AND ISC",
+ "peer": true,
+ "dependencies": {
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-ease": "^3.0.0",
+ "@types/d3-interpolate": "^3.0.1",
+ "@types/d3-scale": "^4.0.2",
+ "@types/d3-shape": "^3.1.0",
+ "@types/d3-time": "^3.0.0",
+ "@types/d3-timer": "^3.0.0",
+ "d3-array": "^3.1.6",
+ "d3-ease": "^3.0.1",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-shape": "^3.1.0",
+ "d3-time": "^3.0.0",
+ "d3-timer": "^3.0.1"
+ }
+ },
+ "node_modules/victory-voronoi-container": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-voronoi-container/-/victory-voronoi-container-37.3.2.tgz",
+ "integrity": "sha512-Y5NiUcVa6SlAMl5yAI5pRRBRCUCDHJHYeUMCiccTOjA+G2B2pUJkJ5NKeFzMLt7hW1LQv0nnRs9ywpMdViF8nQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "delaunay-find": "0.0.6",
+ "lodash": "^4.17.19",
+ "react-fast-compare": "^3.2.0",
+ "victory-core": "37.3.2",
+ "victory-tooltip": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
+ "node_modules/victory-zoom-container": {
+ "version": "37.3.2",
+ "resolved": "https://registry.npmjs.org/victory-zoom-container/-/victory-zoom-container-37.3.2.tgz",
+ "integrity": "sha512-znF3L6+LpQ8hN+7aW8RO+dsHPl1XsMAvf52IKc0OAXZzukIwx1+yW2/OLtHU7G0DzAl3Cxzt5BNd7jFLVXWQJw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.19",
+ "victory-core": "37.3.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0"
+ }
+ },
"node_modules/vscode-oniguruma": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
@@ -28033,29 +28891,39 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/zod": {
+ "version": "3.23.8",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
+ "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
"packages/module": {
"name": "@patternfly/react-data-view",
"version": "1.0.0-prerelease.0",
"license": "MIT",
"dependencies": {
- "@patternfly/react-component-groups": "6.0.0-prerelease.7",
- "@patternfly/react-core": "6.0.0-prerelease.21",
- "@patternfly/react-icons": "6.0.0-prerelease.7",
- "@patternfly/react-table": "6.0.0-prerelease.22",
+ "@patternfly/react-component-groups": "6.0.0",
+ "@patternfly/react-core": "6.0.0",
+ "@patternfly/react-icons": "6.0.0",
+ "@patternfly/react-table": "6.0.0",
"clsx": "^2.1.1",
"react-jss": "^10.10.0"
},
"devDependencies": {
- "@patternfly/documentation-framework": "6.0.0-alpha.117",
- "@patternfly/patternfly": "6.0.0-prerelease.15",
- "@patternfly/patternfly-a11y": "^4.3.1",
+ "@patternfly/documentation-framework": "6.0.6",
+ "@patternfly/patternfly": "6.0.0",
+ "@patternfly/patternfly-a11y": "^5.0.0",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router": "^6.23.0",
- "react-router-dom": "^6.23.0",
+ "react-router-dom": "^6.28.0",
"rimraf": "^5.0.5",
"typescript": "^5.4.5"
},
diff --git a/package.json b/package.json
index ab5c525..9cf31d7 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"eslint-config-standard-with-typescript": "^23.0.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-markdown": "^1.0.2",
- "eslint-plugin-n": "^17.13.1",
+ "eslint-plugin-n": "^15.7.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.2.0",
"eslint-plugin-react": "^7.34.3",
diff --git a/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.tsx b/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.tsx
index 7235165..86a68ad 100644
--- a/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.tsx
+++ b/packages/module/src/DataViewCheckboxFilter/DataViewCheckboxFilter.tsx
@@ -8,13 +8,13 @@ import {
MenuProps,
MenuToggle,
Popper,
- ToolbarChip,
+ ToolbarLabel,
ToolbarFilter,
} from '@patternfly/react-core';
import { FilterIcon } from '@patternfly/react-icons';
import { DataViewFilterOption } from '../DataViewFilters';
-const isToolbarChip = (chip: string | ToolbarChip): chip is ToolbarChip =>
+const isToolbarChip = (chip: string | ToolbarLabel): chip is ToolbarLabel =>
typeof chip === 'object' && 'key' in chip;
export const isDataViewFilterOption = (obj: unknown): obj is DataViewFilterOption =>
@@ -113,11 +113,11 @@ export const DataViewCheckboxFilter: React.FC = ({
{
+ labels={value.map(item => {
const activeOption = normalizeOptions.find(option => option.value === item);
return ({ key: activeOption?.value as string, node: activeOption?.label })
})}
- deleteChip={(_, chip) =>
+ deleteLabel={(_, chip) =>
onChange?.(undefined, value.filter(item => item !== (isToolbarChip(chip) ? chip.key : chip)))
}
categoryName={title}
diff --git a/packages/module/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap b/packages/module/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap
index e6cede5..1087ae1 100644
--- a/packages/module/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap
+++ b/packages/module/src/DataViewCheckboxFilter/__snapshots__/DataViewCheckboxFilter.test.tsx.snap
@@ -3,40 +3,40 @@
exports[`DataViewCheckboxFilter component should render correctly 1`] = `