Skip to content

Commit 6cc0d5c

Browse files
committed
chore(merge): merge main in
2 parents 78b60ba + 1695222 commit 6cc0d5c

File tree

6 files changed

+90
-9
lines changed

6 files changed

+90
-9
lines changed

.changeset/mighty-doors-sit.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@commercetools-uikit/filters': minor
3+
---
4+
5+
Support filter tag appearing if filter is set outside Filter component

packages/components/fields/multiline-text-field/src/multiline-text-field.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useEffect, useState } from 'react';
77

88
const meta: Meta<TMultiTextFieldProps> = {
99
title: 'Form/Fields/MultilineTextField',
10-
component: MultilineTextField,
10+
component: MultilineTextField as React.ComponentType<TMultiTextFieldProps>,
1111
argTypes: {
1212
title: { control: 'text' },
1313
hint: { control: 'text' },

packages/components/fields/radio-field/src/radio-field.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ const meta: Meta<typeof RadioField> = {
99
// @ts-expect-error, fix component and/or types
1010
component: RadioField,
1111
subcomponents: {
12-
// @ts-expect-error
1312
'RadioInput.Option': RadioInput.Option,
1413
},
1514
argTypes: {

packages/components/filters/src/filters.spec.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
selectFilterValues,
1818
toggleFilterList,
1919
} from './filters.spec.utils';
20+
import { IntlProvider } from 'react-intl';
2021

2122
const mockRenderSearchComponent = (
2223
<input id="search-text" type="text" placeholder="Search Placeholder" />
@@ -308,6 +309,51 @@ describe('Filters', () => {
308309
expect(chips).toEqual(['lavender', 'cobalt']);
309310
});
310311

312+
it('should render a filter when props.appliedFilters is updated', async () => {
313+
const { rerender } = render(
314+
<FilterTestComponent
315+
{...createTestProps()}
316+
initialPrimaryColorValue={['lavender', 'cobalt']}
317+
/>
318+
);
319+
// Toggle the filter list to ensure applied filters are shown
320+
await toggleFilterList();
321+
322+
//Expect chips to display selected filter values on initial render
323+
const primaryChips = getDisplayedChipsForFilter('primaryColors');
324+
expect(primaryChips).toEqual(['lavender', 'cobalt']);
325+
expect(screen.queryByText(/rojo/i)).toBeFalsy();
326+
rerender(
327+
<IntlProvider locale="en">
328+
<FilterTestComponent
329+
{...createTestProps({
330+
appliedFilters: [
331+
{
332+
filterKey: 'colorName',
333+
values: [
334+
{
335+
value: 'rojo',
336+
label: 'rojo',
337+
},
338+
],
339+
},
340+
],
341+
})}
342+
initialPrimaryColorValue={['lavender', 'azure']}
343+
/>
344+
</IntlProvider>
345+
);
346+
// await toggleFilterList();
347+
348+
await toggleFilterList();
349+
const colorChips2 = getDisplayedChipsForFilter('colorName');
350+
expect(colorChips2).toEqual(['rojo']);
351+
352+
//Expect chips to display selected filter values on initial render
353+
const primaryChips2 = getDisplayedChipsForFilter('primaryColors');
354+
expect(primaryChips2).toEqual(['lavender', 'azure']);
355+
});
356+
311357
it('should render a badge on initial page load when >=2 appliedFilters are passed', async () => {
312358
render(
313359
<FilterTestComponent

packages/components/filters/src/filters.tsx

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {
2-
type ReactNode,
3-
type MouseEvent,
42
type KeyboardEvent,
3+
type MouseEvent,
4+
type ReactNode,
5+
useEffect,
56
useRef,
67
useState,
78
} from 'react';
@@ -22,8 +23,8 @@ import SelectInput, {
2223
import Spacings from '@commercetools-uikit/spacings';
2324
import { useIntl } from 'react-intl';
2425
import FilterMenu, {
25-
menuStyles,
2626
menuBodyStyle,
27+
menuStyles,
2728
type TAppliedFilterValue,
2829
} from './filter-menu';
2930
import messages from './messages';
@@ -248,9 +249,7 @@ function Filters({
248249
// applied filters must have corresponding filter in `props.filters`,
249250
const visibleFiltersFromProps = filters
250251
.filter(({ key, isPersistent }) => {
251-
const isVisible =
252-
Boolean(isPersistent) || appliedFilterKeys.includes(key);
253-
return isVisible;
252+
return Boolean(isPersistent) || appliedFilterKeys.includes(key);
254253
})
255254
// persistent filters should be first in filter list
256255
.sort(({ isPersistent }) => (isPersistent ? -1 : 1));
@@ -260,6 +259,39 @@ function Filters({
260259
visibleFiltersFromProps.map(({ key }) => key)
261260
);
262261

262+
// Update localVisibleFilters if appliedFilters or filters prop changes
263+
useEffect(() => {
264+
const allFilterKeys = filters.map((f) => f.key);
265+
const persistedFilterKeys = filters
266+
.filter((filter) => filter.isPersistent)
267+
.map((filter) => filter.key);
268+
269+
const appliedFilterKeysWithValues = appliedFilters.map(
270+
(af) => af.filterKey
271+
);
272+
273+
// Calculate keys that *must* be visible based on props
274+
const requiredVisibleKeys = new Set([
275+
...persistedFilterKeys,
276+
...appliedFilterKeysWithValues,
277+
]);
278+
279+
// Update state: keep existing keys, add required keys, remove keys no longer in props.filters
280+
setLocalVisibleFilters((currentVisibleFilters) => {
281+
const combinedKeys = new Set([
282+
...currentVisibleFilters,
283+
...requiredVisibleKeys,
284+
]);
285+
// Ensure all keys in the final state actually exist in the filters prop
286+
return Array.from(combinedKeys).filter((key) =>
287+
allFilterKeys.includes(key)
288+
);
289+
});
290+
291+
// Update the ref for persisted keys (used elsewhere)
292+
persistedFiltersRef.current = persistedFilterKeys;
293+
}, [appliedFilters, filters]); // Keep dependencies correct
294+
263295
//update localVisibleFilters if persisted filter count changes
264296
if (persistedFiltersRef.current.length !== persistedFilterKeys.length) {
265297
setLocalVisibleFilters(visibleFiltersFromProps.map(({ key }) => key));

packages/components/view-switcher/src/view-switcher.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ const meta: Meta<typeof ViewSwitcher.Group> = {
66
title: 'components/ViewSwitcher',
77
component: ViewSwitcher.Group,
88
subcomponents: {
9-
// @ts-expect-error
109
'ViewSwitcher.Button': ViewSwitcher.Button,
1110
},
1211
argTypes: {

0 commit comments

Comments
 (0)