Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions packages/main/src/components/ActionSheet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import { isPhone } from '@ui5/webcomponents-base/dist/Device.js';
import { useI18nBundle, useSyncRef } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import React, { forwardRef, ReactElement, useEffect, useReducer, useRef, useState } from 'react';
import React, { forwardRef, ReactElement, useReducer, useRef } from 'react';
import { createPortal } from 'react-dom';
import { createUseStyles } from 'react-jss';
import { ButtonDesign } from '../../enums';
import { AVAILABLE_ACTIONS, CANCEL, X_OF_Y } from '../../i18n/i18n-defaults';
import { addCustomCSSWithScoping } from '../../internal/addCustomCSSWithScoping';
import { useCanRenderPortal } from '../../internal/ssr';
import { flattenFragments, isSSR } from '../../internal/utils';
import { CustomThemingParameters } from '../../themes/CustomVariables';
import { UI5WCSlotsNode } from '../../types';
Expand Down Expand Up @@ -164,10 +165,10 @@ const ActionSheet = forwardRef<ResponsivePopoverDomRef, ActionSheetPropTypes>((p
const childrenArrayLength = childrenToRender.length;
const childrenLength = isPhone() && showCancelButton ? childrenArrayLength + 1 : childrenArrayLength;

const [canRender, setCanRender] = useState(false);
useEffect(() => {
setCanRender(true);
}, []);
const canRenderPortal = useCanRenderPortal();
if (!canRenderPortal) {
return null;
}

const handleCancelBtnClick = () => {
popoverRef.current.close();
Expand Down Expand Up @@ -218,10 +219,6 @@ const ActionSheet = forwardRef<ResponsivePopoverDomRef, ActionSheetPropTypes>((p
}
};

if (!canRender) {
return null;
}

const displayHeader = isPhone();
return createPortal(
<ResponsivePopover
Expand Down
2 changes: 1 addition & 1 deletion packages/main/src/components/MessageViewButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { ThemingParameters } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import React, { forwardRef } from 'react';
import { createUseStyles } from 'react-jss';
import { Button, ButtonDomRef, ButtonPropTypes } from '../..';
import { ValueState } from '../../enums';
import { Button, ButtonDomRef, ButtonPropTypes } from '../../webComponents';

const buttonStyles = Object.values(ValueState).reduce((acc, cur) => {
let cssType;
Expand Down
76 changes: 38 additions & 38 deletions packages/main/src/components/Toolbar/OverflowPopover.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import iconOverflow from '@ui5/webcomponents-icons/dist/overflow.js';
import { Device, useSyncRef } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import React, { cloneElement, FC, ReactElement, ReactNode, Ref, useCallback, useEffect, useRef, useState } from 'react';
import React, { cloneElement, FC, ReactElement, ReactNode, Ref, useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { ButtonDesign, PopoverPlacementType } from '../../enums';
import { OverflowPopoverContext } from '../../internal/OverflowPopoverContext';
import { useCanRenderPortal } from '../../internal/ssr';
import { stopPropagation } from '../../internal/stopPropagation';
import { getUi5TagWithSuffix } from '../../internal/utils';
import {
Expand Down Expand Up @@ -76,25 +77,6 @@ export const OverflowPopover: FC<OverflowPopoverProps> = (props: OverflowPopover
setPressed(false);
};

const renderChildren = useCallback((): ReactNode[] => {
return children.map((item, index) => {
if (index > lastVisibleIndex && index > numberOfAlwaysVisibleItems - 1) {
// @ts-expect-error: if type is not defined, it's not a spacer
if (item.type?.displayName === 'ToolbarSeparator') {
return cloneElement(item as ReactElement, {
style: {
height: '0.0625rem',
margin: '0.375rem 0.1875rem',
width: '100%'
}
});
}
return item;
}
return null;
});
}, [children, lastVisibleIndex]);

useEffect(() => {
const tagName = getUi5TagWithSuffix('ui5-toggle-button');
customElements.whenDefined(tagName).then(() => {
Expand All @@ -113,6 +95,8 @@ export const OverflowPopover: FC<OverflowPopoverProps> = (props: OverflowPopover
}
};

const canRenderPortal = useCanRenderPortal();

return (
<OverflowPopoverContext.Provider value={{ inPopover: true }}>
{overflowButton ? (
Expand All @@ -129,24 +113,40 @@ export const OverflowPopover: FC<OverflowPopoverProps> = (props: OverflowPopover
data-component-name="ToolbarOverflowButton"
/>
)}
{createPortal(
<Popover
data-component-name="ToolbarOverflowPopover"
className={clsx(classes.popover, isPhone && classes.popoverPhone)}
placementType={PopoverPlacementType.Bottom}
ref={componentRef}
open={pressed}
onAfterClose={handleClose}
onBeforeOpen={handleBeforeOpen}
onAfterOpen={handleAfterOpen}
hideArrow
>
<div className={classes.popoverContent} ref={overflowContentRef}>
{renderChildren()}
</div>
</Popover>,
portalContainer
)}
{canRenderPortal &&
createPortal(
<Popover
data-component-name="ToolbarOverflowPopover"
className={clsx(classes.popover, isPhone && classes.popoverPhone)}
placementType={PopoverPlacementType.Bottom}
ref={componentRef}
open={pressed}
onAfterClose={handleClose}
onBeforeOpen={handleBeforeOpen}
onAfterOpen={handleAfterOpen}
hideArrow
>
<div className={classes.popoverContent} ref={overflowContentRef}>
{children.map((item, index) => {
if (index > lastVisibleIndex && index > numberOfAlwaysVisibleItems - 1) {
// @ts-expect-error: if type is not defined, it's not a spacer
if (item.type?.displayName === 'ToolbarSeparator') {
return cloneElement(item as ReactElement, {
style: {
height: '0.0625rem',
margin: '0.375rem 0.1875rem',
width: '100%'
}
});
}
return item;
}
return null;
})}
</div>
</Popover>,
portalContainer ?? document.body
)}
</OverflowPopoverContext.Provider>
);
};
31 changes: 11 additions & 20 deletions packages/main/src/components/Toolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,16 @@ const OVERFLOW_BUTTON_WIDTH = 36 + 8 + 8; // width + padding end + spacing start
const Toolbar = forwardRef<HTMLDivElement, ToolbarPropTypes>((props, ref) => {
const {
children,
toolbarStyle,
design,
active,
toolbarStyle = ToolbarStyle.Standard,
design = ToolbarDesign.Auto,
active = false,
style,
className,
onClick,
slot,
as,
as = 'div',
portalContainer,
numberOfAlwaysVisibleItems,
numberOfAlwaysVisibleItems = 0,
onOverflowChange,
overflowPopoverRef,
overflowButton,
Expand Down Expand Up @@ -244,19 +244,19 @@ const Toolbar = forwardRef<HTMLDivElement, ToolbarPropTypes>((props, ref) => {
}
setLastVisibleIndex(lastIndex);
});
}, [outerContainer.current, controlMetaData.current, setLastVisibleIndex, childrenWithRef, overflowNeeded]);

const observer = useRef(new ResizeObserver(calculateVisibleItems));
}, []);

useEffect(() => {
const observer = new ResizeObserver(calculateVisibleItems);

if (outerContainer.current) {
observer.current.observe(outerContainer.current);
observer.observe(outerContainer.current);
}
return () => {
cancelAnimationFrame(requestAnimationFrameRef.current);
observer.current.disconnect();
observer.disconnect();
};
}, [outerContainer.current]);
}, [calculateVisibleItems]);

useIsomorphicLayoutEffect(() => {
calculateVisibleItems();
Expand Down Expand Up @@ -350,14 +350,5 @@ const Toolbar = forwardRef<HTMLDivElement, ToolbarPropTypes>((props, ref) => {
);
});

Toolbar.defaultProps = {
as: 'div',
toolbarStyle: ToolbarStyle.Standard,
design: ToolbarDesign.Auto,
active: false,
portalContainer: document.body,
numberOfAlwaysVisibleItems: 0
};

Toolbar.displayName = 'Toolbar';
export { Toolbar };
15 changes: 15 additions & 0 deletions packages/main/src/internal/ssr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { EffectCallback, useEffect, useState } from 'react';

export function useServerSideEffect(effect: EffectCallback) {
useEffect(effect, []);
}

export function useCanRenderPortal() {
const [allowed, setAllowed] = useState(false);

useEffect(() => {
setAllowed(true);
}, []);

return allowed;
}
5 changes: 0 additions & 5 deletions packages/main/src/internal/useServerSideEffect.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/main/src/internal/withWebComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import React, {
} from 'react';
import { CommonProps } from '../interfaces/CommonProps';
import { Ui5DomRef } from '../interfaces/Ui5DomRef';
import { useServerSideEffect } from './useServerSideEffect';
import { useServerSideEffect } from './ssr';
import { camelToKebabCase, capitalizeFirstLetter, kebabToCamelCase } from './utils';

const createEventPropName = (eventName) => `on${capitalizeFirstLetter(kebabToCamelCase(eventName))}`;
Expand Down