diff --git a/netlify.toml b/netlify.toml index 3c01cb331e3..b09903ca426 100644 --- a/netlify.toml +++ b/netlify.toml @@ -13,6 +13,8 @@ # Default build command. command = "npm run build:storybook" + environment = { UI5_WEBCOMPONENTS_FOR_REACT_RELEASE_BUILD = "true" } + # Deploy Preview context: all deploys generated from a pull/merge request will # inherit these settings. [context.deploy-preview] diff --git a/packages/main/src/components/ActionSheet/ActionSheet.jss.ts b/packages/main/src/components/ActionSheet/ActionSheet.jss.ts index 44f5b200d0f..a4da89e9674 100644 --- a/packages/main/src/components/ActionSheet/ActionSheet.jss.ts +++ b/packages/main/src/components/ActionSheet/ActionSheet.jss.ts @@ -3,18 +3,12 @@ const styles = { * is being applied to the encapsulating ul element */ actionSheet: { - listStyleType: 'none', margin: 0, padding: '0.1875rem 0.375rem', - '&$tablet,&$phone': { - padding: '0.25rem 0.5rem' - }, '& ui5-button': { display: 'block' } - }, - phone: {}, - tablet: {} + } }; export default styles; diff --git a/packages/main/src/components/ActionSheet/ActionSheet.test.tsx b/packages/main/src/components/ActionSheet/ActionSheet.test.tsx index f98ea3a6d48..5ecd0c63dd1 100644 --- a/packages/main/src/components/ActionSheet/ActionSheet.test.tsx +++ b/packages/main/src/components/ActionSheet/ActionSheet.test.tsx @@ -41,7 +41,7 @@ describe('ActionSheet', () => { wrapper.update(); wrapper - .find('ui5-popover ui5-button') + .find('ui5-responsive-popover ui5-button') .first() .instance() // @ts-ignore @@ -63,14 +63,14 @@ describe('ActionSheet', () => { ); - expect(legacyRef.tagName).toEqual('UI5-POPOVER'); + expect(legacyRef.tagName).toEqual('UI5-RESPONSIVE-POPOVER'); }); test('Ref object', () => { const ref: RefObject = createRef(); const button = } - placement={select('placement', [PlacementType.Top, PlacementType.Bottom], PlacementType.Top)} - > - - - - -); +export const defaultStory = () => { + const actionSheetRef = useRef(); + const onButtonClick = useCallback( + (e) => { + actionSheetRef.current.open(e.target); + }, + [actionSheetRef] + ); + return ( + <> + + + + + + + + ); +}; defaultStory.story = { name: 'Default' }; diff --git a/packages/main/src/components/ActionSheet/index.tsx b/packages/main/src/components/ActionSheet/index.tsx index 20b06f3dcf5..58f20085c6d 100644 --- a/packages/main/src/components/ActionSheet/index.tsx +++ b/packages/main/src/components/ActionSheet/index.tsx @@ -1,20 +1,18 @@ import { addCustomCSS } from '@ui5/webcomponents-base/dist/Theming'; -import { Device } from '@ui5/webcomponents-react-base/lib/Device'; +import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper'; import { useConsolidatedRef } from '@ui5/webcomponents-react-base/lib/useConsolidatedRef'; import { usePassThroughHtmlProps } from '@ui5/webcomponents-react-base/lib/usePassThroughHtmlProps'; import { ButtonDesign } from '@ui5/webcomponents-react/lib/ButtonDesign'; import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; -import { Popover } from '@ui5/webcomponents-react/lib/Popover'; -import React, { Children, cloneElement, FC, forwardRef, ReactElement, ReactNode, RefObject } from 'react'; -import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; -import { CommonProps } from '../../interfaces/CommonProps'; -import { Ui5PopoverDomRef } from '../../interfaces/Ui5PopoverDomRef'; +import { ResponsivePopover } from '@ui5/webcomponents-react/lib/ResponsivePopover'; +import React, { Children, cloneElement, FC, forwardRef, ReactElement, RefObject } from 'react'; +import { Ui5ResponsivePopoverDomRef } from '../../interfaces/Ui5ResponsivePopoverDomRef'; import { ButtonPropTypes } from '../../webComponents/Button'; +import { ResponsivePopoverPropTypes } from '../../webComponents/ResponsivePopover'; import styles from './ActionSheet.jss'; -export interface ActionSheetPropTypes extends CommonProps { - openBy: ReactNode; +export interface ActionSheetPropTypes extends ResponsivePopoverPropTypes { placement?: PlacementType; children?: ReactElement | ReactElement[]; } @@ -34,8 +32,27 @@ addCustomCSS( * import { ActionSheet } from '@ui5/webcomponents-react/lib/ActionSheet'; */ const ActionSheet: FC = forwardRef( - (props: ActionSheetPropTypes, ref: RefObject) => { - const { children, placement, openBy, style, slot, className } = props; + (props: ActionSheetPropTypes, ref: RefObject) => { + const { + children, + style, + slot, + className, + allowTargetOverlap, + headerText, + horizontalAlign, + initialFocus, + modal, + noArrow, + placementType, + verticalAlign, + footer, + header, + onAfterClose, + onAfterOpen, + onBeforeClose, + onBeforeOpen + } = props; const classes = useStyles(); @@ -43,13 +60,8 @@ const ActionSheet: FC = forwardRef( if (className) { actionSheetClasses.put(className); } - if (Device.system.tablet) { - actionSheetClasses.put(classes.tablet); - } else if (Device.system.phone) { - actionSheetClasses.put(classes.phone); - } - const popoverRef: RefObject = useConsolidatedRef(ref); + const popoverRef: RefObject = useConsolidatedRef(ref); const onActionButtonClicked = (handler) => (e) => { popoverRef.current.close(); @@ -67,20 +79,37 @@ const ActionSheet: FC = forwardRef( }); }; - const passThroughProps = usePassThroughHtmlProps(props); + const passThroughProps = usePassThroughHtmlProps(props, [ + 'onAfterClose', + 'onAfterOpen', + 'onBeforeClose', + 'onBeforeOpen' + ]); return ( - {Children.map(children, renderActionSheetButton)} - + ); } ); diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx b/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx index 147110066e6..ad70972d699 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx @@ -230,7 +230,7 @@ describe('AnalyticalTable', () => { const wrapper = mount(); // get first column of the table and simulate dragging of it - let componentDrag = wrapper.find('div[role="columnheader"] div[draggable]').at(0); + let componentDrag = wrapper.find('div[role="columnheader"][draggable]').at(0); let inst = componentDrag.instance(); // @ts-ignore let dragColumnId = inst.dataset.columnId; @@ -248,7 +248,7 @@ describe('AnalyticalTable', () => { dataTransfer.getData = () => { return dragColumnId; }; - let componentDrop = wrapper.find('div[role="columnheader"] div[draggable]').at(1); + let componentDrop = wrapper.find('div[role="columnheader"][draggable]').at(1); // @ts-ignore componentDrop.simulate('drop', { dataTransfer: dataTransfer }); diff --git a/packages/main/src/components/AnalyticalTable/ColumnHeader/ColumnHeaderModal.tsx b/packages/main/src/components/AnalyticalTable/ColumnHeader/ColumnHeaderModal.tsx index 4fc340f893a..384c813369f 100644 --- a/packages/main/src/components/AnalyticalTable/ColumnHeader/ColumnHeaderModal.tsx +++ b/packages/main/src/components/AnalyticalTable/ColumnHeader/ColumnHeaderModal.tsx @@ -10,30 +10,26 @@ import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; import { Popover } from '@ui5/webcomponents-react/lib/Popover'; import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign'; import { StandardListItem } from '@ui5/webcomponents-react/lib/StandardListItem'; -import React, { CSSProperties, FC, ReactNode, RefObject, useCallback, useRef } from 'react'; +import React, { CSSProperties, forwardRef, RefObject, useCallback } from 'react'; import { Ui5PopoverDomRef } from '../../../interfaces/Ui5PopoverDomRef'; import { ColumnType } from '../types/ColumnType'; export interface ColumnHeaderModalProperties { - openBy: ReactNode; column: ColumnType; - style: CSSProperties; onSort?: (e: CustomEvent<{ column: unknown; sortDirection: string }>) => void; onGroupBy?: (e: CustomEvent<{ column: unknown; isGrouped: boolean }>) => void; } const staticStyle = { fontWeight: 'normal' }; -export const ColumnHeaderModal: FC = (props: ColumnHeaderModalProperties) => { - const { column, style, openBy, onSort, onGroupBy } = props; +export const ColumnHeaderModal = forwardRef((props: ColumnHeaderModalProperties, ref: RefObject) => { + const { column, onSort, onGroupBy } = props; const showFilter = column.canFilter; const showGroup = column.canGroupBy; const showSort = column.canSort; const { Filter } = column; - const popoverRef: RefObject = useRef(); - const handleSort = useCallback( (e) => { const sortType = e.detail.item.getAttribute('data-sort'); @@ -85,11 +81,11 @@ export const ColumnHeaderModal: FC = (props: Column } break; } - if (popoverRef.current) { - popoverRef.current.close(); + if (ref.current) { + ref.current.close(); } }, - [column, popoverRef, onGroupBy, onSort] + [column, ref, onGroupBy, onSort] ); const isSortedAscending = column.isSorted && column.isSortedDesc === false; @@ -97,12 +93,10 @@ export const ColumnHeaderModal: FC = (props: Column return ( @@ -130,7 +124,7 @@ export const ColumnHeaderModal: FC = (props: Column - + )} @@ -142,4 +136,5 @@ export const ColumnHeaderModal: FC = (props: Column ); -}; +}); +ColumnHeaderModal.displayName = 'ColumnHeaderModal'; diff --git a/packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx b/packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx index 075cfe396e6..b542e7904d1 100644 --- a/packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx +++ b/packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx @@ -3,10 +3,19 @@ import '@ui5/webcomponents-icons/dist/icons/group-2'; import '@ui5/webcomponents-icons/dist/icons/sort-ascending'; import '@ui5/webcomponents-icons/dist/icons/sort-descending'; import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; -import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper'; import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; import { Icon } from '@ui5/webcomponents-react/lib/Icon'; -import React, { CSSProperties, DragEventHandler, FC, ReactNode, ReactNodeArray, useMemo } from 'react'; +import React, { + CSSProperties, + DragEventHandler, + FC, + ReactNode, + ReactNodeArray, + useCallback, + useMemo, + useRef +} from 'react'; +import { Ui5PopoverDomRef } from '../../../interfaces/Ui5PopoverDomRef'; import { ColumnType } from '../types/ColumnType'; import { ColumnHeaderModal } from './ColumnHeaderModal'; @@ -47,7 +56,10 @@ const styles = { textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '100%', - position: 'relative' + position: 'relative', + width: '100%', + overflowX: 'hidden', + padding: `0 0.5rem` }, iconContainer: { display: 'inline-block', @@ -101,67 +113,18 @@ export const ColumnHeader: FC = (props: ColumnHeaderProps) => role } = props; - const openBy = useMemo(() => { - if (!column) return null; + const isFiltered = column.filterValue && column.filterValue.length > 0; + const desc = column.isSortedDesc; - const isFiltered = column.filterValue && column.filterValue.length > 0; - const desc = column.isSortedDesc; - - const classNames = StyleClassHelper.of(classes.header); - - const sortingIcon = column.isSorted ? : null; - const filterIcon = isFiltered ? : null; - const groupingIcon = column.isGrouped ? : null; - - return ( -
- - {children} - -
- {filterIcon} - {sortingIcon} - {groupingIcon} -
-
- ); - }, [ - classes, - column.filterValue, - column.isSorted, - column.isGrouped, - column.isSortedDesc, - children, - isDraggable, - onDragEnter, - onDragOver, - onDragStart, - onDrop, - onDragEnd, - id - ]); + const sortingIcon = column.isSorted ? : null; + const filterIcon = isFiltered ? : null; + const groupingIcon = column.isGrouped ? : null; const isResizable = !isLastColumn && column.canResize; + const hasPopover = column.canGroupBy || column.canSort || column.canFilter; const innerStyle: CSSProperties = useMemo(() => { const modifiedStyles: CSSProperties = { - width: '100%', - fontWeight: 'normal', - cursor: 'pointer', - height: '100%', - overflowX: 'hidden', - padding: `0 0.5rem` + cursor: hasPopover ? 'pointer' : 'auto' }; if (isResizable) { modifiedStyles.maxWidth = `calc(100% - 16px)`; @@ -173,17 +136,49 @@ export const ColumnHeader: FC = (props: ColumnHeaderProps) => modifiedStyles.padding = 0; } return modifiedStyles; - }, [isResizable, dragOver]); + }, [isResizable, dragOver, hasPopover]); + + const popoverRef = useRef(null); + + const onOpenPopover = useCallback( + (e) => { + if (popoverRef.current && hasPopover) { + popoverRef.current.openBy(e.target); + } + }, + [popoverRef, hasPopover] + ); if (!column) return null; return ( -
- {column.canGroupBy || column.canSort || column.canFilter ? ( - - ) : ( -
{openBy}
- )} +
+
+ + {children} + +
+ {filterIcon} + {sortingIcon} + {groupingIcon} +
+
+ {hasPopover && } {column.getResizerProps && (
)} diff --git a/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap b/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap index af5f82e69fd..8e34828fc77 100644 --- a/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap +++ b/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap @@ -22,7 +22,6 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` class="AnalyticalTable-table-0" data-per-page="15" role="grid" - tabindex="0" >
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
+
- -
-
+ class="TableColumnHeader-iconContainer-0" + />
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Age + +
-
- - Age - -
-
+ Name + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- -
-
-
+ +
+
- -
-
+ class="TableColumnHeader-iconContainer-0" + />
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
-
- - Name - -
-
+ Name + +
-
- - Age - -
-
+ Age + +
-
- - Friend Name - -
-
+ Friend Name + +
-
- - - Friend Age - + + Friend Age -
-
+
+
= forwardRef((props: TableProps, ref: Ref< 'onLoadMore' ]); - const currentlyFocusedCell = useRef(null); - const onTableFocus = useCallback( - (e) => { - if (e.target.getAttribute('role') === 'grid') { - const firstCell: HTMLDivElement = e.target.querySelector( - 'div[role="row"]:first-child div[role="cell"]:first-child' - ); - firstCell.tabIndex = 0; - firstCell.focus(); - currentlyFocusedCell.current = firstCell; - } - }, - [currentlyFocusedCell] - ); - - const onKeyboardNavigation = useCallback( - (e) => { - if (currentlyFocusedCell.current) { - switch (e.key) { - case 'ArrowRight': { - const newElement = currentlyFocusedCell.current.nextElementSibling as HTMLDivElement; - if (newElement) { - currentlyFocusedCell.current.tabIndex = -1; - newElement.tabIndex = 0; - newElement.focus(); - currentlyFocusedCell.current = newElement; - } - break; - } - case 'ArrowLeft': { - const newElement = currentlyFocusedCell.current.previousElementSibling as HTMLDivElement; - if (newElement) { - currentlyFocusedCell.current.tabIndex = -1; - newElement.tabIndex = 0; - newElement.focus(); - currentlyFocusedCell.current = newElement; - } - break; - } - case 'ArrowDown': { - const nextRow = currentlyFocusedCell.current.parentElement.nextElementSibling as HTMLDivElement; - if (nextRow) { - currentlyFocusedCell.current.tabIndex = -1; - const currentColumnIndex = currentlyFocusedCell.current.getAttribute('aria-colindex'); - const newElement: HTMLDivElement = nextRow.querySelector(`div[aria-colindex="${currentColumnIndex}"]`); - newElement.tabIndex = 0; - newElement.focus(); - currentlyFocusedCell.current = newElement; - } - break; - } - case 'ArrowUp': { - const previousRow = currentlyFocusedCell.current.parentElement.previousElementSibling as HTMLDivElement; - if (previousRow) { - currentlyFocusedCell.current.tabIndex = -1; - const currentColumnIndex = currentlyFocusedCell.current.getAttribute('aria-colindex'); - const newElement: HTMLDivElement = previousRow.querySelector( - `div[aria-colindex="${currentColumnIndex}"]` - ); - newElement.tabIndex = 0; - newElement.focus(); - currentlyFocusedCell.current = newElement; - } - break; - } - } - } - }, - [currentlyFocusedCell] - ); - const inlineStyle = useMemo(() => { if(tableState.tableClientWidth > 0) { return style; @@ -407,7 +336,7 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< visibility: 'hidden' as 'hidden' }; }, [tableState.tableClientWidth, style]); - + return (
{title && {title}} @@ -420,9 +349,6 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< aria-rowcount={rows.length} aria-colcount={tableInternalColumns.length} data-per-page={visibleRows} - tabIndex={0} - onFocus={onTableFocus} - onKeyDown={onKeyboardNavigation} > {headerGroups.map((headerGroup) => { let headerProps = {}; diff --git a/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableBody.tsx b/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableBody.tsx index 427c749fd58..587b70850b3 100644 --- a/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableBody.tsx +++ b/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableBody.tsx @@ -1,10 +1,10 @@ import '@ui5/webcomponents-icons/dist/icons/navigation-down-arrow'; import '@ui5/webcomponents-icons/dist/icons/navigation-right-arrow'; import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper'; +import { GlobalStyleClasses } from '@ui5/webcomponents-react/lib/GlobalStyleClasses'; import { TableSelectionMode } from '@ui5/webcomponents-react/lib/TableSelectionMode'; -import React, { useCallback, useMemo, useRef } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { FixedSizeList } from 'react-window'; -import { GlobalStyleClasses } from '@ui5/webcomponents-react/lib/GlobalStyleClasses'; import { VirtualTableRow } from './VirtualTableRow'; interface VirtualTableBodyProps { @@ -95,6 +95,86 @@ export const VirtualTableBody = (props: VirtualTableBodyProps) => { [infiniteScroll, infiniteScrollThreshold, onLoadMore, rows.length, internalRowHeight, firedInfiniteLoadEvents] ); + const currentlyFocusedCell = useRef(null); + const onTableFocus = useCallback( + (e) => { + const firstCell: HTMLDivElement = e.target.querySelector( + 'div[role="row"]:first-child div[role="cell"]:first-child' + ); + firstCell.tabIndex = 0; + firstCell.focus(); + currentlyFocusedCell.current = firstCell; + }, + [currentlyFocusedCell] + ); + + const onKeyboardNavigation = useCallback( + (e) => { + if (currentlyFocusedCell.current) { + switch (e.key) { + case 'ArrowRight': { + const newElement = currentlyFocusedCell.current.nextElementSibling as HTMLDivElement; + if (newElement) { + currentlyFocusedCell.current.tabIndex = -1; + newElement.tabIndex = 0; + newElement.focus(); + currentlyFocusedCell.current = newElement; + } + break; + } + case 'ArrowLeft': { + const newElement = currentlyFocusedCell.current.previousElementSibling as HTMLDivElement; + if (newElement) { + currentlyFocusedCell.current.tabIndex = -1; + newElement.tabIndex = 0; + newElement.focus(); + currentlyFocusedCell.current = newElement; + } + break; + } + case 'ArrowDown': { + const nextRow = currentlyFocusedCell.current.parentElement.nextElementSibling as HTMLDivElement; + if (nextRow) { + currentlyFocusedCell.current.tabIndex = -1; + const currentColumnIndex = currentlyFocusedCell.current.getAttribute('aria-colindex'); + const newElement: HTMLDivElement = nextRow.querySelector(`div[aria-colindex="${currentColumnIndex}"]`); + newElement.tabIndex = 0; + newElement.focus(); + currentlyFocusedCell.current = newElement; + } + break; + } + case 'ArrowUp': { + const previousRow = currentlyFocusedCell.current.parentElement.previousElementSibling as HTMLDivElement; + if (previousRow) { + currentlyFocusedCell.current.tabIndex = -1; + const currentColumnIndex = currentlyFocusedCell.current.getAttribute('aria-colindex'); + const newElement: HTMLDivElement = previousRow.querySelector( + `div[aria-colindex="${currentColumnIndex}"]` + ); + newElement.tabIndex = 0; + newElement.focus(); + currentlyFocusedCell.current = newElement; + } + break; + } + } + } + }, + [currentlyFocusedCell] + ); + + useEffect(() => { + if (innerDivRef.current) { + innerDivRef.current.tabIndex = 0; + innerDivRef.current.addEventListener('keydown', onKeyboardNavigation); + innerDivRef.current.addEventListener('focus', onTableFocus); + } + return () => { + innerDivRef.current.removeEventListener('keydown', onKeyboardNavigation); + }; + }, [onKeyboardNavigation, reactWindowRef, onTableFocus]); + return ( { ); const component = wrapper .find('ui5-button') - .first() + .last() .instance() as any; component.fireEvent('click'); expect(wrapper.render()).toMatchSnapshot(); diff --git a/packages/main/src/components/FilterBar/__snapshots__/FilterBar.test.tsx.snap b/packages/main/src/components/FilterBar/__snapshots__/FilterBar.test.tsx.snap index 790f864e1da..405bbb8dd39 100644 --- a/packages/main/src/components/FilterBar/__snapshots__/FilterBar.test.tsx.snap +++ b/packages/main/src/components/FilterBar/__snapshots__/FilterBar.test.tsx.snap @@ -8,24 +8,20 @@ exports[`FilterBar Hide Filter Bar 1`] = ` class="FilterBar-filterBarHeader-0" >
-
- - Variant 1 - - -
+ Variant 1 + +
- - +
@@ -71,12 +67,12 @@ exports[`FilterBar Hide Filter Bar 1`] = ` design="Transparent" icon="" > - Hide Filter Bar + Show Filter Bar
-
- - Variant 1 - - -
+ Variant 1 + +
- - +
@@ -305,24 +297,20 @@ exports[`FilterBar Select Filter Item 1`] = ` class="FilterBar-filterBarHeader-0" >
-
- - Variant 1 - - -
+ Variant 1 + +
- - +
diff --git a/packages/main/src/components/MessageBox/__snapshots__/MessageBox.test.tsx.snap b/packages/main/src/components/MessageBox/__snapshots__/MessageBox.test.tsx.snap index de7040ec1c8..328cb151b8d 100644 --- a/packages/main/src/components/MessageBox/__snapshots__/MessageBox.test.tsx.snap +++ b/packages/main/src/components/MessageBox/__snapshots__/MessageBox.test.tsx.snap @@ -3,7 +3,7 @@ exports[`MessageBox Confirm - Cancel 1`] = `
) => void; + onClose: (event: CustomEvent<{ action: MessageBoxActions }>) => void; } const useStyles = createComponentStyles(styles, { name: 'MessageBox' }); @@ -103,13 +104,24 @@ const MessageBox: FC = forwardRef((props: MessageBoxPropTyp [onClose] ); + const dialogRef = useConsolidatedRef(ref); + + useEffect(() => { + if (dialogRef.current) { + if (open) { + dialogRef.current.open(); + } else { + dialogRef.current.close(); + } + } + }, [open, dialogRef]); + const passThroughProps = usePassThroughHtmlProps(props, ['onClose']); return ( = forwardRef( {displayedIcon}
{createPortal( - + {text} diff --git a/packages/main/src/components/VariantManagement/__snapshots__/VariantManagement.test.tsx.snap b/packages/main/src/components/VariantManagement/__snapshots__/VariantManagement.test.tsx.snap index b860208e125..0cb4bd1dac9 100644 --- a/packages/main/src/components/VariantManagement/__snapshots__/VariantManagement.test.tsx.snap +++ b/packages/main/src/components/VariantManagement/__snapshots__/VariantManagement.test.tsx.snap @@ -3,24 +3,20 @@ exports[`VariantManagement Render without crashing 1`] = ` Array [
-
- - Variant 1 - - -
+ Variant 1 + +
, - - , + , ] `; diff --git a/packages/main/src/components/VariantManagement/index.tsx b/packages/main/src/components/VariantManagement/index.tsx index 9b2ba3664ca..af53980c181 100644 --- a/packages/main/src/components/VariantManagement/index.tsx +++ b/packages/main/src/components/VariantManagement/index.tsx @@ -1,20 +1,21 @@ import '@ui5/webcomponents-icons/dist/icons/navigation-down-arrow'; -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; +import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; import { usePassThroughHtmlProps } from '@ui5/webcomponents-react-base/lib/usePassThroughHtmlProps'; +import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { Button } from '@ui5/webcomponents-react/lib/Button'; import { ButtonDesign } from '@ui5/webcomponents-react/lib/ButtonDesign'; import { List } from '@ui5/webcomponents-react/lib/List'; import { ListItemTypes } from '@ui5/webcomponents-react/lib/ListItemTypes'; import { ListMode } from '@ui5/webcomponents-react/lib/ListMode'; import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; -import { Popover } from '@ui5/webcomponents-react/lib/Popover'; +import { ResponsivePopover } from '@ui5/webcomponents-react/lib/ResponsivePopover'; import { StandardListItem } from '@ui5/webcomponents-react/lib/StandardListItem'; import { Title } from '@ui5/webcomponents-react/lib/Title'; import { TitleLevel } from '@ui5/webcomponents-react/lib/TitleLevel'; -import React, { FC, forwardRef, Ref, useCallback, useEffect, useMemo, useState } from 'react'; -import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; +import React, { FC, forwardRef, Ref, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { CommonProps } from '../../interfaces/CommonProps'; +import { Ui5ResponsivePopoverDomRef } from '../../interfaces/Ui5ResponsivePopoverDomRef'; export interface VariantItem { key: string; @@ -84,8 +85,10 @@ const VariantManagement: FC = forwardRef( closeOnItemSelect, disabled } = props; + const classes = useStyles(); - const [open, setOpen] = useState(false); + const popoverRef = useRef(null); + const [selectedKey, setSelectedKey] = useState( initialSelectedKey ? initialSelectedKey : variantItems?.[0]?.key ?? null ); @@ -101,12 +104,15 @@ const VariantManagement: FC = forwardRef( }, [initialSelectedKey, setSelectedKey]); const handleCancelButtonClick = useCallback(() => { - setOpen(false); - }, [setOpen]); + popoverRef.current.close(); + }, [popoverRef]); - const handleAfterOpen = useCallback(() => { - setOpen(true); - }, [setOpen]); + const handleOpenVariantManagement = useCallback( + (e) => { + popoverRef.current.open(e.target); + }, + [popoverRef] + ); const footerButtons = useMemo(() => { return ( @@ -120,23 +126,12 @@ const VariantManagement: FC = forwardRef( return variantItems.find((item) => item.key === key); }; - const variantManagementButton = useMemo(() => { - const selectedItem = getItemByKey(selectedKey) || variantItems[0]; - - let textClasses = classes.VariantManagementText; - if (disabled) { - textClasses += ` ${classes.disabled}`; - } + const selectedItem = getItemByKey(selectedKey) || variantItems[0]; - return ( -
- - {selectedItem.label} - -
- ); - }, [classes, variantItems, level, selectedKey, disabled]); + let textClasses = classes.VariantManagementText; + if (disabled) { + textClasses += ` ${classes.disabled}`; + } const handleVariantItemSelect = useCallback( (event) => { @@ -153,35 +148,43 @@ const VariantManagement: FC = forwardRef( const passThroughProps = usePassThroughHtmlProps(props, ['onSelect']); return ( - - - {variantItems.map((item) => ( - - {item.label} - - ))} - - + <> +
+ + {selectedItem.label} + +
+ + + {variantItems.map((item) => ( + + {item.label} + + ))} + + + ); } ); diff --git a/packages/main/src/webComponents/Dialog/Dialog.stories.tsx b/packages/main/src/webComponents/Dialog/Dialog.stories.tsx index 2c238a97b0a..190c675397f 100644 --- a/packages/main/src/webComponents/Dialog/Dialog.stories.tsx +++ b/packages/main/src/webComponents/Dialog/Dialog.stories.tsx @@ -1,29 +1,40 @@ import { action } from '@storybook/addon-actions'; import { boolean, text } from '@storybook/addon-knobs'; +import { Button } from '@ui5/webcomponents-react/lib/Button'; import { Dialog } from '@ui5/webcomponents-react/lib/Dialog'; -import React from 'react'; +import React, { useCallback, useRef } from 'react'; export default { title: 'UI5 Web Components / Dialog', component: Dialog }; -export const generatedDefaultStory = () => ( - Footer} - header={null} - onAfterClose={action('onAfterClose')} - onAfterOpen={action('onAfterOpen')} - onBeforeClose={action('onBeforeClose')} - onBeforeOpen={action('onBeforeOpen')} - open={boolean('open', true)} - > - Some Content - -); +export const generatedDefaultStory = () => { + const dialogRef = useRef(); + const onButtonClick = useCallback(() => { + dialogRef.current.open(); + }, [dialogRef]); + + return ( + <> + + Footer} + header={null} + onAfterClose={action('onAfterClose')} + onAfterOpen={action('onAfterOpen')} + onBeforeClose={action('onBeforeClose')} + onBeforeOpen={action('onBeforeOpen')} + > + Some Content + + + ); +}; generatedDefaultStory.story = { name: 'Generated default story' diff --git a/packages/main/src/webComponents/Dialog/__snapshots__/Dialog.test.tsx.snap b/packages/main/src/webComponents/Dialog/__snapshots__/Dialog.test.tsx.snap index 71b22b10a05..ad48f7ff869 100644 --- a/packages/main/src/webComponents/Dialog/__snapshots__/Dialog.test.tsx.snap +++ b/packages/main/src/webComponents/Dialog/__snapshots__/Dialog.test.tsx.snap @@ -3,5 +3,6 @@ exports[`Dialog Basic Test (generated) 1`] = ` `; diff --git a/packages/main/src/webComponents/Dialog/index.tsx b/packages/main/src/webComponents/Dialog/index.tsx index 8d83870482c..e90184524ea 100644 --- a/packages/main/src/webComponents/Dialog/index.tsx +++ b/packages/main/src/webComponents/Dialog/index.tsx @@ -1,9 +1,6 @@ -import { useConsolidatedRef } from '@ui5/webcomponents-react-base/lib/useConsolidatedRef'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import UI5Dialog from '@ui5/webcomponents/dist/Dialog'; -import React, { FC, ReactNode, RefForwardingComponent, RefObject, useEffect } from 'react'; -import { Ui5DialogDomRef } from '../../interfaces/Ui5DialogDomRef'; -import { Ui5DomRef } from '../../interfaces/Ui5DomRef'; +import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface DialogPropTypes extends WithWebComponentPropTypes { @@ -20,17 +17,17 @@ export interface DialogPropTypes extends WithWebComponentPropTypes { */ initialFocus?: string; /** - * Defines the header HTML Element. + * Defines the content of the Web Component. */ - header?: ReactNode | ReactNode[]; + children?: ReactNode | ReactNode[]; /** * Defines the footer HTML Element. */ footer?: ReactNode | ReactNode[]; /** - * Defines the content of the Web Component. + * Defines the header HTML Element. */ - children?: ReactNode | ReactNode[]; + header?: ReactNode | ReactNode[]; /** * Fired after the component is closed. */ @@ -47,40 +44,21 @@ export interface DialogPropTypes extends WithWebComponentPropTypes { * Fired before the component is opened. */ onBeforeOpen?: (event: CustomEvent<{}>) => void; - open?: boolean; } -const InnerDialog: RefForwardingComponent = withWebComponent(UI5Dialog); - /** * import { Dialog } from '@ui5/webcomponents-react/lib/Dialog'; *
* UI5 Web Components Playground */ -const Dialog: FC = React.forwardRef( - (props: DialogPropTypes, dialogRef: RefObject) => { - const localDialogRef = useConsolidatedRef(dialogRef); - - const setDialogOpen = (open) => { - if (!localDialogRef.current || !localDialogRef.current.open) { - return; - } - return open ? localDialogRef.current.open() : localDialogRef.current.close(); - }; - - useEffect(() => { - setDialogOpen(props.open); - }, [props.open]); +const Dialog: FC = withWebComponent(UI5Dialog); - return ; - } -); +Dialog.displayName = 'Dialog'; Dialog.defaultProps = { - initialFocus: null, - headerText: '' + stretch: false, + headerText: '', + initialFocus: '' }; -Dialog.displayName = 'Dialog'; - export { Dialog }; diff --git a/packages/main/src/webComponents/Popover/Popover.stories.tsx b/packages/main/src/webComponents/Popover/Popover.stories.tsx index 0cdd7dcf000..09ca66044f9 100644 --- a/packages/main/src/webComponents/Popover/Popover.stories.tsx +++ b/packages/main/src/webComponents/Popover/Popover.stories.tsx @@ -5,46 +5,59 @@ import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; import { Popover } from '@ui5/webcomponents-react/lib/Popover'; import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign'; import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; -import React from 'react'; +import React, { useCallback, useRef } from 'react'; export default { title: 'UI5 Web Components / Popover', component: Popover }; -export const generatedDefaultStory = () => ( - { + const popoverRef = useRef(); + const onButtonClick = useCallback( + (e) => { + popoverRef.current.openBy(e.target); + }, + [popoverRef] + ); + + return ( + <> + + + +
+ } + header={null} + onAfterClose={action('onAfterClose')} + onAfterOpen={action('onAfterOpen')} + onBeforeClose={action('onBeforeClose')} + onBeforeOpen={action('onBeforeOpen')} > - -
- } - header={null} - onAfterClose={action('onAfterClose')} - onAfterOpen={action('onAfterOpen')} - onBeforeClose={action('onBeforeClose')} - onBeforeOpen={action('onBeforeOpen')} - openBy={} - > - Some Content - -); + Some Content + + + ); +}; generatedDefaultStory.story = { name: 'Generated default story' diff --git a/packages/main/src/webComponents/Popover/index.tsx b/packages/main/src/webComponents/Popover/index.tsx index 52055ffd6dc..7ffc8d32b6d 100644 --- a/packages/main/src/webComponents/Popover/index.tsx +++ b/packages/main/src/webComponents/Popover/index.tsx @@ -1,12 +1,9 @@ -import { useConsolidatedRef } from '@ui5/webcomponents-react-base/lib/useConsolidatedRef'; import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign'; import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import UI5Popover from '@ui5/webcomponents/dist/Popover'; -import React, { FC, ReactNode, RefObject, useCallback, useEffect, useMemo, useRef } from 'react'; -import { Ui5PopoverDomRef } from '../../interfaces/Ui5PopoverDomRef'; -import { UI5WebComponentsReactPopoverPropTypes } from '../../interfaces/UI5WebComponentsReactPopoverPropTypes'; +import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface PopoverPropTypes extends WithWebComponentPropTypes { @@ -43,17 +40,17 @@ export interface PopoverPropTypes extends WithWebComponentPropTypes { */ verticalAlign?: PopoverVerticalAlign; /** - * Defines the header HTML Element. + * Defines the content of the Web Component. */ - header?: ReactNode | ReactNode[]; + children?: ReactNode | ReactNode[]; /** * Defines the footer HTML Element. */ footer?: ReactNode | ReactNode[]; /** - * Defines the content of the Web Component. + * Defines the header HTML Element. */ - children?: ReactNode | ReactNode[]; + header?: ReactNode | ReactNode[]; /** * Fired after the component is closed. */ @@ -72,66 +69,14 @@ export interface PopoverPropTypes extends WithWebComponentPropTypes { onBeforeOpen?: (event: CustomEvent<{}>) => void; } -const InternalPopover = withWebComponent(UI5Popover); - /** * import { Popover } from '@ui5/webcomponents-react/lib/Popover'; *
* UI5 Web Components Playground */ -const Popover: FC = React.forwardRef( - (props: PopoverPropTypes & UI5WebComponentsReactPopoverPropTypes, givenRef: RefObject) => { - const { propagateOpenByClickEvent, openBy, openByStyle, open, ...rest } = props; +const Popover: FC = withWebComponent(UI5Popover); - const openByRef: RefObject = useRef(null); - - const internalPopoverRef = useConsolidatedRef(givenRef); - - const handleOpenPopover = useCallback( - (e) => { - if (internalPopoverRef.current) { - internalPopoverRef.current.openBy(openByRef.current); - } - if (e && !propagateOpenByClickEvent) { - e.stopPropagation(); - } - }, - [internalPopoverRef, openByRef] - ); - - const closePopover = useCallback(() => { - if (internalPopoverRef.current) { - internalPopoverRef.current.close(); - } - }, [internalPopoverRef]); - - useEffect(() => { - if (open) { - handleOpenPopover(null); - } else { - closePopover(); - } - }, [open]); - - const style = useMemo(() => { - return { - display: 'inline-block', - ...openByStyle - }; - }, [openByStyle]); - - return ( - <> - {openBy && ( -
- {openBy} -
- )} - - - ); - } -); +Popover.displayName = 'Popover'; Popover.defaultProps = { allowTargetOverlap: false, @@ -140,10 +85,7 @@ Popover.defaultProps = { modal: false, noArrow: false, placementType: PlacementType.Right, - verticalAlign: PopoverVerticalAlign.Center, - propagateOpenByClickEvent: true + verticalAlign: PopoverVerticalAlign.Center }; -Popover.displayName = 'Popover'; - export { Popover }; diff --git a/packages/main/src/webComponents/ResponsivePopover/ResponsivePopover.stories.tsx b/packages/main/src/webComponents/ResponsivePopover/ResponsivePopover.stories.tsx index a0c7e76e760..42db94162d2 100644 --- a/packages/main/src/webComponents/ResponsivePopover/ResponsivePopover.stories.tsx +++ b/packages/main/src/webComponents/ResponsivePopover/ResponsivePopover.stories.tsx @@ -5,46 +5,59 @@ import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign'; import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; import { ResponsivePopover } from '@ui5/webcomponents-react/lib/ResponsivePopover'; -import React from 'react'; +import React, { useCallback, useRef } from 'react'; export default { title: 'UI5 Web Components / ResponsivePopover', component: ResponsivePopover }; -export const generatedDefaultStory = () => ( - { + const popoverRef = useRef(); + const onButtonClick = useCallback( + (e) => { + popoverRef.current.open(e.target); + }, + [popoverRef] + ); + + return ( + <> + + + +
+ } + header={null} + onAfterClose={action('onAfterClose')} + onAfterOpen={action('onAfterOpen')} + onBeforeClose={action('onBeforeClose')} + onBeforeOpen={action('onBeforeOpen')} > - -
- } - header={null} - onAfterClose={action('onAfterClose')} - onAfterOpen={action('onAfterOpen')} - onBeforeClose={action('onBeforeClose')} - onBeforeOpen={action('onBeforeOpen')} - openBy={} - > - Some Content - -); + Some Content + + + ); +}; generatedDefaultStory.story = { name: 'Generated default story' diff --git a/packages/main/src/webComponents/ResponsivePopover/index.tsx b/packages/main/src/webComponents/ResponsivePopover/index.tsx index a1cf534f479..2a2e0417bff 100644 --- a/packages/main/src/webComponents/ResponsivePopover/index.tsx +++ b/packages/main/src/webComponents/ResponsivePopover/index.tsx @@ -1,12 +1,9 @@ -import { useConsolidatedRef } from '@ui5/webcomponents-react-base/lib/useConsolidatedRef'; import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign'; import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import UI5ResponsivePopover from '@ui5/webcomponents/dist/ResponsivePopover'; -import React, { FC, ReactNode, RefObject, useCallback, useEffect, useMemo, useRef } from 'react'; -import { Ui5ResponsivePopoverDomRef } from '../../interfaces/Ui5ResponsivePopoverDomRef'; -import { UI5WebComponentsReactPopoverPropTypes } from '../../interfaces/UI5WebComponentsReactPopoverPropTypes'; +import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface ResponsivePopoverPropTypes extends WithWebComponentPropTypes { @@ -43,17 +40,17 @@ export interface ResponsivePopoverPropTypes extends WithWebComponentPropTypes { */ verticalAlign?: PopoverVerticalAlign; /** - * Defines the header HTML Element. + * Defines the content of the Web Component. */ - header?: ReactNode | ReactNode[]; + children?: ReactNode | ReactNode[]; /** * Defines the footer HTML Element. */ footer?: ReactNode | ReactNode[]; /** - * Defines the content of the Web Component. + * Defines the header HTML Element. */ - children?: ReactNode | ReactNode[]; + header?: ReactNode | ReactNode[]; /** * Fired after the component is closed. */ @@ -72,67 +69,13 @@ export interface ResponsivePopoverPropTypes extends WithWebComponentPropTypes { onBeforeOpen?: (event: CustomEvent<{}>) => void; } -const ResponsivePopoverWebComponent = withWebComponent(UI5ResponsivePopover); - /** * import { ResponsivePopover } from '@ui5/webcomponents-react/lib/ResponsivePopover'; *
* UI5 Web Components Playground */ -const ResponsivePopover: FC = React.forwardRef( - ( - props: ResponsivePopoverPropTypes & UI5WebComponentsReactPopoverPropTypes, - givenRef: RefObject - ) => { - const { propagateOpenByClickEvent, openBy, openByStyle, open, ...rest } = props; - const openByRef: RefObject = useRef(null); - - const internalPopoverRef = useConsolidatedRef(givenRef); - - const handleOpenPopover = useCallback( - (e) => { - if (internalPopoverRef.current) { - internalPopoverRef.current.open(openByRef.current); - } - if (e && !propagateOpenByClickEvent) { - e.stopPropagation(); - } - }, - [internalPopoverRef, openByRef] - ); - - const closePopover = useCallback(() => { - if (internalPopoverRef.current) { - internalPopoverRef.current.close(); - } - }, [internalPopoverRef]); - - useEffect(() => { - if (open) { - handleOpenPopover(null); - } else { - closePopover(); - } - }, [open]); - - const style = useMemo(() => { - return { - display: 'inline-block', - ...openByStyle - }; - }, [openByStyle]); - - return ( - <> - {openBy && ( -
- {openBy} -
- )} - - - ); - } +const ResponsivePopover: FC = withWebComponent( + UI5ResponsivePopover ); ResponsivePopover.displayName = 'ResponsivePopover'; @@ -144,8 +87,7 @@ ResponsivePopover.defaultProps = { modal: false, noArrow: false, placementType: PlacementType.Right, - verticalAlign: PopoverVerticalAlign.Center, - propagateOpenByClickEvent: true + verticalAlign: PopoverVerticalAlign.Center }; export { ResponsivePopover }; diff --git a/shared/tests/utils.tsx b/shared/tests/utils.tsx index 21b7f09e8e2..ddfb67c9fb0 100644 --- a/shared/tests/utils.tsx +++ b/shared/tests/utils.tsx @@ -1,6 +1,4 @@ -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; -import { ThemeProvider } from '@ui5/webcomponents-react/lib/ThemeProvider'; -import { mount, shallow } from 'enzyme'; +import { mount } from 'enzyme'; import React, { ComponentType } from 'react'; export const modifyObjectProperty = (object: any, attr: string, value: any) => {