import type { DId } from '../../utils/types';
export type TreeNodeStatus = 'INDETERMINATE' | 'CHECKED' | 'UNCHECKED';
export const [INDETERMINATE, CHECKED, UNCHECKED] = ['INDETERMINATE', 'CHECKED', 'UNCHECKED'] as TreeNodeStatus[];
export interface TreeOrigin {
disabled?: boolean;
children?: TreeOrigin[];
}
export abstract class AbstractTreeNode<ID extends DId, T extends TreeOrigin> {
private _parent: AbstractTreeNode<ID, T> | null = null;
constructor(public origin: T) {}
get parent(): AbstractTreeNode<ID, T> | null {
return this._parent;
}
get root(): AbstractTreeNode<ID, T> {
let node: AbstractTreeNode<ID, T> = this;
while (node.parent) {
node = node.parent;
}
return node;
}
get isLeaf(): boolean {
return !this.children;
}
get id(): ID {
return this._id;
}
get status(): TreeNodeStatus {
return this._status;
}
get checked(): boolean {
return this._status === CHECKED;
}
get unchecked(): boolean {
return this._status === UNCHECKED;
}
get indeterminate(): boolean {
return this._status === INDETERMINATE;
}
get disabled(): boolean {
return this._disabled;
}
get enabled(): boolean {
return !this._disabled;
}
updateStatus(checked: ID | null | Set<ID>, onlySelf = false): void {
if (this.children && !onlySelf) {
this.children.forEach((child) => {
child.updateStatus(checked, onlySelf);
});
}
this._calculateStatus(checked);
}
protected _setParent(parent: AbstractTreeNode<ID, T>): void {
this._parent = parent;
}
protected _updateAncestors(checked: ID | null | Set<ID>, onlySelf: boolean) {
if (this._parent && !onlySelf) {
this._parent.updateStatus(checked, onlySelf);
}
}
abstract children?: AbstractTreeNode<ID, T>[];
protected abstract _id: ID;
protected abstract _status: TreeNodeStatus;
protected abstract _disabled: boolean;
protected abstract _calculateStatus(checked: ID | null | Set<ID>): void;
}