Add column enum filter.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
71b10a3c89
commit
267afa68dd
2 changed files with 83 additions and 1 deletions
69
src/Smartable/Filters/EnumFilter.tsx
Normal file
69
src/Smartable/Filters/EnumFilter.tsx
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import React, {useCallback} from "react";
|
||||||
|
import {ColumnFilter, useFilterState} from "../Columns/ColumnFilter";
|
||||||
|
import {Select} from "@kernelui/core";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String column filter.
|
||||||
|
*/
|
||||||
|
export function EnumFilter<OptionKey extends keyof any, Option>(options: Record<OptionKey, Option>): ColumnFilter<OptionKey[], EnumFilterState<OptionKey>>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
{
|
||||||
|
filter: (data: OptionKey|OptionKey[], filterState: EnumFilterState<OptionKey>) => {
|
||||||
|
// Normalized data array.
|
||||||
|
const dataArray = Array.isArray(data) ? data : [data];
|
||||||
|
|
||||||
|
// Nothing in filter value, allow everything.
|
||||||
|
if (!filterState?.value?.length) return true;
|
||||||
|
|
||||||
|
// Get current filter result.
|
||||||
|
return filterState?.value?.some(
|
||||||
|
// Keep the row if any element in data match the current filter value.
|
||||||
|
(optionKey) => dataArray.includes(optionKey)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
element: <EnumFilterComponent options={options} />
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumeration filter state.
|
||||||
|
*/
|
||||||
|
export interface EnumFilterState<OptionKey extends keyof any>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Filter value.
|
||||||
|
*/
|
||||||
|
value: OptionKey[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum filter component.
|
||||||
|
*/
|
||||||
|
export function EnumFilterComponent<OptionKey extends keyof any, Option>({options}: {
|
||||||
|
/**
|
||||||
|
* Enum options.
|
||||||
|
*/
|
||||||
|
options: Record<OptionKey, Option>;
|
||||||
|
})
|
||||||
|
{
|
||||||
|
// Initialize enum filter state.
|
||||||
|
const [enumFilterState, setEnumFilterState] =
|
||||||
|
useFilterState<EnumFilterState<OptionKey>>({ value: [] });
|
||||||
|
|
||||||
|
// Handle filter input change.
|
||||||
|
const handleChange = useCallback((filter: OptionKey[]) => {
|
||||||
|
// Save the current filter value.
|
||||||
|
setEnumFilterState({
|
||||||
|
value: filter,
|
||||||
|
})
|
||||||
|
}, [setEnumFilterState]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select<OptionKey, Option> options={options} multiple={true} size={1}
|
||||||
|
className={!enumFilterState.value?.length ? "empty" : undefined}
|
||||||
|
value={enumFilterState.value} onChange={handleChange} />
|
||||||
|
)
|
||||||
|
}
|
|
@ -9,9 +9,22 @@ tr.filters
|
||||||
padding-left: 0.25em;
|
padding-left: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input
|
input, .select
|
||||||
{
|
{
|
||||||
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select
|
||||||
|
{
|
||||||
|
ul.selected
|
||||||
|
{
|
||||||
|
margin: 0 0 0.25em 0;
|
||||||
|
}
|
||||||
|
&.empty ul.selected
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue