@@ -15,21 +15,29 @@ type EventAsReturnType<Payload> = any extends Payload ? Event<Payload> : never;
15
15
export function throttle < T > ( _ : {
16
16
source : Unit < T > ;
17
17
timeout : number | Store < number > ;
18
+ leading ?: boolean | Store < boolean > ;
19
+ trailing ?: boolean | Store < boolean > ;
18
20
name ?: string ;
19
21
} ) : EventAsReturnType < T > ;
20
22
export function throttle < T , Target extends Unit < T > > ( _ : {
21
23
source : Unit < T > ;
22
24
timeout : number | Store < number > ;
23
25
target : Target ;
26
+ leading ?: boolean | Store < boolean > ;
27
+ trailing ?: boolean | Store < boolean > ;
24
28
name ?: string ;
25
29
} ) : Target ;
26
30
export function throttle < T > ( {
27
31
source,
28
32
timeout,
33
+ leading,
34
+ trailing,
29
35
target = createEvent < T > ( ) ,
30
36
} : {
31
37
source : Unit < T > ;
32
38
timeout : number | Store < number > ;
39
+ leading ?: boolean | Store < boolean > ;
40
+ trailing ?: boolean | Store < boolean > ;
33
41
name ?: string ;
34
42
target ?: Unit < any > ;
35
43
} ) : EventAsReturnType < T > {
@@ -42,13 +50,18 @@ export function throttle<T>({
42
50
) ;
43
51
44
52
// It's ok - nothing will ever start unless source is triggered
45
- const $payload = createStore < T > ( null as unknown as T , { serialize : 'ignore' } ) . on (
46
- source ,
47
- ( _ , payload ) => payload ,
48
- ) ;
53
+ const $payload = createStore < T > ( null as unknown as T , {
54
+ serialize : 'ignore' ,
55
+ } ) . on ( source , ( _ , payload ) => payload ) ;
49
56
50
57
const triggerTick = createEvent < T > ( ) ;
51
58
59
+ const $leading = toStoreBoolean ( leading , '$leading' , false ) ;
60
+ const $trailing = toStoreBoolean ( trailing , '$trailing' , true ) ;
61
+
62
+ const $neverCalled = createStore ( true ) . on ( target , ( ) => false ) ;
63
+ const $lastCalled = createStore < number > ( 0 ) . on ( target , ( ) => Date . now ( ) ) ;
64
+
52
65
const $canTick = createStore ( true , { serialize : 'ignore' } )
53
66
. on ( triggerTick , ( ) => false )
54
67
. on ( target , ( ) => true ) ;
@@ -66,8 +79,25 @@ export function throttle<T>({
66
79
} ) ;
67
80
68
81
sample ( {
69
- source : $payload ,
82
+ clock : $payload ,
83
+ source : [ $leading , $neverCalled ] ,
84
+ filter : ( [ leading , neverCalled ] ) => leading && neverCalled ,
85
+ target,
86
+ } ) ;
87
+
88
+ sample ( {
89
+ source : [ $trailing , $payload ] as const ,
70
90
clock : timerFx . done ,
91
+ filter : ( [ trailing ] ) => trailing ,
92
+ fn : ( [ _ , payload ] ) => payload ,
93
+ target,
94
+ } ) ;
95
+ sample ( {
96
+ clock : $payload ,
97
+ source : { trailing : $trailing , lastCalled : $lastCalled , timeout : $timeout } ,
98
+ filter : ( { trailing, lastCalled, timeout } ) =>
99
+ ! trailing && lastCalled + timeout < Date . now ( ) ,
100
+ fn : ( _src , clk ) => clk ,
71
101
target,
72
102
} ) ;
73
103
@@ -88,3 +118,16 @@ function toStoreNumber(value: number | Store<number> | unknown): Store<number> {
88
118
`timeout parameter should be number or Store. "${ typeof value } " was passed` ,
89
119
) ;
90
120
}
121
+
122
+ function toStoreBoolean (
123
+ value : boolean | Store < boolean > | undefined ,
124
+ name : string ,
125
+ defaultValue : boolean ,
126
+ ) : Store < boolean > {
127
+ if ( is . store ( value ) ) return value ;
128
+ if ( typeof value === 'boolean' ) {
129
+ return createStore ( value , { name } ) ;
130
+ } else {
131
+ return createStore ( defaultValue , { name } ) ;
132
+ }
133
+ }
0 commit comments