export function CategoricalFilter()

in src/data-table/column-categorical.tsx [115:213]


export function CategoricalFilter(props: CategoricalFilterProps) {
  const [css, theme] = useStyletron();
  const locale = React.useContext(LocaleContext);
  const [selection, setSelection] = React.useState<Set<string>>(
    props.filterParams ? props.filterParams.selection : new Set()
  );
  const [exclude, setExclude] = React.useState(
    props.filterParams ? props.filterParams.exclude : false
  );
  const [query, setQuery] = React.useState('');
  const categories: Set<string> = React.useMemo(() => {
    return props.data.reduce((set, category) => set.add(category), new Set<string>());
  }, [props.data]);

  const checkboxStyles = css({ marginBottom: theme.sizing.scale200 });

  const showQuery = Boolean(categories.size >= 10);
  const filteredCategories = Array.from(categories, (c) => c).filter((c) => matchesQuery(c, query));

  return (
    <FilterShell
      exclude={exclude}
      onExcludeChange={() => setExclude(!exclude)}
      onApply={() => {
        props.setFilter({
          description: Array.from(selection).join(', '),
          exclude,
          selection,
        });
        props.close();
      }}
    >
      {showQuery && (
        <Input
          aria-label={locale.datatable.categoricalFilterSearchLabel}
          size={INPUT_SIZE.compact}
          overrides={{ Before: InputBefore }}
          value={query}
          onChange={(event) => setQuery(event.target.value)}
          clearable
        />
      )}

      <div
        style={{
          // @ts-ignore
          marginTop: showQuery ? theme.sizing.scale600 : null,
        }}
      >
        <FilterQuickControls
          onSelectAll={() => {
            filteredCategories.forEach((c) => selection.add(c));
            setSelection(new Set(selection));
          }}
          onClearSelection={() => {
            setSelection(new Set());
          }}
        />
      </div>

      <div
        className={css({
          maxHeight: '256px',
          overflowY: 'auto',
          marginTop: theme.sizing.scale600,
          position: 'relative',
        })}
      >
        {!filteredCategories.length && (
          <LabelSmall>{locale.datatable.categoricalFilterEmpty}</LabelSmall>
        )}

        {Boolean(filteredCategories.length) &&
          filteredCategories.map((category, i) => (
            <div className={checkboxStyles} key={i}>
              {/* @ts-ignore */}
              <Checkbox
                checked={selection.has(category)}
                onChange={() => {
                  if (selection.has(category)) {
                    selection.delete(category);
                  } else {
                    selection.add(category);
                  }
                  setSelection(new Set(selection));
                }}
                overrides={{
                  // @ts-ignore
                  Label: { component: HighlightCheckboxLabel, props: { query } },
                }}
              >
                {category}
              </Checkbox>
            </div>
          ))}
      </div>
    </FilterShell>
  );
}