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

feat: add filterTooltipValueFn option to transform the value of the filter tooltip #360

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,16 @@ export const columnOptions: ColumnOption[] = [
required: false,
type: 'MRT_FilterFn',
},
{
columnOption: 'filterTooltipValueFn',
defaultValue: '',
description: 'Specify to transform tooltip values to a readable format.',
link: '',
linkText: '',
source: 'MRT',
required: false,
type: 'MRT_FilterTooltipValueFn',
},
{
columnOption: 'filterVariant',
defaultValue: "'text'",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export const MRT_TableHeadCellFilterLabel = <TData extends MRT_RowData>({
columnDef._filterFn,
);
const currentFilterOption = columnDef._filterFn;
const filterValueFn =
columnDef.filterTooltipValueFn || ((value) => value as string);
type FilterValueType = Parameters<typeof filterValueFn>[0];
const filterTooltip =
columnFilterDisplayMode === 'popover' && !isFilterActive
? localization.filterByColumn?.replace(
Expand All @@ -70,10 +73,17 @@ export const MRT_TableHeadCellFilterLabel = <TData extends MRT_RowData>({
'{filterValue}',
`"${
Array.isArray(column.getFilterValue())
? (column.getFilterValue() as [string, string]).join(
`" ${isRangeFilter ? localization.and : localization.or} "`,
? (
column.getFilterValue() as [
FilterValueType,
FilterValueType,
]
)
: (column.getFilterValue() as string)
.map((v) => filterValueFn(v))
.join(
`" ${isRangeFilter ? localization.and : localization.or} "`,
)
: filterValueFn(column.getFilterValue())
}"`,
)
.replace('" "', '');
Expand Down
3 changes: 3 additions & 0 deletions packages/mantine-react-table/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ export type MRT_ColumnDef<TData extends MRT_RowData, TValue = unknown> = Omit<
enableEditing?: ((row: MRT_Row<TData>) => boolean) | boolean;
enableFilterMatchHighlighting?: boolean;
filterFn?: MRT_FilterFn<TData>;
filterTooltipValueFn?: MRT_FilterTooltipValueFn;
filterVariant?:
| 'autocomplete'
| 'checkbox'
Expand Down Expand Up @@ -737,6 +738,8 @@ export type MRT_FilterFn<TData extends MRT_RowData> =
| FilterFn<TData>
| MRT_FilterOption;

export type MRT_FilterTooltipValueFn<TValue = any> = (value: TValue) => string;

export type MRT_InternalFilterOption = {
divider: boolean;
label: string;
Expand Down
135 changes: 134 additions & 1 deletion packages/mantine-react-table/stories/features/Filtering.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import { useEffect, useState } from 'react';
import { Button, Flex } from '@mantine/core';
import { Button, Checkbox, Flex, Group, SegmentedControl } from '@mantine/core';
import {
type MRT_ColumnDef,
type MRT_ColumnFiltersState,
type MRT_FilterTooltipValueFn,
MantineReactTable,
} from '../../src';
import { faker } from '@faker-js/faker';
import { type Meta } from '@storybook/react';

import { MRT_Localization_EN } from '../../src/locales/en';
import { MRT_Localization_JA } from '../../src/locales/ja';

import dayjs from 'dayjs';
import isBetween from 'dayjs/plugin/isBetween';
import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(isBetween);
dayjs.extend(localizedFormat);
import Dayjs_EN from 'dayjs/locale/en';
import Dayjs_JA from 'dayjs/locale/ja';

const meta: Meta = {
title: 'Features/Filtering Examples',
};
Expand Down Expand Up @@ -730,3 +742,124 @@ export const ExternalSetFilterValue = () => (
)}
/>
);

export const CustomTooltipValueFn = () => {
const [localization, setLocalization] = useState(MRT_Localization_EN);
const [locale, setLocale] = useState<string | undefined>('en');
const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(
[],
);
const [isActiveValueFn, setIsActiveValueFn] = useState<
MRT_FilterTooltipValueFn<string> | undefined
>(undefined);
const [dateValueFn, setDateValueFn] = useState<
MRT_FilterTooltipValueFn<Date> | undefined
>(undefined);
const [enableValueFns, setEnableValueFns] = useState(true);

const formatDate = (date: any, format: string) => {
const d = dayjs(date || '');
return d.isValid() ? d.format(format) : '';
};
const formatIsActiveValue = () => (value: string) =>
value === 'true' ? 'Yes' : 'No';
const formatDateValue = () => (value: Date) => formatDate(value, 'L');

useEffect(() => {
switch (locale) {
case 'en':
setLocalization(MRT_Localization_EN);
dayjs.locale(Dayjs_EN);
break;
case 'ja':
setLocalization(MRT_Localization_JA);
dayjs.locale(Dayjs_JA);
break;
}
}, [locale]);

useEffect(() => {
if (enableValueFns) {
setIsActiveValueFn(formatIsActiveValue);
setDateValueFn(formatDateValue);
} else {
setIsActiveValueFn(undefined);
setDateValueFn(undefined);
}
}, [enableValueFns]);

return (
<>
<MantineReactTable
renderTopToolbarCustomActions={() => (
<Group>
<Checkbox
label="Enable Custom Tooltip Value Fn"
checked={enableValueFns}
onChange={(event) =>
setEnableValueFns(event.currentTarget.checked)
}
/>
<SegmentedControl
data={['en', 'ja']}
value={locale}
onChange={setLocale}
/>
</Group>
)}
localization={localization}
columns={[
{
Cell: ({ cell }) => (cell.getValue() === 'true' ? 'Yes' : 'No'),
accessorFn: (originalRow) =>
originalRow.isActive ? 'true' : 'false',
filterVariant: 'checkbox',
filterTooltipValueFn: isActiveValueFn, //transform data to readable format for tooltip
header: 'Is Active',
id: 'isActive',
size: 200,
},
{
accessorKey: 'firstName',
header: 'First Name',
},
{
accessorKey: 'lastName',
header: 'Last Name',
},
{
Cell: ({ cell }) => formatDate(cell.getValue<Date>(), 'L'), //transform data to readable format for cell render
mantineFilterDateInputProps: {
locale: locale,
valueFormat: 'L',
},
accessorFn: (row) => new Date(row.birthDate), //transform data before processing so sorting works
accessorKey: 'birthDate',
filterVariant: 'date',
filterTooltipValueFn: dateValueFn, //transform data to readable format for tooltip
header: 'Birth Date (date)',
sortingFn: 'datetime',
},
{
Cell: ({ cell }) => formatDate(cell.getValue<Date>(), 'L'), //transform data to readable format for cell render
mantineFilterDateInputProps: {
locale: locale,
valueFormat: 'L',
},
accessorFn: (row) => new Date(row.birthDate), //transform data before processing so sorting works
accessorKey: 'birthDateRange',
filterVariant: 'date-range',
filterTooltipValueFn: dateValueFn, //transform data to readable format for tooltip
header: 'Birth Date (date-range)',
sortingFn: 'datetime',
},
]}
data={data}
onColumnFiltersChange={setColumnFilters}
state={{
columnFilters,
}}
/>
</>
);
};
Loading