• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAP / ui5-webcomponents-react / 9418003409

07 Jun 2024 01:40PM CUT coverage: 88.099% (-0.5%) from 88.645%
9418003409

Pull #5860

github

web-flow
Merge 2d8ec93e0 into 2bba948ab
Pull Request #5860: feat: support React 19

3096 of 4079 branches covered (75.9%)

88 of 94 new or added lines in 38 files covered. (93.62%)

31 existing lines in 4 files now uncovered.

5500 of 6243 relevant lines covered (88.1%)

66352.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.7
/packages/main/src/components/FilterBar/FilterDialog.tsx
1
import group2Icon from '@ui5/webcomponents-icons/dist/group-2.js';
2
import listIcon from '@ui5/webcomponents-icons/dist/list.js';
3
import searchIcon from '@ui5/webcomponents-icons/dist/search.js';
4
import { enrichEventWithDetails, useI18nBundle, useIsomorphicId, useStylesheet } from '@ui5/webcomponents-react-base';
5
import type { Dispatch, MutableRefObject, ReactElement, SetStateAction } from 'react';
6
import { Children, cloneElement, useEffect, useReducer, useRef, useState } from 'react';
7
import { createPortal } from 'react-dom';
8
import {
9
  BarDesign,
10
  ButtonDesign,
11
  FlexBoxDirection,
12
  FlexBoxJustifyContent,
13
  MessageBoxActions,
14
  MessageBoxTypes,
15
  TableMode,
16
  TitleLevel,
17
  ToolbarStyle
18
} from '../../enums/index.js';
19
import {
20
  ACTIVE,
21
  ALL,
22
  BASIC,
23
  CANCEL,
24
  FIELDS_BY_ATTRIBUTE,
25
  FILTER_DIALOG_RESET_WARNING,
26
  FILTER,
27
  FILTERS,
28
  GROUP_VIEW,
29
  HIDE_VALUES,
30
  LIST_VIEW,
31
  MANDATORY,
32
  OK,
33
  RESET,
34
  SEARCH_FOR_FILTERS,
35
  SHOW_VALUES,
36
  VISIBLE,
37
  VISIBLE_AND_ACTIVE
38
} from '../../i18n/i18n-defaults.js';
39
import { addCustomCSSWithScoping } from '../../internal/addCustomCSSWithScoping.js';
40
import type { OnReorderParams } from '../../internal/FilterBarDialogContext.js';
41
import { FilterBarDialogContext } from '../../internal/FilterBarDialogContext.js';
42
import { useCanRenderPortal } from '../../internal/ssr.js';
43
import { stopPropagation } from '../../internal/stopPropagation.js';
44
import type { Ui5CustomEvent } from '../../types/index.js';
45
import type { DialogDomRef, SegmentedButtonPropTypes, TableDomRef, TableRowDomRef } from '../../webComponents/index.js';
46
import {
47
  Bar,
48
  Button,
49
  Dialog,
50
  Icon,
51
  Input,
52
  Option,
53
  Panel,
54
  SegmentedButton,
55
  SegmentedButtonItem,
56
  Select,
57
  Table,
58
  TableColumn,
59
  Title
60
} from '../../webComponents/index.js';
61
import type { FilterGroupItemInternalProps } from '../FilterGroupItem/types.js';
62
import { FlexBox } from '../FlexBox/index.js';
63
import { MessageBox } from '../MessageBox/index.js';
64
import { Toolbar } from '../Toolbar/index.js';
65
import { ToolbarSpacer } from '../ToolbarSpacer/index.js';
66
import { classNames, styleData } from './FilterBarDialog.module.css.js';
67
import type { FilterBarPropTypes } from './types.js';
68
import { filterValue, syncRef } from './utils.js';
69

