@tdb/util
Version:
Shared helpers and utilities.
91 lines (80 loc) • 2.54 kB
text/typescript
/**
* Global events subscribed to only once and consumed as [Observable] event producers.
*/
import { MouseEvent } from 'react';
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 * as constants from '../../constants';
const { IS_BROWSER } = constants;
const fromEvent = <T>(
source: FromEventTarget<any> | undefined,
event: string,
): Observable<T> => {
return source
? rxFromEvent(source, event).pipe(share())
: new Subject<any>().pipe(share()); // Safe when server-rendered.
};
const fromDocumentEvent = <T>(event: string): Observable<T> =>
fromEvent(IS_BROWSER ? document : undefined, event);
const fromWindowEvent = <T>(event: string): Observable<T> =>
fromEvent(IS_BROWSER ? window : undefined, event);
export const click$ = fromDocumentEvent<MouseEvent<any>>('click');
export const mouseDown$ = fromDocumentEvent<MouseEvent<any>>('mousedown');
export const mouseUp$ = fromDocumentEvent<MouseEvent<any>>('mouseup');
export const mouseMove$ = fromDocumentEvent<MouseEvent<any>>('mousemove');
export const hashChange$ = fromWindowEvent<HashChangeEvent>('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<KeypressEvent>;
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<KeyboardEvent>('keydown').pipe(
map(e => toKeypress(e, true)),
share(),
);
export const keyUp$ = fromDocumentEvent<KeyboardEvent>('keyup').pipe(
map(e => toKeypress(e, false)),
share(),
);
export const keyPress$ = keyDown$.pipe(merge(keyUp$)) as KepressObservable;