Skip to content
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

refactor(FilterGroupItem): api alignment #6012

Merged
merged 9 commits into from
Jul 5, 2024
103 changes: 74 additions & 29 deletions docs/MigrationGuide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -347,35 +347,6 @@ function MyComponent() {
}
```

### MessageBox

- `onClose` is now a plain callback function and no `CustomEvent` anymore. It receives two parameters, `action` and `escPressed`.

```jsx
// v1
// onClose?: (event: CustomEvent<{ action: MessageBoxAction }>) => void;

<MessageBox
onClose={(event) => {
console.log(event.detail.action);
}}
>
{children}
</MessageBox>

// v2
// onClose?: (action: MessageBoxActionType | undefined, escPressed?: true) => void;

<MessageBox
onClose={(action, escPressed) => {
console.log(action, escPressed);
}}
>
{children}
</MessageBox>

```

### ObjectPage

The newly introduced `DynamicPage` web component comes with its own `DynamicPageHeader` and `DynamicPageTitle` components, which are unfortunately incompatible with our `ObjectPage` implementation.
Expand Down Expand Up @@ -457,6 +428,80 @@ The prop `portalContainer` has been removed as it is no longer needed due to the
As the underlying `Text` component has been replaced with the UI5 Web Component, some inherited props `hyphenated` and `emptyIndicator` from the `Text` component have been removed.
You can follow this [feature request](https://github.com/SAP/ui5-webcomponents/issues/9244) for updates.

### FilterGroupItem

For a better aligned API, the `visible` and `visibleInFilterBar` (defaulted to `true)` props has been replaced with `hidden` and `hiddenInFilterBar` (no default value).
You only need to apply changes to your code if `visible` or `visibleInFilterBar` have been set to `false`:

```tsx
// v1
import { FilterBar, FilterGroupItem, Input } from '@ui5/webcomponents-react';

function MyComponent() {
return (
<FilterBar>
<FilterGroupItem visible={false}>
<Input />
</FilterGroupItem>
<FilterGroupItem visibleInFilterBar={false}>
<Input />
</FilterGroupItem>
<FilterGroupItem>
<Input />
</FilterGroupItem>
</FilterBar>
);
}

// v2
import { FilterBar, FilterGroupItem, Input } from '@ui5/webcomponents-react';

function MyComponent() {
return (
<FilterBar>
<FilterGroupItem hidden>
<Input />
</FilterGroupItem>
<FilterGroupItem hiddenInFilterBar>
<Input />
</FilterGroupItem>
<FilterGroupItem>
<Input />
</FilterGroupItem>
</FilterBar>
);
}
```

### MessageBox

- `onClose` is now a plain callback function and no `CustomEvent` anymore. It receives two parameters, `action` and `escPressed`.

```jsx
// v1
// onClose?: (event: CustomEvent<{ action: MessageBoxAction }>) => void;

<MessageBox
onClose={(event) => {
console.log(event.detail.action);
}}
>
{children}
</MessageBox>

// v2
// onClose?: (action: MessageBoxActionType | undefined, escPressed?: true) => void;

<MessageBox
onClose={(action, escPressed) => {
console.log(action, escPressed);
}}
>
{children}
</MessageBox>

