@@ -28,16 +28,19 @@ export interface EventHandlerOptions {
2828 preventDefault : boolean ;
2929}
3030
31- /**
32- * A config that specifies how to handle a particular event.
33- */
31+ /** A basic event handler. */
32+ export type EventHandler < T extends Event > = ( event : T ) => void ;
33+
34+ /** A function that determines whether an event is to be handled. */
35+ export type EventMatcher < T extends Event > = ( event : T ) => boolean ;
36+
37+ /** A config that specifies how to handle a particular event. */
3438export interface EventHandlerConfig < T extends Event > extends EventHandlerOptions {
35- handler : ( event : T ) => boolean | void ;
39+ matcher : EventMatcher < T > ;
40+ handler : EventHandler < T > ;
3641}
3742
38- /**
39- * Bit flag representation of the possible modifier keys that can be present on an event.
40- */
43+ /** Bit flag representation of the possible modifier keys that can be present on an event. */
4144export enum ModifierKey {
4245 None = 0 ,
4346 Ctrl = 0b1 ,
@@ -46,134 +49,40 @@ export enum ModifierKey {
4649 Meta = 0b1000 ,
4750}
4851
52+ export type ModifierInputs = ModifierKey | ModifierKey [ ] ;
53+
4954/**
5055 * Abstract base class for all event managers.
5156 *
5257 * Event managers are designed to normalize how event handlers are authored and create a safety net
5358 * for common event handling gotchas like remembering to call preventDefault or stopPropagation.
5459 */
5560export abstract class EventManager < T extends Event > {
56- private _submanagers : EventManager < T > [ ] = [ ] ;
57-
5861 protected configs : EventHandlerConfig < T > [ ] = [ ] ;
59- protected beforeFns : ( ( event : T ) => void ) [ ] = [ ] ;
60- protected afterFns : ( ( event : T ) => void ) [ ] = [ ] ;
62+ abstract options : EventHandlerOptions ;
6163
62- protected defaultHandlerOptions : EventHandlerOptions = {
63- preventDefault : false ,
64- stopPropagation : false ,
65- } ;
64+ /** Runs the handlers that match with the given event. */
65+ handle ( event : T ) : void {
66+ for ( const config of this . configs ) {
67+ if ( config . matcher ( event ) ) {
68+ config . handler ( event ) ;
6669
67- constructor ( defaultHandlerOptions ?: Partial < EventHandlerOptions > ) {
68- this . defaultHandlerOptions = {
69- ...this . defaultHandlerOptions ,
70- ...defaultHandlerOptions ,
71- } ;
72- }
73-
74- /**
75- * Composes together multiple event managers into a single event manager that delegates to the
76- * individual managers.
77- */
78- static compose < T extends Event > ( ...managers : EventManager < T > [ ] ) {
79- const composedManager = new GenericEventManager < T > ( ) ;
80- composedManager . _submanagers = managers ;
81- return composedManager ;
82- }
70+ if ( config . preventDefault ) {
71+ event . preventDefault ( ) ;
72+ }
8373
84- /**
85- * Runs any handlers that have been configured to handle this event. If multiple handlers are
86- * configured for this event, they are run in the order they were configured. Returns
87- * `true` if the event has been handled, otherwise returns `undefined`.
88- *
89- * Note: the use of `undefined` instead of `false` in the unhandled case is necessary to avoid
90- * accidentally preventing the default behavior on an unhandled event.
91- */
92- handle ( event : T ) : true | undefined {
93- if ( ! this . isHandled ( event ) ) {
94- return undefined ;
95- }
96- for ( const fn of this . beforeFns ) {
97- fn ( event ) ;
98- }
99- for ( const submanager of this . _submanagers ) {
100- submanager . handle ( event ) ;
101- }
102- for ( const config of this . getHandlersForKey ( event ) ) {
103- config . handler ( event ) ;
104- if ( config . stopPropagation ) {
105- event . stopPropagation ( ) ;
74+ if ( config . stopPropagation ) {
75+ event . stopPropagation ( ) ;
76+ }
10677 }
107- if ( config . preventDefault ) {
108- event . preventDefault ( ) ;
109- }
110- }
111- for ( const fn of this . afterFns ) {
112- fn ( event ) ;
11378 }
114- return true ;
11579 }
11680
117- /**
118- * Configures the event manager to run a function immediately before it as about to handle
119- * any event.
120- */
121- beforeHandling ( fn : ( event : T ) => void ) : this {
122- this . beforeFns . push ( fn ) ;
123- return this ;
124- }
125-
126- /**
127- * Configures the event manager to run a function immediately after it handles any event.
128- */
129- afterHandling ( fn : ( event : T ) => void ) : this {
130- this . afterFns . push ( fn ) ;
131- return this ;
132- }
133-
134- /**
135- * Configures the event manager to handle specific events. (See subclasses for more).
136- */
81+ /** Configures the event manager to handle specific events. (See subclasses for more). */
13782 abstract on ( ...args : [ ...unknown [ ] ] ) : this;
138-
139- /**
140- * Gets all of the handler configs that are applicable to the given event.
141- */
142- protected abstract getHandlersForKey ( event : T ) : EventHandlerConfig < T > [ ] ;
143-
144- /**
145- * Checks whether this event manager is confugred to handle the given event.
146- */
147- protected isHandled ( event : T ) : boolean {
148- return (
149- this . getHandlersForKey ( event ) . length > 0 || this . _submanagers . some ( sm => sm . isHandled ( event ) )
150- ) ;
151- }
152- }
153-
154- /**
155- * A generic event manager that can work with any type of event.
156- */
157- export class GenericEventManager < T extends Event > extends EventManager < T > {
158- /**
159- * Configures this event manager to handle all events with the given handler.
160- */
161- on ( handler : ( event : T ) => boolean | void ) : this {
162- this . configs . push ( {
163- ...this . defaultHandlerOptions ,
164- handler,
165- } ) ;
166- return this ;
167- }
168-
169- getHandlersForKey ( _event : T ) : EventHandlerConfig < T > [ ] {
170- return this . configs ;
171- }
17283}
17384
174- /**
175- * Gets bit flag representation of the modifier keys present on the given event.
176- */
85+ /** Gets bit flag representation of the modifier keys present on the given event. */
17786export function getModifiers ( event : EventWithModifiers ) : number {
17887 return (
17988 ( + event . ctrlKey && ModifierKey . Ctrl ) |
@@ -187,7 +96,7 @@ export function getModifiers(event: EventWithModifiers): number {
18796 * Checks if the given event has modifiers that are an exact match for any of the given modifier
18897 * flag combinations.
18998 */
190- export function hasModifiers ( event : EventWithModifiers , modifiers : number | number [ ] ) : boolean {
99+ export function hasModifiers ( event : EventWithModifiers , modifiers : ModifierInputs ) : boolean {
191100 const eventModifiers = getModifiers ( event ) ;
192101 const modifiersList = Array . isArray ( modifiers ) ? modifiers : [ modifiers ] ;
193102 return modifiersList . some ( modifiers => eventModifiers === modifiers ) ;
0 commit comments