Skip to content

Instantly share code, notes, and snippets.

@danwbyrne
Created September 29, 2018 19:53
Show Gist options
  • Save danwbyrne/8632f03370e6bde74d6ba56a7d9fe30c to your computer and use it in GitHub Desktop.
Save danwbyrne/8632f03370e6bde74d6ba56a7d9fe30c to your computer and use it in GitHub Desktop.
import { merge, Observable, Observer } from 'rxjs';
import { distinctUntilChanged, filter, scan } from 'rxjs/internal/operators';
import { map } from 'rxjs/operators';
import { unless } from '../shared/operators';
export interface KeyEvent {
readonly keyCode: number;
}
export const keyEventStream = (
targetKeys: number[],
blur$: Observable<any>,
keyDown$: Observable<KeyEvent>,
keyUp$: Observable<KeyEvent>,
isDisabled$: Observable<boolean>,
): Observable<number[]> =>
new Observable((observer: Observer<number[]>) => {
const onlyTargetKeys = filter((event: KeyEvent) =>
targetKeys.includes(event.keyCode),
);
const calculateNewKeyCombo = scan(
(
currentKeyCombo: Set<number>,
): Set<number> => currentKeyCombo,
);
const keyComboStream = (currentKeyCombo: Set<number>): Observable<number[]> => merge(
keyDown$.pipe(
unless(isDisabled$),
onlyTargetKeys,
map((event) => currentKeyCombo.add(event.keyCode)),
),
keyUp$.pipe(
unless(isDisabled$),
onlyTargetKeys,
map((event) => currentKeyCombo.delete(event.keyCode)),
),
blur$.pipe(
map(() => currentKeyCombo.clear()),
),
).pipe(
calculateNewKeyCombo,
distinctUntilChanged(),
map((newKeyCombo: Set<number>) => [...newKeyCombo]),
);
return keyComboStream(new Set<number>()).subscribe(observer);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment