Skip to content

fix: Re-enable passing refs to non-webcomponent components #83

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
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
12 changes: 10 additions & 2 deletions packages/main/src/components/ActionSheet/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { Device, StyleClassHelper, useConsolidatedRef } from '@ui5/webcomponents-react-base';
import React, { Children, cloneElement, forwardRef, ReactElement, ReactNode, RefObject, FC } from 'react';
import React, {
Children,
cloneElement,
forwardRef,
ReactElement,
ReactNode,
RefForwardingComponent,
RefObject
} from 'react';
import { CommonProps } from '../../interfaces/CommonProps';
import { Ui5PopoverDomRef } from '../../interfaces/Ui5PopoverDomRef';
import { ButtonDesign } from '../../lib/ButtonDesign';
Expand All @@ -17,7 +25,7 @@ export interface ActionSheetPropTypes extends CommonProps {

const useStyles = createUseStyles(styles, { name: 'ActionSheet' });

const ActionSheet: FC<ActionSheetPropTypes> = forwardRef(
const ActionSheet: RefForwardingComponent<Ui5PopoverDomRef, ActionSheetPropTypes> = forwardRef(
(props: ActionSheetPropTypes, ref: RefObject<Ui5PopoverDomRef>) => {
const { children, placement, openBy, style, slot } = props;

Expand Down
190 changes: 96 additions & 94 deletions packages/main/src/components/FilterItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Event, StyleClassHelper } from '@ui5/webcomponents-react-base';
import React, { FC, forwardRef, ReactNode, RefObject, useMemo } from 'react';
import React, { forwardRef, ReactNode, RefForwardingComponent, RefObject, useMemo } from 'react';
import { CommonProps } from '../../interfaces/CommonProps';
import { BusyIndicator } from '../../lib/BusyIndicator';
import { FilterType } from '../../lib/FilterType';
Expand Down Expand Up @@ -28,112 +28,114 @@ export interface FilterItemPropTypes extends CommonProps {

const useStyles = createUseStyles(styles, { name: 'FilterItem' });

const FilterItem: FC<FilterItemPropTypes> = forwardRef((props: FilterItemPropTypes, ref: RefObject<HTMLDivElement>) => {
const {
filterItems,
onChange,
type,
placeholder,
children,
loading,
changeEventName,
valueParamName,
label,
style,
tooltip
} = props as FilterItemPropTypes;
const classes = useStyles();
const FilterItem: RefForwardingComponent<HTMLDivElement, FilterItemPropTypes> = forwardRef(
(props: FilterItemPropTypes, ref: RefObject<HTMLDivElement>) => {
const {
filterItems,
onChange,
type,
placeholder,
children,
loading,
changeEventName,
valueParamName,
label,
style,
tooltip
} = props as FilterItemPropTypes;
const classes = useStyles();

function getItemByKey(key) {
return filterItems.filter((item) => item.key === key)[0];
}
function getItemByKey(key) {
return filterItems.filter((item) => item.key === key)[0];
}

function onSelect(e) {
const selectedKey = e.getParameter('selectedOption').getAttribute('data-key');
const item = getItemByKey(selectedKey) || filterItems[0];
onChange(Event.of(null, e.getOriginalEvent(), { selectedItem: item }));
}
function onSelect(e) {
const selectedKey = e.getParameter('selectedOption').getAttribute('data-key');
const item = getItemByKey(selectedKey) || filterItems[0];
onChange(Event.of(null, e.getOriginalEvent(), { selectedItem: item }));
}

function onMultiCbChange(e) {
const selectedItems = e.getParameter('items');
onChange(
Event.of(null, e.getOriginalEvent(), {
selectedItems: selectedItems.map((item) => {
return getItemByKey(item.getAttribute('data-key'));
function onMultiCbChange(e) {
const selectedItems = e.getParameter('items');
onChange(
Event.of(null, e.getOriginalEvent(), {
selectedItems: selectedItems.map((item) => {
return getItemByKey(item.getAttribute('data-key'));
})
})
})
);
}

const filterComponent = useMemo(() => {
if (loading) {
return (
<div className={classes.loadingContainer}>
<BusyIndicator
active
size={BusyIndicatorType.Medium}
style={{ backgroundColor: 'transparent', width: '80px' }}
/>
</div>
);
}

switch (type) {
case FilterType.Default:
return <Input placeholder={placeholder} onChange={onSelect} style={{ width: '100%' }} />;
case FilterType.MultiSelect:
return (
<MultiComboBox onSelectionChange={onMultiCbChange}>
{filterItems.map((item) => (
<StandardListItem data-key={item.key} key={item.key}>
{item.text}
</StandardListItem>
))}
</MultiComboBox>
);
case FilterType.Select:
const filterComponent = useMemo(() => {
if (loading) {
return (
<Select onChange={onSelect} style={{ width: '100%' }}>
{filterItems.map((item) => (
<Option key={item.key} data-key={item.key}>
{item.text}
</Option>
))}
</Select>
);
case FilterType.Custom:
return (
<div>
{React.Children.map(children, (child) => {
return React.cloneElement(child as React.ReactElement<any>, {
[changeEventName]: (event) => {
onSelect(event);
// @ts-ignore
if (child.props.hasOwnProperty(changeEventName)) {
// @ts-ignore
child.props[changeEventName](event);
}
},
valueParameter: valueParamName,
style: { width: '100%' }
});
})}
<div className={classes.loadingContainer}>
<BusyIndicator
active
size={BusyIndicatorType.Medium}
style={{ backgroundColor: 'transparent', width: '80px' }}
/>
</div>
);
}
}, [valueParamName, changeEventName, filterItems, loading, type, children]);
}

const filterItemClasses = StyleClassHelper.of(classes.filterItem);
switch (type) {
case FilterType.Default:
return <Input placeholder={placeholder} onChange={onSelect} style={{ width: '100%' }} />;
case FilterType.MultiSelect:
return (
<MultiComboBox onSelectionChange={onMultiCbChange}>
{filterItems.map((item) => (
<StandardListItem data-key={item.key} key={item.key}>
{item.text}
</StandardListItem>
))}
</MultiComboBox>
);
case FilterType.Select:
return (
<Select onChange={onSelect} style={{ width: '100%' }}>
{filterItems.map((item) => (
<Option key={item.key} data-key={item.key}>
{item.text}
</Option>
))}
</Select>
);
case FilterType.Custom:
return (
<div>
{React.Children.map(children, (child) => {
return React.cloneElement(child as React.ReactElement<any>, {
[changeEventName]: (event) => {
onSelect(event);
// @ts-ignore
if (child.props.hasOwnProperty(changeEventName)) {
// @ts-ignore
child.props[changeEventName](event);
}
},
valueParameter: valueParamName,
style: { width: '100%' }
});
})}
</div>
);
}
}, [valueParamName, changeEventName, filterItems, loading, type, children]);

return (
<div ref={ref} className={filterItemClasses.toString()} style={style} title={tooltip}>
<div className={classes.innerFilterItemContainer}>
<Label>{label}</Label>
{filterComponent}
const filterItemClasses = StyleClassHelper.of(classes.filterItem);

return (
<div ref={ref} className={filterItemClasses.toString()} style={style} title={tooltip}>
<div className={classes.innerFilterItemContainer}>
<Label>{label}</Label>
{filterComponent}
</div>
</div>
</div>
);
});
);
}
);

FilterItem.defaultProps = {
placeholder: '',
Expand Down
112 changes: 61 additions & 51 deletions packages/main/src/components/FlexBox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { StyleClassHelper } from '@ui5/webcomponents-react-base';
import React, { CSSProperties, FC, forwardRef, ReactNode, ReactNodeArray, Ref, useMemo } from 'react';
import React, {
CSSProperties,
forwardRef,
ReactNode,
ReactNodeArray,
Ref,
RefForwardingComponent,
useMemo
} from 'react';
import { createUseStyles } from 'react-jss';
import { CommonProps } from '../../interfaces/CommonProps';
import { FlexBoxAlignItems } from '../../lib/FlexBoxAlignItems';
Expand All @@ -22,61 +30,63 @@ export interface FlexBoxPropTypes extends CommonProps {
children: ReactNode | ReactNodeArray;
}

const FlexBox: FC<FlexBoxPropTypes> = forwardRef((props: FlexBoxPropTypes, ref: Ref<HTMLDivElement>) => {
const {
children,
justifyContent,
direction,
alignItems,
height,
width,
displayInline,
wrap,
style,
className,
tooltip,
slot
} = props;
const FlexBox: RefForwardingComponent<HTMLDivElement, FlexBoxPropTypes> = forwardRef(
(props: FlexBoxPropTypes, ref: Ref<HTMLDivElement>) => {
const {
children,
justifyContent,
direction,
alignItems,
height,
width,
displayInline,
wrap,
style,
className,
tooltip,
slot
} = props;

const classes = useStyles();
const flexBoxClasses = StyleClassHelper.of(classes.flexBox);
// direction
flexBoxClasses.put(classes[`flexBoxDirection${direction}`]);
// justify content
flexBoxClasses.put(classes[`justifyContent${justifyContent}`]);
// align items
flexBoxClasses.put(classes[`alignItems${alignItems}`]);
// wrapping
flexBoxClasses.put(classes[`flexWrap${wrap}`]);
const classes = useStyles();
const flexBoxClasses = StyleClassHelper.of(classes.flexBox);
// direction
flexBoxClasses.put(classes[`flexBoxDirection${direction}`]);
// justify content
flexBoxClasses.put(classes[`justifyContent${justifyContent}`]);
// align items
flexBoxClasses.put(classes[`alignItems${alignItems}`]);
// wrapping
flexBoxClasses.put(classes[`flexWrap${wrap}`]);

if (displayInline) {
flexBoxClasses.put(classes.flexBoxDisplayInline);
}

if (className) {
flexBoxClasses.put(className);
}

const memoizedStyles = useMemo(() => {
const innerStyles: CSSProperties = {};
if (height) {
innerStyles.height = height;
if (displayInline) {
flexBoxClasses.put(classes.flexBoxDisplayInline);
}
if (width) {
innerStyles.width = width;
}
if (style) {
Object.assign(innerStyles, style);

if (className) {
flexBoxClasses.put(className);
}
return innerStyles;
}, [height, width, style]);

return (
<div ref={ref} className={flexBoxClasses.valueOf()} style={memoizedStyles} title={tooltip} slot={slot}>
{children}
</div>
);
});
const memoizedStyles = useMemo(() => {
const innerStyles: CSSProperties = {};
if (height) {
innerStyles.height = height;
}
if (width) {
innerStyles.width = width;
}
if (style) {
Object.assign(innerStyles, style);
}
return innerStyles;
}, [height, width, style]);

return (
<div ref={ref} className={flexBoxClasses.valueOf()} style={memoizedStyles} title={tooltip} slot={slot}>
{children}
</div>
);
}
);

FlexBox.defaultProps = {
alignItems: FlexBoxAlignItems.Stretch,
Expand Down
Loading