@@ -54,6 +54,15 @@ const DEFAULT_OPERATOR: Record<FilterConfig["type"], FilterOperator> = {
5454const NUMERIC_TEMPORAL_OPERATORS = [ "eq" , "ne" , "gt" , "gte" , "lt" , "lte" , "between" ] as const ;
5555type NumericTemporalOperator = ( typeof NUMERIC_TEMPORAL_OPERATORS ) [ number ] ;
5656
57+ // Date filters use a slimmer, friendlier operator set: an exact date, inclusive
58+ // "after"/"before" (gte/lte), and a between range. No gt/lt/ne.
59+ const DATE_OPERATORS = [ "eq" , "gte" , "lte" , "between" ] as const ;
60+
61+ /** Operators offered for a temporal editor, narrowed for `date` columns. */
62+ function temporalOperatorsFor ( type : FilterConfig [ "type" ] ) : readonly NumericTemporalOperator [ ] {
63+ return type === "date" ? DATE_OPERATORS : NUMERIC_TEMPORAL_OPERATORS ;
64+ }
65+
5766/** String operators available in the operator selector. */
5867const STRING_OPERATORS = [ "eq" , "ne" , "contains" , "notContains" , "hasPrefix" , "hasSuffix" ] as const ;
5968type StringOperator = ( typeof STRING_OPERATORS ) [ number ] ;
@@ -489,7 +498,7 @@ function AddFilterPopover({
489498 } }
490499 mapItem = { ( op ) => ( {
491500 value : op ,
492- label : getOperatorLabel ( op , t ) ,
501+ label : getOperatorLabel ( op , t , selectedColumn ?. filter . type ) ,
493502 } ) }
494503 className = "astw:h-8 astw:text-sm"
495504 />
@@ -920,8 +929,9 @@ function NumericFilterEditor({
920929 onClose : ( ) => void ;
921930} ) {
922931 const t = useDataTableT ( ) ;
932+ const operatorItems = temporalOperatorsFor ( config . type ) ;
923933 const [ localOp , setLocalOp ] = useState < NumericTemporalOperator > (
924- NUMERIC_TEMPORAL_OPERATORS . includes ( filter . operator as NumericTemporalOperator )
934+ operatorItems . includes ( filter . operator as NumericTemporalOperator )
925935 ? ( filter . operator as NumericTemporalOperator )
926936 : "eq" ,
927937 ) ;
@@ -985,12 +995,12 @@ function NumericFilterEditor({
985995 className = "astw:flex astw:flex-col astw:gap-2 astw:p-2"
986996 >
987997 < Select
988- items = { [ ...NUMERIC_TEMPORAL_OPERATORS ] }
998+ items = { [ ...operatorItems ] }
989999 value = { localOp }
9901000 onValueChange = { ( v ) => {
9911001 if ( v ) setLocalOp ( v ) ;
9921002 } }
993- mapItem = { ( op ) => ( { value : op , label : t ( `filterOperator_ ${ op } ` ) } ) }
1003+ mapItem = { ( op ) => ( { value : op , label : getOperatorLabel ( op , t , config . type ) } ) }
9941004 className = "astw:h-8 astw:text-sm"
9951005 />
9961006 { localOp === "between" ? (
@@ -1036,8 +1046,9 @@ function TemporalFilterEditor({
10361046 onClose : ( ) => void ;
10371047} ) {
10381048 const t = useDataTableT ( ) ;
1049+ const operatorItems = temporalOperatorsFor ( config . type ) ;
10391050 const [ localOp , setLocalOp ] = useState < NumericTemporalOperator > (
1040- NUMERIC_TEMPORAL_OPERATORS . includes ( filter . operator as NumericTemporalOperator )
1051+ operatorItems . includes ( filter . operator as NumericTemporalOperator )
10411052 ? ( filter . operator as NumericTemporalOperator )
10421053 : "eq" ,
10431054 ) ;
@@ -1151,12 +1162,12 @@ function TemporalFilterEditor({
11511162 className = "astw:flex astw:flex-col astw:gap-2 astw:p-2"
11521163 >
11531164 < Select
1154- items = { [ ...NUMERIC_TEMPORAL_OPERATORS ] }
1165+ items = { [ ...operatorItems ] }
11551166 value = { localOp }
11561167 onValueChange = { ( v ) => {
11571168 if ( v ) setLocalOp ( v ) ;
11581169 } }
1159- mapItem = { ( op ) => ( { value : op , label : t ( `filterOperator_ ${ op } ` ) } ) }
1170+ mapItem = { ( op ) => ( { value : op , label : getOperatorLabel ( op , t , config . type ) } ) }
11601171 className = "astw:h-8 astw:text-sm"
11611172 />
11621173 { valueInput }
@@ -1175,9 +1186,10 @@ function getAddFilterOperators(type: FilterConfig["type"]): FilterOperator[] {
11751186 switch ( type ) {
11761187 case "string" :
11771188 return [ ...STRING_OPERATORS ] ;
1189+ case "date" :
1190+ return [ ...DATE_OPERATORS ] ;
11781191 case "number" :
11791192 case "datetime" :
1180- case "date" :
11811193 case "time" :
11821194 return [ ...NUMERIC_TEMPORAL_OPERATORS ] ;
11831195 case "enum" :
@@ -1311,7 +1323,17 @@ function getTemporalInputProps(type: "datetime" | "date" | "time") {
13111323 }
13121324}
13131325
1314- function getOperatorLabel ( operator : FilterOperator , t : ReturnType < typeof useDataTableT > ) : string {
1326+ function getOperatorLabel (
1327+ operator : FilterOperator ,
1328+ t : ReturnType < typeof useDataTableT > ,
1329+ type ?: FilterConfig [ "type" ] ,
1330+ ) : string {
1331+ // Date columns relabel the comparison operators (exact date / after / before).
1332+ if ( type === "date" ) {
1333+ if ( operator === "eq" ) return t ( "filterDateOperator_eq" ) ;
1334+ if ( operator === "gte" ) return t ( "filterDateOperator_gte" ) ;
1335+ if ( operator === "lte" ) return t ( "filterDateOperator_lte" ) ;
1336+ }
13151337 switch ( operator ) {
13161338 case "eq" :
13171339 return t ( "filterOperator_eq" ) ;
@@ -1397,7 +1419,7 @@ function getChipDisplayLabel(
13971419 const valueLabel = formatFilterValue ( filter , config , t ) ;
13981420 if ( ! valueLabel ) return columnLabel ;
13991421
1400- const operatorLabel = getOperatorLabel ( filter . operator , t ) ;
1422+ const operatorLabel = getOperatorLabel ( filter . operator , t , config . type ) ;
14011423 const ciSuffix = filter . caseSensitive ? " (Aa)" : "" ;
14021424
14031425 if ( config . type === "enum" ) {
0 commit comments