```

## Enum Changes

For a better alignment with the UI5 Web Components, the following enums have been renamed:
Expand Down
38 changes: 38 additions & 0 deletions packages/cli/src/scripts/codemod/transforms/v2/main.cts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,44 @@ export default function transform(file: FileInfo, api: API, options?: Options):
});
}

if (componentName === 'FilterGroupItem') {
jsxElements.forEach((el) => {
const visible = j(el).find(j.JSXAttribute, { name: { name: 'visible' } });
if (visible.size() > 0) {
const attr = visible.get();
if (
attr.value.value &&
((attr.value.value.type === 'JSXAttribute' && attr.value.value === false) ||
(attr.value.value.type === 'JSXExpressionContainer' && attr.value.value.expression.value === false))
) {
j(el)
.find(j.JSXOpeningElement)
.get()
.value.attributes.push(j.jsxAttribute(j.jsxIdentifier('hidden'), null));
}
visible.remove();
isDirty = true;
}

const visibleInFilterBar = j(el).find(j.JSXAttribute, { name: { name: 'visibleInFilterBar' } });
if (visibleInFilterBar.size() > 0) {
const attr = visibleInFilterBar.get();
if (
attr.value.value &&
((attr.value.value.type === 'JSXAttribute' && attr.value.value === false) ||
(attr.value.value.type === 'JSXExpressionContainer' && attr.value.value.expression.value === false))
) {
j(el)
.find(j.JSXOpeningElement)
.get()
.value.attributes.push(j.jsxAttribute(j.jsxIdentifier('hiddenInFilterBar'), null));
}
visibleInFilterBar.remove();
isDirty = true;
}
});
}

if (componentName === 'Icon') {
jsxElements.forEach((el) => {
const interactive = j(el).find(j.JSXAttribute, { name: { name: 'interactive' } });
Expand Down
18 changes: 9 additions & 9 deletions packages/main/src/components/FilterBar/FilterBar.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -632,34 +632,34 @@ describe.skip('FilterBar.cy.tsx', () => {
cy.get('div[data-order-id]').eq(4).find('[ui5-label]').should('have.text', 'RatingIndicator');
});

it('visible & visibleInFilterBar', () => {
it('hidden & hiddenInFilterBar', () => {
cy.mount(
<FilterBar>
<FilterGroupItem label="undefined">
<StepInput />
</FilterGroupItem>
<FilterGroupItem label="false" visible={false}>
<FilterGroupItem label="false" hidden>
<StepInput />
</FilterGroupItem>
<FilterGroupItem label="true" visible>
<FilterGroupItem label="true" hidden={false}>
<StepInput />
</FilterGroupItem>
<FilterGroupItem label="undefined undefined">
<StepInput />
</FilterGroupItem>
<FilterGroupItem label="false false" visible={false} visibleInFilterBar={false}>
<FilterGroupItem label="false false" hidden hiddenInFilterBar>
<StepInput />
</FilterGroupItem>
<FilterGroupItem label="true true" visible visibleInFilterBar>
<FilterGroupItem label="true true">
<StepInput />
</FilterGroupItem>
<FilterGroupItem label="true false" visible visibleInFilterBar={false}>
<FilterGroupItem label="true false" hiddenInFilterBar>
<StepInput />
</FilterGroupItem>
<FilterGroupItem label="undefined true" visible visibleInFilterBar={true}>
<FilterGroupItem label="undefined true" hiddenInFilterBar={false}>
<StepInput />
</FilterGroupItem>
<FilterGroupItem label="undefined false" visible visibleInFilterBar={false}>
<FilterGroupItem label="undefined false" hiddenInFilterBar>
<StepInput />
</FilterGroupItem>
</FilterBar>
Expand Down Expand Up @@ -724,7 +724,7 @@ function FilterBarWithReordering(props: Partial<FilterBarPropTypes>) {
<FilterGroupItem
key={`${uniqueId}-5`}
label="SELECT w/ initial selected"
visibleInFilterBar={false}
hiddenInFilterBar
orderId={`${uniqueId}-5`}
>
<Select>
Expand Down
4 changes: 2 additions & 2 deletions packages/main/src/components/FilterBar/FilterBar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const FilterBarComponent = (args) => {
<FilterGroupItem label="Date" active={!!date}>
<DatePicker value={date} onChange={handleDateChange} style={{ minWidth: 'auto' }} on />
</FilterGroupItem>
<FilterGroupItem label="Date Range" active={!!dateRange} visibleInFilterBar={false}>
<FilterGroupItem label="Date Range" active={!!dateRange} hiddenInFilterBar>
<DateRangePicker value={dateRange} onChange={handleDateRangeChange} style={{ minWidth: 'auto' }} on />
</FilterGroupItem>
</FilterBar>
Expand Down Expand Up @@ -233,7 +233,7 @@ function FilterBarWithReordering(props) {
<FilterGroupItem
key={`${uniqueId}-5`}
label="SELECT w/ initial selected"
visibleInFilterBar={false}
hiddenInFilterBar
orderId={`${uniqueId}-5`}
>
<Select>
Expand Down
22 changes: 11 additions & 11 deletions packages/main/src/components/FilterBar/FilterBar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const Default: Story = {
render: (args) => {
return (
<FilterBar {...args}>
<FilterGroupItem label="StepInput" required>
<FilterGroupItem label="StepInput" hiddenInFilterBar hidden>
<StepInput required />
</FilterGroupItem>
<FilterGroupItem label="RatingIndicator">
Expand All @@ -80,7 +80,7 @@ export const Default: Story = {
<FilterGroupItem label="Switch">
<Switch />
</FilterGroupItem>
<FilterGroupItem label="SELECT w/ initial selected" visibleInFilterBar={false}>
<FilterGroupItem label="SELECT w/ initial selected" hiddenInFilterBar>
<Select>
<Option>Option 1</Option>
<Option selected>Option 2</Option>
Expand Down Expand Up @@ -248,10 +248,10 @@ export const WithLogic: Story = {
</Select>
</FilterGroupItem>
<FilterGroupItem label="Date" active={!!date}>
<DatePicker value={date} onChange={handleDateChange} style={{ minWidth: 'auto' }} on />
<DatePicker value={date} onChange={handleDateChange} style={{ minWidth: 'auto' }} />
</FilterGroupItem>
<FilterGroupItem label="Date Range" active={!!dateRange} visibleInFilterBar={false}>
<DateRangePicker value={dateRange} onChange={handleDateRangeChange} style={{ minWidth: 'auto' }} on />
<FilterGroupItem label="Date Range" active={!!dateRange} hiddenInFilterBar>
<DateRangePicker value={dateRange} onChange={handleDateRangeChange} style={{ minWidth: 'auto' }} />
</FilterGroupItem>
</FilterBar>
<FlexBox direction={FlexBoxDirection.Column}>
Expand Down Expand Up @@ -329,18 +329,18 @@ export const InDynamicPage: Story = {
<FilterGroupItem label="Input">
<Input placeholder="Placeholder" />
</FilterGroupItem>
<FilterGroupItem label="Switch" visibleInFilterBar={false}>
<FilterGroupItem label="Switch" hiddenInFilterBar>
<Switch />
</FilterGroupItem>
<FilterGroupItem label="SELECT w/ initial selected" visibleInFilterBar={false}>
<FilterGroupItem label="SELECT w/ initial selected" hiddenInFilterBar>
<Select>
<Option>Option 1</Option>
<Option selected>Option 2</Option>
<Option>Option 3</Option>
<Option>Option 4</Option>
</Select>
</FilterGroupItem>
<FilterGroupItem label="SELECT w/o initial selected" visibleInFilterBar={false}>
<FilterGroupItem label="SELECT w/o initial selected" hiddenInFilterBar>
<Select>
<Option data-key="Test 1" selected icon="add">
Test 1
Expand All @@ -359,15 +359,15 @@ export const InDynamicPage: Story = {
</Option>
</Select>
</FilterGroupItem>
<FilterGroupItem label="MultBox w/ initial selected" groupName="Group 1" visibleInFilterBar={false}>
<FilterGroupItem label="MultBox w/ initial selected" groupName="Group 1" hiddenInFilterBar>
<MultiComboBox>
<MultiComboBoxItem text="MultiComboBoxItem 1" />
<MultiComboBoxItem selected text="MultiComboBoxItem 2" />
<MultiComboBoxItem text="MultiComboBoxItem 3" />
<MultiComboBoxItem selected text="MultiComboBoxItem 4" />
</MultiComboBox>
</FilterGroupItem>
<FilterGroupItem label="ComboBox w/o initial selected" groupName="Group 2" visibleInFilterBar={false}>
<FilterGroupItem label="ComboBox w/o initial selected" groupName="Group 2" hiddenInFilterBar>
<ComboBox>
<ComboBoxItem text="ComboBoxItem 1" />
<ComboBoxItem text="ComboBoxItem 2" />
Expand Down Expand Up @@ -429,7 +429,7 @@ export const WithReordering: Story = {
<FilterGroupItem
key={`${uniqueId}-5`}
label="SELECT w/ initial selected"
visibleInFilterBar={false}
hiddenInFilterBar
orderId={`${uniqueId}-5`}
>
<Select>
Expand Down
6 changes: 3 additions & 3 deletions packages/main/src/components/FilterBar/FilterDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@
case 'all':
return true;
case 'visible':
return filter.props?.visibleInFilterBar;
return filter.props?.hiddenInFilterBar !== true;
case 'active':
return filter.props?.active;
case 'visibleAndActive':
return filter.props?.visibleInFilterBar && filter.props?.active;
return filter.props?.hiddenInFilterBar !== true && filter.props?.active;
case 'mandatory':
return filter.props?.required;
default:
Expand Down Expand Up @@ -207,7 +207,7 @@

const visibleChildren = () =>
children.filter((item) => {
return !!item?.props && (typeof item.props.visible === 'undefined' || item?.props?.visible);

Check failure on line 210 in packages/main/src/components/FilterBar/FilterDialog.tsx

View workflow job for this annotation

GitHub Actions / Build (19)

Property 'visible' does not exist on type 'FilterGroupItemInternalProps'.

Check failure on line 210 in packages/main/src/components/FilterBar/FilterDialog.tsx

View workflow job for this annotation

GitHub Actions / Build (19)

Property 'visible' does not exist on type 'FilterGroupItemInternalProps'.
});

const [orderedChildren, setOrderedChildren] = useState([]);
Expand All @@ -232,7 +232,7 @@
return filteredChildren.map((child, index) => {
const filterBarItemRef = filterBarRefs.current[child.key];
let isSelected =
child.props.visibleInFilterBar || child.props.required || child.type.displayName !== 'FilterGroupItem';
child.props.hiddenInFilterBar !== true || child.props.required || child.type.displayName !== 'FilterGroupItem';
if (toggledFilters.hasOwnProperty(child.key)) {
isSelected = toggledFilters[child.key];
}
Expand Down
20 changes: 13 additions & 7 deletions packages/main/src/components/FilterBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,14 @@ const FilterBar = forwardRef<HTMLDivElement, FilterBarPropTypes>((props, ref) =>
if (isValidElement(item)) {
const key = item.key as ReactKeyWithoutBigInt;
setToggledFilters((prev) => {
if (!item.props.hasOwnProperty('visibleInFilterBar') && prev?.[key] === undefined) {
if (!item.props.hasOwnProperty('hiddenInFilterBar') && prev?.[key] === undefined) {
return { ...prev, [key]: true };
}
if (item.props.hasOwnProperty('visibleInFilterBar')) {
return { ...prev, [key]: (item as ReactElement<FilterGroupItemInternalProps>).props.visibleInFilterBar };
if (item.props.hasOwnProperty('hiddenInFilterBar')) {
return {
...prev,
[key]: (item as ReactElement<FilterGroupItemInternalProps>).props.hiddenInFilterBar !== true
};
}
return prev;
});
Expand Down Expand Up @@ -225,7 +228,7 @@ const FilterBar = forwardRef<HTMLDivElement, FilterBarPropTypes>((props, ref) =>
if (toggledFilters?.[key] !== undefined) {
// @ts-expect-error: child should always be a FilterGroupItem w/o portal
return cloneElement<FilterGroupItemInternalProps, HTMLDivElement>(child, {
visibleInFilterBar: toggledFilters[key]
hiddenInFilterBar: !toggledFilters[key]
});
}
}
Expand All @@ -247,7 +250,10 @@ const FilterBar = forwardRef<HTMLDivElement, FilterBarPropTypes>((props, ref) =>
if (!isValidElement(item)) {
return false;
}
return (typeof item.props.visible === 'undefined' || item?.props?.visible) && item.props?.visibleInFilterBar;
return (
(typeof item.props.hidden === 'undefined' || item?.props?.hidden !== true) &&
item.props?.hiddenInFilterBar !== true
);
})
.map((child) => {
const key = child.key as ReactKeyWithoutBigInt;
Expand All @@ -258,7 +264,7 @@ const FilterBar = forwardRef<HTMLDivElement, FilterBarPropTypes>((props, ref) =>
if (hideFilterConfiguration) {
return cloneElement(child, { ...childProps });
}
prevVisibleInFilterBarProps.current[key] = child.props.visibleInFilterBar;
prevVisibleInFilterBarProps.current[key] = child.props.hiddenInFilterBar !== true;
let filterItemProps = {};
if (Object.keys(dialogRefs).length > 0) {
const dialogItemRef = dialogRefs[key];
Expand Down Expand Up @@ -522,7 +528,7 @@ const FilterBar = forwardRef<HTMLDivElement, FilterBarPropTypes>((props, ref) =>
data-component-name="FilterBarFilterArea"
>
{search && (
<FilterGroupItem visibleInFilterBar data-with-toolbar={!hideToolbar}>
<FilterGroupItem data-with-toolbar={!hideToolbar}>
<div ref={searchRef} className={classNames.searchContainer}>
{renderSearchWithValue(search, searchValue, {
placeholder: searchText,
Expand Down
Loading
Loading