@@ -8,6 +8,9 @@ import { Student } from '..'
88import type { FilterContext , FilterViewContextState } from '../context'
99import type { FilterTrayProps } from '../FilterTray'
1010
11+ type Selector < T , R > = ( options : FilterContext [ 'options' ] , args : T ) => R
12+ type Action < P > = ( options : FilterContext [ 'options' ] , payload : P ) => void
13+
1114export type Filter = {
1215 args ?: any
1316
@@ -50,7 +53,7 @@ export type Filter = {
5053 */
5154 render : ( props : FilterTrayProps , ctx : FilterContext ) => ReactNode
5255
53- isActive : ( opts : FilterContext [ 'options' ] ) => boolean
56+ isActive : Selector < void , boolean >
5457}
5558
5659/** TODO: Find acual types */
@@ -59,24 +62,24 @@ type FilterOptions = Filter & {
5962 * Redux selectors.
6063 * `selectOptions` and `isActive` will be overwriten.
6164 */
62- selectors ?: Record < string , ( options : FilterContext [ 'options' ] , args : any ) => any >
65+ selectors ?: Record < string , Selector < any , any > >
6366
6467 /**
6568 * By default `setOptions` and `reset` are assigned.
6669 * NOTE: `reset` will set the value to null, this may not be desired!
6770 */
68- actions ?: Record < string , ( options : FilterContext [ 'options' ] , payload : any ) => void >
71+ actions ?: Record < string , Action < any > >
6972}
7073
7174export type FilterFactory = {
7275 key : string
7376 actions : Record <
7477 string ,
75- < T > ( payload : T ) => (
78+ < P > ( payload : P ) => (
7679 view : string ,
7780 getContext : FilterViewContextState [ 'getContextByKey' ]
7881 ) => {
79- payload : T
82+ payload : P
8083 type : string
8184 }
8285 >
@@ -96,58 +99,52 @@ export type FilterFactory = {
9699 * Unlike the name suggests, this function returns a filter factory.
97100 */
98101export const createFilter = ( options : FilterOptions ) : FilterFactory => {
99- const opt_selectors = options . selectors ?? { }
100- const opt_actions = options . actions ?? { }
102+ const opt_selectors : NonNullable < FilterOptions [ 'selectors' ] > = Object . assign ( options . selectors ?? { } , {
103+ selectOptions : ( opts , _ ) => opts ,
104+ isActive : options . isActive ,
105+ } )
101106
102107 /**
103108 * Selectors are wrapped redux selectors that act on the filter's options.
104109 */
105- const selectors = mapValues (
106- {
107- ...opt_selectors ,
108- selectOptions : ( opts , _ ) => opts ,
109- isActive : options . isActive ,
110- } ,
111- ( [ key , selector ] ) => {
112- const gift = args => {
113- const wrapper = ( opts : FilterContext [ 'options' ] ) => selector ( opts , args )
114- wrapper . filter = options . key
115-
116- return wrapper
117- }
118-
119- return [ key , gift ]
110+ const selectors = mapValues ( opt_selectors , ( [ key , selector ] ) => {
111+ const gift = args => {
112+ const wrapper = ( opts : FilterContext [ 'options' ] ) => selector ( opts , args )
113+ wrapper . filter = options . key
114+
115+ return wrapper
120116 }
121- )
117+
118+ return [ key , gift ]
119+ } )
120+
121+ const opt_actions : NonNullable < FilterOptions [ 'actions' ] > = Object . assign ( options . actions ?? { } , {
122+ setOptions : ( _ , value ) => value ,
123+ reset : ( ..._ ) => null ,
124+ } )
125+
122126 /**
123127 * Actions are wrapped redux actions that act on the filter's options.
124128 *
125129 * Note that these actions cannot be dispatched using the vanilla redux
126130 * dispatch function. You need to use the dipatch function obtained form
127131 * the useFilterDispatch hook.
128132 */
129- const actions = mapValues (
130- {
131- setOptions : ( _ , value ) => value ,
132- reset : ( ..._ ) => null ,
133- ...opt_actions ,
134- } ,
135- ( [ key , action ] ) => {
136- return [
137- key ,
138- payload => ( view : string , getContext : FilterViewContextState [ 'getContextByKey' ] ) => {
139- const ctx = getContext ( options . key )
140-
141- return setFilterOptions ( {
142- view,
143- filter : options . key ,
144- action : `${ options . key } /${ key } ` ,
145- options : produce ( ctx . options , ( draft : FilterContext [ 'options' ] ) => action ( draft , payload ) ) ,
146- } )
147- } ,
148- ]
149- }
150- )
133+ const actions = mapValues ( opt_actions , ( [ key , action ] ) => {
134+ return [
135+ key ,
136+ payload => ( view : string , getContext : FilterViewContextState [ 'getContextByKey' ] ) => {
137+ const ctx = getContext ( options . key )
138+
139+ return setFilterOptions ( {
140+ view,
141+ filter : options . key ,
142+ action : `${ options . key } /${ key } ` ,
143+ options : produce ( ctx . options , ( draft : FilterContext [ 'options' ] ) => action ( draft , payload ) ) ,
144+ } )
145+ } ,
146+ ]
147+ } )
151148
152149 /**
153150 * `filter`
@@ -191,7 +188,7 @@ export const createFilter = (options: FilterOptions): FilterFactory => {
191188 * The filter is evaluated over the student list only when this function returns true.
192189 * Activity of the filter is also reflected in the user interface.
193190 */
194- const factory = ( args ?: any ) : Filter => ( {
191+ const factory : FilterFactory = ( args ?: any ) : Filter => ( {
195192 args,
196193
197194 key : options . key ,
0 commit comments