@@ -13,62 +13,92 @@ import cx from "clsx";
1313
1414import columnFilterCss from "./ColumnFilter.css" ;
1515import { getDataItemEditControl } from "@vuu-ui/vuu-data-react" ;
16- import { useCallback , useMemo } from "react" ;
17- import { CommitHandler } from "@vuu-ui/vuu-utils" ;
16+ import { ForwardedRef , forwardRef , ReactElement , useMemo } from "react" ;
1817import { VuuTable } from "@vuu-ui/vuu-protocol-types" ;
19- import {
20- assertValidValue ,
21- ColumnFilterHookProps ,
22- FilterValue ,
23- } from "./useColumnFilter" ;
18+ import { assertValidOperator , assertValidValue , Operator , useColumnFilter } from "./useColumnFilter" ;
19+ import { ColumnDescriptor } from "@vuu-ui/vuu-table-types" ;
2420
2521const classBase = "vuuColumnFilter" ;
22+ export type FilterValue = string | readonly string [ ] | number ;
23+ export type ColumnFilterValue = FilterValue | [ FilterValue , FilterValue ] ;
2624
27- export interface ColumnFilterProps
28- extends ColumnFilterHookProps ,
29- SegmentedButtonGroupProps {
25+ export interface ColumnFilterProps extends SegmentedButtonGroupProps {
26+ column : ColumnDescriptor ;
27+ operator ?: Operator ;
28+ /**
29+ * Display operator picker.
30+ */
3031 showOperatorPicker ?: boolean ;
3132 /**
3233 * VuuTable is required if typeahead support is expected.
3334 */
3435 table ?: VuuTable ;
35-
3636 /**
37- * Initial filter value. Pair of values expewcted when operator is
37+ * Filter value. Pair of values expected when operator is
3838 * 'between'
3939 */
40- value ?: FilterValue | [ FilterValue , FilterValue ] ;
40+ value ?: ColumnFilterValue ;
41+ /**
42+ * Filter change events.
43+ */
44+ onFilterChange ?: (
45+ value : ColumnFilterValue | undefined ,
46+ columnName : string ,
47+ op : Operator ,
48+ ) => void ;
4149}
4250
43- export const ColumnFilter = ( {
44- column,
45- className,
46- operator = "=" ,
47- showOperatorPicker = false ,
48- table,
49- value,
50- ...buttonGroupProps
51- } : ColumnFilterProps ) => {
51+ export const ColumnFilter = forwardRef ( function ColumnFilter (
52+ {
53+ column,
54+ className,
55+ operator = "=" ,
56+ showOperatorPicker = false ,
57+ table,
58+ value,
59+ onFilterChange,
60+ ...buttonGroupProps
61+ } : ColumnFilterProps ,
62+ forwardRef : ForwardedRef < HTMLDivElement > ,
63+ ) {
5264 const targetWindow = useWindow ( ) ;
5365 useComponentCssInjection ( {
54- testId : "vuu-filter-bar " ,
66+ testId : "vuu-column-filter " ,
5567 css : columnFilterCss ,
5668 window : targetWindow ,
5769 } ) ;
5870
71+ const {
72+ op,
73+ allowedOperators,
74+ filterValue,
75+ inputProps,
76+ rangeInputProps,
77+ onOperatorChange,
78+ handleCommit,
79+ handleRangeCommit,
80+ } = useColumnFilter ( {
81+ operator,
82+ column,
83+ value,
84+ onFilterChange,
85+ } ) ;
86+
5987 useMemo (
60- ( ) => assertValidValue ( column , operator , value ) ,
61- [ column , operator , value ] ,
88+ ( ) => assertValidOperator ( allowedOperators , column , operator ) ,
89+ [ column , operator , allowedOperators ] ,
6290 ) ;
6391
64- const onCommit = useCallback < CommitHandler < HTMLElement > > ( ( e , value ) => {
65- console . log ( `onCommit ${ value } ` ) ;
66- } , [ ] ) ;
92+ useMemo (
93+ ( ) => assertValidValue ( column , op , filterValue ) ,
94+ [ column , op , filterValue ] ,
95+ ) ;
6796
6897 return (
6998 < SegmentedButtonGroup
7099 { ...buttonGroupProps }
71100 className = { cx ( classBase , className ) }
101+ ref = { forwardRef }
72102 >
73103 { showOperatorPicker ? (
74104 < Menu placement = "bottom-start" >
@@ -80,37 +110,44 @@ export const ColumnFilter = ({
80110 data-embedded
81111 sentiment = "neutral"
82112 >
83- { operator }
113+ { op }
84114 </ Button >
85115 </ MenuTrigger >
86116 < MenuPanel >
87- < MenuItem > =</ MenuItem >
88- < MenuItem > !=</ MenuItem >
89- < MenuItem > starts</ MenuItem >
90- < MenuItem > ends</ MenuItem >
91- < MenuItem > contains</ MenuItem >
117+ { allowedOperators . map ( ( operator ) => (
118+ < MenuItem
119+ key = { operator }
120+ onClick = { ( ) => onOperatorChange ( operator ) }
121+ >
122+ { operator }
123+ </ MenuItem >
124+ ) ) }
92125 </ MenuPanel >
93126 </ Menu >
94127 ) : null }
95128 { getDataItemEditControl ( {
129+ InputProps : { inputProps } ,
96130 dataDescriptor : column ,
97- defaultValue : Array . isArray ( value )
98- ? ( value [ 0 ] as string )
99- : ( value as string ) ,
100- onCommit,
131+ onCommit : handleCommit ,
132+ defaultValue : Array . isArray ( filterValue ) ? filterValue [ 0 ] : filterValue ,
101133 table,
102134 } ) }
103- { operator === "between"
135+ { op === "between"
104136 ? getDataItemEditControl ( {
105137 className : `${ classBase } -rangeHigh` ,
138+ InputProps : { inputProps : rangeInputProps } ,
106139 dataDescriptor : column ,
107- defaultValue : Array . isArray ( value )
108- ? ( value [ 1 ] as string )
109- : undefined ,
110- onCommit ,
140+ onCommit : handleRangeCommit ,
141+ defaultValue : Array . isArray ( filterValue )
142+ ? filterValue [ 1 ]
143+ : filterValue ,
111144 table,
112145 } )
113146 : null }
114147 </ SegmentedButtonGroup >
115148 ) ;
116- } ;
149+ } ) as (
150+ props : ColumnFilterProps & {
151+ ref ?: ForwardedRef < HTMLDivElement > ;
152+ } ,
153+ ) => ReactElement < ColumnFilterProps > ;
0 commit comments