/** * Global events subscribed to only once and consumed as [Observable] event producers. */ import * as React from 'react'; export type MouseEvent = React.MouseEvent; import { animationFrameScheduler, fromEvent as rxFromEvent, Observable, Subject, } from 'rxjs'; import { FromEventTarget } from 'rxjs/internal/observable/fromEvent'; import { map, merge, observeOn, share } from 'rxjs/operators'; import { IS_BROWSER } from '../../constants'; const fromEvent = ( source: FromEventTarget | undefined, event: string, ): Observable => { return source ? rxFromEvent(source, event).pipe(share()) : new Subject().pipe(share()); // NB: Safe when server-rendered. }; const fromDocumentEvent = (event: string): Observable => fromEvent(IS_BROWSER ? document : undefined, event); const fromWindowEvent = (event: string): Observable => fromEvent(IS_BROWSER ? window : undefined, event); export const click$ = fromDocumentEvent('click'); export const mouseDown$ = fromDocumentEvent('mousedown'); export const mouseUp$ = fromDocumentEvent('mouseup'); export const mouseMove$ = fromDocumentEvent('mousemove'); export const hashChange$ = fromWindowEvent('hashchange'); export const resize$ = fromWindowEvent<{}>('resize').pipe( observeOn(animationFrameScheduler), share(), ); /** * Keyboard events. */ export type KeypressEvent = { isPressed: boolean; char: string | null; code: string; charCode: number; key: string; altKey: boolean; ctrlKey: boolean; shiftKey: boolean; metaKey: boolean; isModifier: boolean; preventDefault: () => void; }; export type KepressObservable = Observable; const toKeypress = (e: KeyboardEvent, isPressed: boolean) => { const { key, code, charCode, altKey, ctrlKey, shiftKey, metaKey, char } = e; const isModifier = key === 'Meta' || key === 'Control' || key === 'Alt' || key === 'Shift'; const event: KeypressEvent = { isPressed, key, code, charCode, char, altKey, ctrlKey, shiftKey, metaKey, isModifier, preventDefault: () => e.preventDefault(), }; return event; }; export const keyDown$ = fromDocumentEvent('keydown').pipe( map(e => toKeypress(e, true)), share(), ); export const keyUp$ = fromDocumentEvent('keyup').pipe( map(e => toKeypress(e, false)), share(), ); export const keyPress$ = keyDown$.pipe(merge(keyUp$)) as KepressObservable;