first commit
This commit is contained in:
29
xterminal/source/base/debouncer.ts
Normal file
29
xterminal/source/base/debouncer.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { isFunction } from "../helpers";
|
||||
|
||||
/**
|
||||
* Debouncing functions
|
||||
*
|
||||
* https://www.freecodecamp.org/news/javascript-debounce-example
|
||||
*
|
||||
* https://programmingwithmosh.com/javascript/javascript/throttle-and-debounce-patterns/
|
||||
*/
|
||||
|
||||
const DEBOUNCE_TIME = 0;
|
||||
|
||||
export function bounce(fn: TimerHandler, ...args: unknown[]): number {
|
||||
return setTimeout(fn, DEBOUNCE_TIME, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delay the execution of the function until a pause happens
|
||||
* @param fn The function to execute
|
||||
* @returns A function that limits the intermediate calls to `fn`
|
||||
*/
|
||||
export function debounce(fn: TimerHandler) {
|
||||
let flag: number;
|
||||
return (...args: unknown[]) => {
|
||||
if (!isFunction(fn)) return;
|
||||
clearTimeout(flag);
|
||||
flag = bounce(fn, ...args);
|
||||
};
|
||||
}
|
||||
42
xterminal/source/base/disposable.ts
Normal file
42
xterminal/source/base/disposable.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { IDisposable } from "../types";
|
||||
|
||||
/**
|
||||
* Disposables
|
||||
*
|
||||
* https://blog.hediet.de/post/the_disposable_pattern_in_typescript
|
||||
*
|
||||
* https://github.com/xtermjs/xterm.js/blob/master/src/common/Lifecycle.ts
|
||||
*/
|
||||
|
||||
export default class Disposable implements IDisposable {
|
||||
// private store for states
|
||||
#disposables: IDisposable[];
|
||||
|
||||
public isDisposed: boolean;
|
||||
|
||||
constructor() {
|
||||
this.isDisposed = false;
|
||||
this.#disposables = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a disposable object
|
||||
* @param d The disposable to register
|
||||
*/
|
||||
public register<T extends IDisposable>(d: T): void {
|
||||
if (this.isDisposed) {
|
||||
d?.dispose();
|
||||
} else {
|
||||
this.#disposables.push(d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the object, triggering the `dispose` method on all registered disposables
|
||||
*/
|
||||
public dispose(): void {
|
||||
if (this.isDisposed) return;
|
||||
this.isDisposed = true;
|
||||
this.#disposables.forEach((d) => d?.dispose());
|
||||
}
|
||||
}
|
||||
13
xterminal/source/base/error.ts
Normal file
13
xterminal/source/base/error.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export class XError extends Error {
|
||||
constructor(message: string) {
|
||||
message = "[x] " + message;
|
||||
super(message);
|
||||
this.name = "XTerminalError";
|
||||
}
|
||||
}
|
||||
|
||||
export const TARGET_INVALID_ERR =
|
||||
"mount: A parent HTMLElement (target) is required";
|
||||
|
||||
export const TARGET_NOT_CONNECTED_ERR =
|
||||
"'mount' was called on an HTMLElement (target) that is not attached to DOM.";
|
||||
70
xterminal/source/base/reactivity.ts
Normal file
70
xterminal/source/base/reactivity.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { isFunction } from "../helpers";
|
||||
import type { IDisposable } from "../types";
|
||||
|
||||
/**
|
||||
* Reactivity
|
||||
* => https://github.com/henryhale/reactivity
|
||||
*/
|
||||
|
||||
/**
|
||||
* Effect - callback triggered when a reactive value changes
|
||||
*/
|
||||
export type IEffect = () => void;
|
||||
|
||||
/**
|
||||
* Reactive value -> all effects are disposable
|
||||
*/
|
||||
export interface IReactive<T> extends IDisposable {
|
||||
value: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Global observer
|
||||
*/
|
||||
let observer: IEffect | null;
|
||||
|
||||
/**
|
||||
* Function that creates a disposable reactive object from a primitive value
|
||||
* @param value The primitive value (initial)
|
||||
* @returns Reactive object
|
||||
*/
|
||||
export function ref<T>(value: T): IReactive<T> {
|
||||
const observers = new Set<IEffect>();
|
||||
let disposed = false;
|
||||
return {
|
||||
get value() {
|
||||
// allow subscriptons only when the object is not disposed
|
||||
if (!disposed && isFunction(observer)) {
|
||||
observers.add(observer);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
set value(newValue) {
|
||||
value = newValue;
|
||||
// alert subscribers only when the object is not disposed
|
||||
if (!disposed) {
|
||||
observers.forEach((o) => o.call(undefined));
|
||||
}
|
||||
},
|
||||
dispose() {
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
// remove all subscriptions
|
||||
observers.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that opens a subscription to reactive values
|
||||
* @param fn The subscription (function) to be made
|
||||
*/
|
||||
export function createEffect(fn: IEffect): void {
|
||||
if (!isFunction(fn)) return;
|
||||
observer = fn;
|
||||
try {
|
||||
fn.call(undefined);
|
||||
} finally {
|
||||
observer = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user