@coveord/plasma-mantine 59.4.0 → 59.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,13 @@
1
- import {CrossSize16Px, FilterSize16Px} from '@coveord/plasma-react-icons';
1
+ import {IconSearch} from '@coveord/plasma-react-icons';
2
2
  import {
3
3
  Box,
4
4
  BoxProps,
5
+ CloseButton,
5
6
  Combobox,
6
7
  Divider,
7
8
  factory,
8
9
  Factory,
10
+ Group,
9
11
  StylesApiProps,
10
12
  Text,
11
13
  TextInput,
@@ -17,7 +19,6 @@ import {useUncontrolled} from '@mantine/hooks';
17
19
  import {clsx} from 'clsx';
18
20
  import {FunctionComponent, ReactElement, ReactNode, useEffect} from 'react';
19
21
  import {groupOptions} from '../../utils/groupOptions.js';
20
- import {ActionIcon} from '../ActionIcon/ActionIcon.js';
21
22
  import {DefaultFacetItem} from './DefaultFacetItem.js';
22
23
  import classes from './Facet.module.css';
23
24
  import {FacetScrollArea} from './FacetScrollArea.js';
@@ -31,7 +32,9 @@ export type FacetStylesNames =
31
32
  | 'searchInput'
32
33
  | 'hiddenSearch'
33
34
  | 'facetBody'
35
+ | 'facetTitleRow'
34
36
  | 'facetTitle'
37
+ | 'facetRemoveButton'
35
38
  | 'facetSearch'
36
39
  | 'facetControl'
37
40
  | 'separator'
@@ -49,12 +52,22 @@ export interface FacetProps extends BoxProps, StylesApiProps<FacetFactory> {
49
52
  * @param values the selected items
50
53
  */
51
54
  onChange?: (values: string[]) => void;
55
+ /**
56
+ * Function called when the remove icon is clicked.
57
+ */
58
+ onRemove?: () => void;
52
59
  /**
53
60
  * Initial items selection
54
61
  *
55
62
  * @default []
56
63
  */
57
64
  initialSelection?: string[];
65
+ /**
66
+ * Determines if the facet is removable
67
+ *
68
+ * @default false
69
+ */
70
+ removable?: boolean;
58
71
  /**
59
72
  * Determined items selection
60
73
  *
@@ -158,6 +171,7 @@ const defaultProps: Partial<FacetProps> = {
158
171
  limit: Infinity,
159
172
  itemComponent: DefaultFacetItem,
160
173
  listComponent: FacetScrollArea,
174
+ removable: false,
161
175
  };
162
176
 
163
177
  export const Facet: FunctionComponent<FacetProps> = factory<FacetFactory>((_props, ref) => {
@@ -166,7 +180,9 @@ export const Facet: FunctionComponent<FacetProps> = factory<FacetFactory>((_prop
166
180
  className,
167
181
  data,
168
182
  onChange,
183
+ onRemove,
169
184
  initialSelection = [],
185
+ removable,
170
186
  selection,
171
187
  itemComponent: ItemComponent,
172
188
  listComponent: ListComponent,
@@ -260,7 +276,20 @@ export const Facet: FunctionComponent<FacetProps> = factory<FacetFactory>((_prop
260
276
  <Combobox store={combobox} onOptionSubmit={handleValueSelect}>
261
277
  <Combobox.EventsTarget>
262
278
  <Box className={classes.facetHeader}>
263
- {title ? <Title order={5}>{title}</Title> : null}
279
+ <Group wrap="nowrap" justify="space-between" className={classes.facetTitleRow}>
280
+ {title ? (
281
+ <Title order={5} className={classes.facetTitle}>
282
+ {title}
283
+ </Title>
284
+ ) : null}
285
+ {removable ? (
286
+ <CloseButton
287
+ onClick={onRemove}
288
+ className={classes.facetRemoveButton}
289
+ aria-label="remove facet"
290
+ />
291
+ ) : null}
292
+ </Group>
264
293
 
265
294
  <TextInput
266
295
  unstyled={unstyled}
@@ -275,17 +304,14 @@ export const Facet: FunctionComponent<FacetProps> = factory<FacetFactory>((_prop
275
304
  className={clsx(classes.facetSearch, {[classes.hiddenSearch]: hideSearch})}
276
305
  rightSection={
277
306
  search ? (
278
- <ActionIcon.Quaternary
307
+ <CloseButton
279
308
  aria-label="clear search"
280
- color="gray"
281
309
  onClick={() => {
282
310
  handleSearch('');
283
311
  }}
284
- >
285
- <CrossSize16Px height={16} />
286
- </ActionIcon.Quaternary>
312
+ />
287
313
  ) : (
288
- <FilterSize16Px height={16} />
314
+ <IconSearch height={16} />
289
315
  )
290
316
  }
291
317
  />
@@ -237,5 +237,25 @@ describe('Facet', () => {
237
237
  await user.click(screen.getByRole('button', {name: /clear search/i}));
238
238
  expect(onSearch).toHaveBeenCalledWith('');
239
239
  });
240
+
241
+ it('does not render the remove button by default', () => {
242
+ render(<Facet data={[]} title="My little title" />);
243
+ expect(screen.queryByRole('button', {name: /remove facet/i})).not.toBeInTheDocument();
244
+ });
245
+
246
+ it('renders the remove button when the removable prop is true', () => {
247
+ render(<Facet data={[]} title="My little title" removable />);
248
+ expect(screen.getByRole('button', {name: /remove facet/i})).toBeVisible();
249
+ });
250
+
251
+ it('calls onRemove when clicking the remove button', async () => {
252
+ const user = userEvent.setup();
253
+ const onRemove = vi.fn();
254
+ render(<Facet data={[]} title="My little title" onRemove={onRemove} removable />);
255
+
256
+ await user.click(screen.getByRole('button', {name: /remove facet/i}));
257
+
258
+ expect(onRemove).toHaveBeenCalledTimes(1);
259
+ });
240
260
  });
241
261
  });