UNPKG

@byloth/core

Version:

An unopinionated collection of useful functions and classes that I use widely in all my projects. 🔧

220 lines (201 loc) • 5.43 kB
import Publisher from "../callbacks/publisher.js"; import type { Callback } from "../types.js"; // eslint-disable-next-line @typescript-eslint/no-unused-vars import type MapView from "./map-view.js"; interface SetViewEventsMap<T> { "add": (value: T) => void; "remove": (value: T) => void; "clear": () => void; } /** * A wrapper class around the native {@link Set} class that provides additional functionality * for publishing events when entries are added, removed or the collection is cleared. * There's also a complementary class that works with the native `Map` class. * See also {@link MapView}. * * --- * * @example * ```ts * const set = new SetView<number>(); * * set.onAdd((value: number) => console.log(`Added ${value}`)); * set.add(42); // "Added 42" * ``` * * --- * * @template T The type of the values in the set. */ export default class SetView<T> extends Set<T> { /** * The internal {@link Publisher} instance used to publish events. */ protected readonly _publisher: Publisher<SetViewEventsMap<T>>; /** * Initializes a new instance of the {@link SetView} class. * * --- * * @example * ```ts * const set = new SetView<number>([2, 4, 8]); * ``` * * --- * * @param iterable An optional iterable of values to initialize the {@link Set} with. */ public constructor(iterable?: Iterable<T> | null) { super(); this._publisher = new Publisher(); if (iterable) { for (const value of iterable) { this.add(value); } } } /** * Appends a new element with a specified value to the end of the {@link Set}. * If the value already exists, it will not be added again. * * --- * * @example * ```ts * const set = new SetView<number>(); * set.add(2) * .add(4) * .add(8); * * console.log(set); // SetView(4) { 2, 4, 8 } * ``` * * --- * * @param value The value to add. * * @returns The current instance of the {@link SetView} class. */ public override add(value: T): this { super.add(value); this._publisher.publish("add", value); return this; } /** * Removes the specified value from the {@link Set}. * * --- * * @example * ```ts * const set = new SetView<number>([2, 4, 8]); * set.delete(4); // true * set.delete(16); // false * * console.log(set); // SetView(2) { 2, 8 } * ``` * * --- * * @param value The value to remove. * * @returns `true` if the entry existed and has been removed; otherwise `false` if the entry doesn't exist. */ public override delete(value: T): boolean { const result = super.delete(value); if (result) { this._publisher.publish("remove", value); } return result; } /** * Removes all entries from the {@link Set}. * * --- * * @example * ```ts * const set = new SetView<number>([2, 4, 8]); * set.clear(); * * console.log(set); // SetView(0) { } * ``` */ public override clear(): void { const size = this.size; super.clear(); if (size > 0) { this._publisher.publish("clear"); } } /** * Subscribes to the `add` event of the set with a callback that will be executed when a value is added. * * --- * * @example * ```ts * set.onAdd((value) => console.log(`Added ${value}`)); * * set.add(2); // "Added 2" * set.add(42); // "Added 42" * ``` * * --- * * @param callback The callback that will be executed when a value is added to the set. * * @returns A function that can be used to unsubscribe from the event. */ public onAdd(callback: (value: T) => void): Callback { return this._publisher.subscribe("add", callback); } /** * Subscribes to the `remove` event of the set with a callback that will be executed when a value is removed. * * --- * * @example * ```ts * set.onRemove((value) => console.log(`Removed ${value}`)); * * set.delete(2); // "Removed 2" * set.delete(42); // "Removed 42" * ``` * * --- * * @param callback The callback that will be executed when a value is removed from the set. * * @returns A function that can be used to unsubscribe from the event. */ public onRemove(callback: (value: T) => void): Callback { return this._publisher.subscribe("remove", callback); } /** * Subscribes to the `clear` event of the set with a callback that will be executed when the set is cleared. * * --- * * @example * ```ts * set.onClear(() => console.log("The set has all been cleared.")); * set.clear(); // "The set has all been cleared." * ``` * * --- * * @param callback The callback that will be executed when the set is cleared. * * @returns A function that can be used to unsubscribe from the event. */ public onClear(callback: () => void): Callback { return this._publisher.subscribe("clear", callback); } public override readonly [Symbol.toStringTag]: string = "SetView"; }