70
addCustomCSSWithScoping(
447✔
71
  'ui5-table',
72
  `
73
/* hide table header of panel table */
74
:host([data-component-name="FilterBarDialogPanelTable"]) thead {
75
  visibility: collapse;
76
}
77

78
/* don't display border of panel table */
79
:host([data-component-name="FilterBarDialogPanelTable"]) table {
80
  border-collapse: unset;
81
}
82

83
/* don't allow table cells to grow
84
todo: FilterBarDialogPanelTable
85
*/
86
:host([data-component-name="FilterBarDialogTable"]) table {
87
  table-layout: fixed;
88
}
89

90
/* prevent focus by click on group-view thead */
91
:host([data-component-name="FilterBarDialogTable"][tabindex="-1"]) thead > tr {
92
  pointer-events: none;
93
}
94

95
:host([data-component-name="FilterBarDialogPanelTable"]) .ui5-table-root {
96
  border-bottom: none;
97
}
98
/* don't display select all checkbox */
99
:host([data-component-name="FilterBarDialogTable"]) thead th.ui5-table-select-all-column [ui5-checkbox] {
100
 visibility: hidden;
101
}
102

103
:host([data-component-name="FilterBarDialogPanelTable"]) thead th.ui5-table-select-all-column {
104
 display: none;
105
}
106
 `
107
);
108

109
type ActiveFilterAttributes = 'all' | 'visible' | 'active' | 'visibleAndActive' | 'mandatory';
110
const getActiveFilters = (
447✔
111
  activeFilterAttribute: ActiveFilterAttributes,
112
  filter: ReactElement<FilterGroupItemInternalProps>
113
) => {
114
  switch (activeFilterAttribute) {
120!
115
    case 'all':
116
      return true;
120✔
117
    case 'visible':
118
      return filter.props?.visibleInFilterBar;
×
119
    case 'active':
120
      return filter.props?.active;
×
121
    case 'visibleAndActive':
122
      return filter.props?.visibleInFilterBar && filter.props?.active;
×
123
    case 'mandatory':
124
      return filter.props?.required;
×
125
    default:
126
      return true;
×
127
  }
128
};
129

130
const compareObjects = (firstObj, secondObj) =>
447✔
131
  Object.keys(firstObj).find((first) =>
112✔
132
    Object.keys(secondObj).every((second) => firstObj[second] !== secondObj[first])
168✔
133
  );
134

135
interface FilterDialogPropTypes {
136
  filterBarRefs: any;
137
  open: boolean;
138
  handleDialogClose: (event: Ui5CustomEvent<DialogDomRef>) => void;
139
  children: ReactElement<FilterGroupItemInternalProps>[];
140
  showRestoreButton: boolean;
141
  handleRestoreFilters: (e, source, filterElements) => void;
142
  handleDialogSave: (e, newRefs, updatedToggledFilters, orderedChildren) => void;
143
  handleSearchValueChange: Dispatch<SetStateAction<string>>;
144
  handleSelectionChange?: (
145
    event: Ui5CustomEvent<
146
      TableDomRef,
147
      { element: TableRowDomRef; checked: boolean; selectedRows: unknown[]; previouslySelectedRows: unknown[] }
148
    >
149
  ) => void;
150
  handleDialogSearch?: (event: CustomEvent<{ value: string; element: HTMLElement }>) => void;
151
  handleDialogCancel?: (event: Ui5CustomEvent<HTMLElement>) => void;
152
  portalContainer: Element;
153
  onAfterFiltersDialogOpen: (event: Ui5CustomEvent<DialogDomRef>) => void;
154
  dialogRef: MutableRefObject<DialogDomRef>;
155
  enableReordering?: FilterBarPropTypes['enableReordering'];
156
  isPhone?: boolean;
157
}
158

