A collection of reactive wrappers for various browser APIs.
npm install subscribable-things!logo
A collection of reactive wrappers for various browser APIs.

This package provides factory functions which can be used to turn browser APIs into subscribable things. A subscribable thing can either be consumed directly with callback functions or by utilzing one of the popular libraries for reactive programming.
The subscribable-things package is published on npm and can be installed as usual.
``shell`
npm install subscribable-things
It exports individual functions for each wrapped browser API which are described in greater detail below. They can either be used directly by providing a callback function ...
`js
import { mediaQueryMatch } from 'subscribable-things';
const subscribe = mediaQueryMatch('(max-width:600px)');
const unsubscribe = subscribe((isMatching) => console.log(isMatching));
unsubscribe();
`
... or by utilizing a library for reactive programming like RxJS ...
`js
import { from } from 'rxjs';
import { mediaQueryMatch } from 'subscribable-things';
const mediaQueryMatch$ = from(mediaQueryMatch('(max-width:600px)'));
const subscription = mediaQueryMatch$.subscribe((isMatching) => console.log(isMatching));
subscription.unsubscribe();
`
... or Callbags ...
`js
import fromObs from 'callbag-from-obs';
import observe from 'callbag-observe';
import { mediaQueryMatch } from 'subscribable-things';
const source = fromObs(mediaQueryMatch('(max-width:600px)'));
observe((isMatching) => console.log(isMatching))(source);
`
... or XStream ...
`js
import { mediaQueryMatch } from 'subscribable-things';
import { fromObservable } from 'xstream';
const stream = fromObservable(mediaQueryMatch('(max-width:600px)'));
const unsubscribe = stream.subscribe((isMatching) => console.log(isMatching));
unsubscribe();
`
... or Bacon.js ...
`js
import { fromESObservable } from 'baconjs';
import { mediaQueryMatch } from 'subscribable-things';
const eventStream = fromESObservable(mediaQueryMatch('(max-width:600px)'));
const unsubscribe = eventStream.onValue((isMatching) => console.log(isMatching));
unsubscribe();
`
... or Kefir.js.
`js
import { fromESObservable } from 'kefir';
import { mediaQueryMatch } from 'subscribable-things';
const stream = fromESObservable(mediaQueryMatch('(max-width:600px)'));
const subscription = stream.observe({
value(isMatching) {
console.log(isMatching);
}
});
subscription.unsubscribe();
`
It is even possible to consume subscribable-things as an async iterable by taking the little detour over RxJS and rxjs-for-await.
`js
import { eachValueFrom } from 'rxjs-for-await';
import { from } from 'rxjs';
import { mediaQueryMatch } from 'subscribable-things';
const source$ = from(mediaQueryMatch('(max-width:600px)'));
for await (const isMatching of eachValueFrom(source$)) {
console.log(isMatching);
}
`
Also it's possible to output values directly to HTML via hyperf.
`js
import h from 'hyperf';
import { mediaQueryMatch } from 'subscribable-things';
const element = h
;document.body.appendChild(element);
`$3
`ts
function animationFrame(): SubscribableThing;
`requestAnimationFrame() method. It emits the current timestamp of each animation frame.$3
`ts
function attribute(htmlElement: HTMLElement, name: string): TSubscribableThing;
`This function uses
mutations() on the inside to emit the latest value of the attribute with the given name.$3
`ts
function geolocation(options?: PositionOptions): SubscribableThing;
`This is a wrapper for the Geolocation API. It uses
watchPosition() to gather the most recent GeolocationPosition whenever it changes.$3
`ts
function intersections(
htmlElement: HTMLElement,
options?: IntersectionObserverInit
): SubscribableThing;
`IntersectionObserver.$3
`ts
function mediaDevices(): SubscribableThing;
`enumerateDevices() method of the Media Capture and Streams specification. It will also listen for the devicechange event to emit a fresh list of devices whenever they change.$3
`ts
function mediaQueryMatch(mediaQueryString: string): SubscribableThing;
`matchMedia() method. It will emit a new value whenever the result of matchMedia() changes.$3
`ts
function midiInputs(midiAccess: IMidiAccess): SubscribableThing;
`This function returns the currently available MIDI input devices. It accepts a
MIDIAccess object of the Web MIDI API.$3
`ts
function midiOutputs(midiAccess: IMidiAccess): SubscribableThing;
`This function returns the currently available MIDI output devices. It accepts a
MIDIAccess object of the Web MIDI API.$3
`ts
function metrics(options: PerformanceObserverInit): SubscribableThing;
`PerformanceObserver as defined by the Performance Timeline Level 2 specification.$3
`ts
function mutations(
htmlElement: HTMLElement,
options: MutationObserverInit
): SubscribableThing;
`MutationObserver.$3
`ts
function on(
target: EventTarget,
type: string,
options?: boolean | AddEventListenerOptions
): SubscribableThing;
`This function can be used to subscribe to events of a certain type dispatched from an
EventTarget.$3
`ts
function online(): SubscribableThing;
`onLine property of the Navigator and listens for the corresponding 'online' and 'offline' events on the Window to emit updates.$3
`ts
function permissionState(
permissionDescriptor: PermissionDescriptor
): SubscribableThing;
`query() method of the Permissions API. It will monitor the permission status to emit a new state whenever it gets updated.$3
`ts
function reports(options?: IReportingObserverOptions): SubscribableThing;
`ReportingObserver of the Reporting API.$3
`ts
function resizes(
htmlElement: HTMLElement,
options?: IResizesObserverOptions
): SubscribableThing;
`ResizeObserver of the Resize Observer specification.$3
`ts
function unhandledRejection(coolingOffPeriod: number): SubscribableThing;
`This function emits unhandled rejections. It will listen for the
unhandledrejection event to register possibly unhandled rejections. It will then wait for the cooling-off period to elapse before it emits the reason (aka the error) that caused the unhandled rejection. It is possible that a previously unhandled rejection gets handled later on in which case a rejectionhandled event will be fired. If that happens during the cooling-off period nothing will be emitted by this function.$3
`ts
function videoFrame(
videoElement: HTMLVideoElement
): SubscribableThing<{ now: number } & IVideoFrameMetadata>;
`requestVideoFrameCallback() method of the given HTMLVideoElement. It emits the current timestamp combined with the VideoFrameMetadata object.$3
`ts
function wakeLock(type: TWakeLockType): SubscribableThing;
``This function simplifies the usage of the Screen Wake Lock API. It emits true when a wake lock could be acquired and emits false once the wake lock gets released by the browser. As long as the subscription is alive it will continuosly try to get a new wake lock if the current one gets released.
There are two similar packages available which are based directly on RxJS. They are rx-use and rxjs-web.