159
export const FilterDialog = (props: FilterDialogPropTypes) => {
447✔
160
  const {
161
    filterBarRefs,
162
    open,
163
    handleDialogClose,
164
    children,
165
    showRestoreButton,
166
    handleRestoreFilters,
167
    handleDialogSave,
168
    handleSelectionChange,
169
    handleDialogSearch,
170
    handleDialogCancel,
171
    onAfterFiltersDialogOpen,
172
    portalContainer,
173
    dialogRef,
174
    enableReordering,
175
    isPhone
176
  } = props;
853✔
177
  useStylesheet(styleData, 'FilterBarDialog');
853✔
178
  const uniqueId = useIsomorphicId();
853✔
179
  const [searchString, setSearchString] = useState('');
853✔
180
  const [toggledFilters, setToggledFilters] = useState({});
853✔
181
  const dialogRefs = useRef({});
853✔
182
  const dialogSearchRef = useRef(null);
853✔
183
  const [showValues, toggleValues] = useReducer((prev) => !prev, false);
853✔
184
  const [messageBoxOpen, setMessageBoxOpen] = useState(false);
853✔
185

186
  const [forceRequired, setForceRequired] = useState<undefined | TableRowDomRef>();
853✔
187
  const [showBtnsOnHover, setShowBtnsOnHover] = useState(true);
853✔
188
  const [isListView, setIsListView] = useState(true);
853✔
189
  const [filteredAttribute, setFilteredAttribute] = useState<ActiveFilterAttributes>('all');
853✔
190
  const [currentReorderedItem, setCurrentReorderedItem] = useState<OnReorderParams | Record<string, never>>({});
853✔
191
  const tableRef = useRef(null);
853✔
192
  const okBtnRef = useRef(null);
853✔
193
  const handleReorder = (e: OnReorderParams) => {
853✔
194
    setCurrentReorderedItem(e);
50✔
195
  };
196

197
  const prevOderId = useRef(undefined);
853✔
198
  const handleFocusFallback = () => {
853✔
199
    const orderId = currentReorderedItem?.target?.dataset.orderId;
65✔
200
    if (orderId && tableRef.current && orderId !== prevOderId.current) {
65✔
201
      // we have to retrigger the internal item navigation logic after reordering,
202
      // otherwise keyboard nav and general focus handling is not working properly
203
      setTimeout(() => {
50✔
204
        const itemNav = tableRef.current._itemNavigation;
50✔
205
        itemNav._getItems = () => Array.from(tableRef.current.querySelectorAll('[ui5-table-row]'));
680✔
206
        itemNav.setCurrentItem(tableRef.current.querySelector(`[data-order-id="${orderId}"]`));
50✔
207
      });
208
      prevOderId.current = orderId;
50✔
209
    }
210
  };
211

212
  const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
853✔
213

214
  const basicText = i18nBundle.getText(BASIC);
853✔
215
  const cancelText = i18nBundle.getText(CANCEL);
853✔
216
  const okText = i18nBundle.getText(OK);
853✔
217
  const searchForFiltersText = i18nBundle.getText(SEARCH_FOR_FILTERS);
853✔
218
  const filtersTitle = i18nBundle.getText(FILTERS);
853✔
219
  const resetText = i18nBundle.getText(RESET);
853✔
220
  const allText = i18nBundle.getText(ALL);
853✔
221
  const activeText = i18nBundle.getText(ACTIVE);
853✔
222
  const visibleText = i18nBundle.getText(VISIBLE);
853✔
223
  const visibleAndActiveText = i18nBundle.getText(VISIBLE_AND_ACTIVE);
853✔
224
  const mandatoryText = i18nBundle.getText(MANDATORY);
853✔
225
  const listViewText = i18nBundle.getText(LIST_VIEW);
853✔
226
  const groupViewText = i18nBundle.getText(GROUP_VIEW);
853✔
227
  const showValuesText = i18nBundle.getText(SHOW_VALUES);
853✔
228
  const hideValuesText = i18nBundle.getText(HIDE_VALUES);
853✔
229
  const filterText = i18nBundle.getText(FILTER);
853✔
230
  const fieldsByAttributeText = i18nBundle.getText(FIELDS_BY_ATTRIBUTE);
853✔
231

232
  const visibleChildren = () =>
853✔
233
    children.filter((item) => {
131✔
234
      return !!item?.props && (typeof item.props.visible === 'undefined' || item?.props?.visible);
433✔
235
    });
236

237
  const [orderedChildren, setOrderedChildren] = useState([]);
853✔
238

239
  useEffect(() => {
853✔
240
    if (children.length) {
112✔
241
      setOrderedChildren(visibleChildren());
112✔
242
    }
243
  }, [children]);
244

245
  const renderChildren = () => {
853✔
246
    const searchStringLower = searchString.toLowerCase();
741✔
247
    const filteredChildren =
248
      searchStringLower.length > 0 || filteredAttribute !== 'all'
741✔
249
        ? orderedChildren.filter(
250
            (item) =>
321✔
251
              (searchStringLower === '' || item.props.label?.toLowerCase().includes(searchStringLower)) &&
252
              getActiveFilters(filteredAttribute, item)
253
          )
254
        : orderedChildren;
255

256
    return filteredChildren.map((child, index) => {
741✔
257
      const filterBarItemRef = filterBarRefs.current[child.key];
2,640✔
258
      let isSelected =
259
        child.props.visibleInFilterBar || child.props.required || child.type.displayName !== 'FilterGroupItem';
2,640✔
260
      if (toggledFilters.hasOwnProperty(child.key)) {
2,640✔
261
        isSelected = toggledFilters[child.key];
308✔
262
      }
263

264
      const filterItemProps = filterBarItemRef ? filterValue(filterBarItemRef, child) : {};
2,640!
265

266
      return cloneElement<FilterGroupItemInternalProps>(child, {
2,640✔
267
        'data-selected': isSelected,
268
        'data-react-key': child.key,
269
        'data-index': index,
270
        children: {
271
          ...child.props.children,
272
          props: {
273
            ...(child.props.children.props || {}),
2,640!
274
            ...filterItemProps
275
          },
276
          ref: (node) => {
UNCOV
277
            if (node) {
×
UNCOV
278
              dialogRefs.current[child.key] = node;
×
UNCOV
279
              syncRef(child.props.children.ref, node);
×
280
            }
281
          }
282
        }
283
      });
284
    });
285
  };
286

287
  const handleSearch = (e) => {
853✔
288
    if (handleDialogSearch) {
138✔
289
      handleDialogSearch(enrichEventWithDetails(e, { value: e.target.value, element: e.target }));
99✔
290
    }
291
    setSearchString(e.target.value);
138✔
292
  };
293
  const handleSave = (e) => {
853✔
294
    const orderedChildrenIds = enableReordering ? orderedChildren.map((child) => child.props.orderId) : [];
33✔
295
    handleDialogSave(e, dialogRefs.current, toggledFilters, orderedChildrenIds);
33✔
296
  };
297

298
  const handleClose = (e) => {
853✔
299
    setToggledFilters({});
14✔
300
    stopPropagation(e);
14✔
301
    if (handleDialogCancel) {
14✔
302
      handleDialogCancel(e);
14✔
303
    }
304
    handleDialogClose(e);
14✔
305
  };
306

307
  const handleCancel = (e) => {
853✔
308
    if (handleDialogCancel) {
14✔
309
      handleDialogCancel(e);
14✔
310
    }
311
    handleDialogClose(e);
14✔
312
  };
313

314
  const handleRestore = () => {
853✔
315
    setMessageBoxOpen(true);
47✔
316
  };
317
  const handleViewChange: SegmentedButtonPropTypes['onSelectionChange'] = (e) => {
853✔
318
    setIsListView(e.detail.selectedItem.dataset.id === 'list');
20✔
319
  };
320

321
  const handleMessageBoxClose = (e) => {
853✔
322
    if (e.detail.action === 'OK') {
47✔
323
      setToggledFilters({});
19✔
324
      setOrderedChildren(visibleChildren());
19✔
325
      handleRestoreFilters(e, 'dialog', { filters: Array.from(dialogRef.current.querySelectorAll('ui5-table-row')) });
19✔
326
    }
327
    setMessageBoxOpen(false);
47✔
328
    okBtnRef.current.focus();
47✔
329
  };
330

331
  const [updatedIndex, setUpdatedIndex] = useState(undefined);
853✔
332
  useEffect(() => {
853✔
333
    if (currentReorderedItem?.index != null) {
162✔
334
      setOrderedChildren((prev: any[]) => {
50✔
335
        const { index, direction } = currentReorderedItem;
50✔
336
        switch (direction) {
50✔
337
          case 'up':
338
            if (index > 0) {
10✔
339
              setUpdatedIndex(index - 1);
10✔
340
              const temp = prev[index];
10✔
341
              prev[index] = prev[index - 1];
10✔
342
              prev[index - 1] = temp;
10✔
343
            }
344
            break;
10✔
345
          case 'down':
346
            if (index < prev.length - 1) {
10✔
347
              setUpdatedIndex(index + 1);
10✔
348
              const temp = prev[index];
10✔
349
              prev[index] = prev[index + 1];
10✔
350
              prev[index + 1] = temp;
10✔
351
            }
352
            break;
10✔
353
          case 'top':
354
            if (index > 0) {
10✔
355
              setUpdatedIndex(0);
10✔
356
              const item = prev.splice(index, 1)[0];
10✔
357
              prev.unshift(item);
10✔
358
            }
359
            break;
10✔
360
          case 'bottom':
361
            if (index < prev.length - 1) {
20✔
362
              setUpdatedIndex(prev.length - 1);
20✔
363
              const item = prev.splice(index, 1)[0];
20✔
364
              prev.push(item);
20✔
365
            }
366
            break;
20✔
367
        }
368
        return [...prev];
50✔
369
      });
370
      void currentReorderedItem.target.focus();
50✔
371
    }
372
  }, [currentReorderedItem]);
373

374
  useEffect(() => {
853✔
375
    if (updatedIndex != null) {
157✔
376
      prevOderId.current = undefined;
45✔
377
    }
378
  }, [updatedIndex]);
379

380
  const handleAttributeFilterChange = (e) => {
853✔
381
    setFilteredAttribute(e.detail.selectedOption.dataset.id);
×
382
  };
383

384
  const handleCheckBoxChange = (e) => {
853✔
385
    if (e.target.hasAttribute('ui5-table')) {
112✔
386
      // preventDefault should only be called if the target is the table, otherwise bubbled `selection-change` events
387
      // also prevent their default behavior (e.g. the event of the MultiComboBox)
388
      e.preventDefault();
112✔
389
      const prevRowsByKey = e.detail.previouslySelectedRows.reduce(
112✔
390
        (acc, prevSelRow) => ({ ...acc, [prevSelRow.dataset.reactKey]: prevSelRow }),
280✔
391
        {}
392
      );
393
      const rowsByKey = e.detail.selectedRows.reduce(
112✔
394
        (acc, selRow) => ({ ...acc, [selRow.dataset.reactKey]: selRow }),
168✔
395
        {}
396
      );
397

398
      const changedRowKey =
399
        e.detail.previouslySelectedRows > e.detail.selectedRows
112!
400
          ? compareObjects(prevRowsByKey, rowsByKey)
401
          : compareObjects(rowsByKey, prevRowsByKey);
402

403
      const element = rowsByKey[changedRowKey] || prevRowsByKey[changedRowKey];
112✔
404

405
      // todo: workaround until specific rows can be disabled
406
      if (element.dataset?.required === 'true') {
112!
407
        setForceRequired(element);
×
408
        return;
×
409
      }
410

411
      if (typeof handleSelectionChange === 'function') {
112✔
412
        handleSelectionChange(enrichEventWithDetails(e, { element, checked: element.selected }));
112✔
413
      }
414

415
      setToggledFilters((prev) => {
112✔
416
        return { ...prev, [changedRowKey]: element.selected };
112✔
417
      });
418
    }
419
  };
420

421
  useEffect(() => {
853✔
422
    if (forceRequired) {
112!
423
      forceRequired.setAttribute('selected', 'true');
×
424
      setForceRequired(undefined);
×
425
    }
426
  }, [forceRequired]);
427

428
  const canRenderPortal = useCanRenderPortal();
853✔
429
  if (!canRenderPortal) {
853✔
430
    return null;
112✔
431
  }
432

433
  const renderGroups = () => {
741✔
434
    const groups = {};
74✔
435
    Children.forEach(renderChildren(), (child) => {
74✔
436
      const childGroups = child.props.groupName ?? 'default';
132✔
437
      if (groups[childGroups]) {
132✔
438
        groups[childGroups].push(child);
22✔
439
      } else {
440
        groups[childGroups] = [child];
110✔
441
      }
442
    });
443

444
    const filterGroups = Object.keys(groups)
74✔
445
      .sort((x, y) => (x === 'default' ? -1 : y === 'role' ? 1 : 0))
81!
446
      .map((item, index) => {
447
        return (
110✔
448
          <Panel
449
            headerText={item === 'default' ? basicText : item}
110✔
450
            className={classNames.groupPanel}
451
            key={`${item === 'default' ? basicText : item}${index}`}
110✔
452
          >
453
            <Table
454
              mode={TableMode.MultiSelect}
455
              data-component-name="FilterBarDialogPanelTable"
456
              onSelectionChange={handleCheckBoxChange}
457
            >
458
              {groups[item]}
459
            </Table>
460
          </Panel>
461
        );
462
      });
463
    return filterGroups;
74✔
464
  };
465

466
  const currentReorderedItemOrderId = currentReorderedItem?.orderId;
741✔
467

468
  return (
741✔
469
    <FilterBarDialogContext.Provider
470
      value={{
471
        isFilterInDialog: true,
472
        enableReordering,
473
        onReorder: handleReorder,
474
        isListView,
475
        withValues: showValues,
476
        handleFocusFallback,
477
        showBtnsOnHover,
478
        setShowBtnsOnHover,
479
        currentReorderedItemOrderId
480
      }}
481
    >
482
      {createPortal(
483
        <Dialog
484
          open={open}
485
          ref={dialogRef}
486
          data-component-name="FilterBarDialog"
487
          data-is-phone={isPhone}
488
          onAfterClose={handleClose}
489
          onAfterOpen={onAfterFiltersDialogOpen}
490
          resizable
491
          draggable
492
          className={classNames.dialogComponent}
493
          preventFocusRestore
494
          initialFocus={`${uniqueId}-fb-dialog-search`}
495
          header={
496
            <Bar
497
              design={BarDesign.Header}
498
              startContent={
499
                <Title level={TitleLevel.H4} title={filtersTitle}>
500
                  {filtersTitle}
501
                </Title>
502
              }
503
              endContent={
504
                showRestoreButton && (
1,259✔
505
                  <Button design={ButtonDesign.Transparent} onClick={handleRestore}>
506
                    {resetText}
507
                  </Button>
508
                )
509
              }
510
            />
511
          }
512
          footer={
513
            <Bar
514
              design={BarDesign.Footer}
515
              endContent={
516
                <FlexBox justifyContent={FlexBoxJustifyContent.End} className={classNames.footer}>
517
                  <Button
518
                    ref={okBtnRef}
519
                    onClick={handleSave}
520
                    data-component-name="FilterBarDialogSaveBtn"
521
                    design={ButtonDesign.Emphasized}
522
                  >
523
                    {okText}
524
                  </Button>
525
                  <Button
526
                    design={ButtonDesign.Transparent}
527
                    onClick={handleCancel}
528
                    data-component-name="FilterBarDialogCancelBtn"
529
                  >
530
                    {cancelText}
531
                  </Button>
532
                </FlexBox>
533
              }
534
            />
535
          }
536
        >
537
          <FlexBox direction={FlexBoxDirection.Column} className={classNames.subheaderContainer}>
538
            <Toolbar className={classNames.subheader} toolbarStyle={ToolbarStyle.Clear}>
539
              <Select
540
                onChange={handleAttributeFilterChange}
541
                title={fieldsByAttributeText}
542
                accessibleName={fieldsByAttributeText}
543
              >
544
                <Option selected={filteredAttribute === 'all'} data-id="all">
545
                  {allText}
546
                </Option>
547
                <Option selected={filteredAttribute === 'visible'} data-id="visible">
548
                  {visibleText}
549
                </Option>
550
                <Option selected={filteredAttribute === 'active'} data-id="active">
551
                  {activeText}
552
                </Option>
553
                <Option selected={filteredAttribute === 'visibleAndActive'} data-id="visibleAndActive">
554
                  {visibleAndActiveText}
555
                </Option>
556
                <Option selected={filteredAttribute === 'mandatory'} data-id="mandatory">
557
                  {mandatoryText}
558
                </Option>
559
              </Select>
560
              <ToolbarSpacer />
561
              <Button design={ButtonDesign.Transparent} onClick={toggleValues} aria-live="polite">
562
                {showValues ? hideValuesText : showValuesText}
741✔
563
              </Button>
564
              <SegmentedButton onSelectionChange={handleViewChange}>
565
                <SegmentedButtonItem
566
                  icon={listIcon}
567
                  data-id="list"
568
                  pressed={isListView}
569
                  accessibleName={listViewText}
570
                />
571
                <SegmentedButtonItem
572
                  icon={group2Icon}
573
                  data-id="group"
574
                  pressed={!isListView}
575
                  accessibleName={groupViewText}
576
                />
577
              </SegmentedButton>
578
            </Toolbar>
579
            <FlexBox className={classNames.searchInputContainer}>
580
              <Input
581
                id={`${uniqueId}-fb-dialog-search`}
582
                noTypeahead
583
                placeholder={searchForFiltersText}
584
                onInput={handleSearch}
585
                showClearIcon
586
                icon={<Icon name={searchIcon} />}
587
                ref={dialogSearchRef}
588
                className={classNames.searchInput}
589
                data-component-name="FilterBarDialogSearchInput"
590
              />
591
            </FlexBox>
592
          </FlexBox>
593
          <Table
594
            ref={tableRef}
595
            data-component-name="FilterBarDialogTable"
596
            hideNoData={!isListView}
597
            mode={TableMode.MultiSelect}
598
            onSelectionChange={handleCheckBoxChange}
599
            tabIndex={!isListView ? -1 : undefined}
741✔
600
            columns={
601
              <>
602
                <TableColumn>{filterText}</TableColumn>
603
                {!showValues && <TableColumn className={classNames.tHactive}>{activeText}</TableColumn>}
1,216✔
604
              </>
605
            }
606
          >
607
            {isListView && renderChildren()}
1,408✔
608
          </Table>
609
          {!isListView && renderGroups()}
815✔
610
        </Dialog>,
611
        portalContainer ?? document.body
1,482✔
612
      )}
613
      {showRestoreButton &&
1,306✔
614
        messageBoxOpen &&
615
        createPortal(
616
          <MessageBox
617
            open
618
            type={MessageBoxTypes.Warning}
619
            actions={[MessageBoxActions.OK, MessageBoxActions.Cancel]}
620
            onClose={handleMessageBoxClose}
621
            data-component-name="FilterBarDialogResetMessageBox"
622
          >
623
            {i18nBundle.getText(FILTER_DIALOG_RESET_WARNING)}
624
          </MessageBox>,
625
          portalContainer ?? document.body
94✔
626
        )}
627
    </FilterBarDialogContext.Provider>
628
  );
629
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc