UNPKG

@e280/quay

Version:

File-browser and outliner UI for the web

95 lines (79 loc) 2.56 kB
import {signal} from "@benev/slate" import {Codex} from "../codex.js" import {Id, Kind, Schema} from "./types.js" /** * Codex Item * - Quay's concept of a nestable thing. * - ergonomic handle which consolidates taxonomy, clade, and hierarchy functionality. */ export class CodexItem<Sc extends Schema = any, K extends Kind<Sc> = Kind<Sc>> { signal = signal(this) constructor( private codex: Codex<Sc>, public id: Id, ) {} get kind(): K { return this.codex.clade.query<K>(this.id).kind } isKind<K2 extends Kind<Sc>>(kind: K2): this is CodexItem<Sc, K2> { return (kind as any === this.kind) } /** get information about the type of entity */ get taxon(): Sc["taxon"] { return this.codex.clade.query(this.id).taxon } /** get information about this specific entity */ get specimen(): Sc["specimens"][K] { return this.codex.clade.query<K>(this.id).specimen } /** get this item's parent item, or undefined if it's not attached */ get parent(): CodexItem<Sc> | undefined { const parent = this.codex.hierarchy.getParent(this.id) return parent ? this.codex.require(parent) as CodexItem<Sc> : undefined } /** get an array of this item's children */ get children(): CodexItem<Sc>[] { // TODO actually replace this with a children() iterator, could be a perf win for supermassive sets return [...this.codex.hierarchy.getChildren(this.id)] .map(id => this.codex.require(id)) } /** add items as children */ attach(...items: CodexItem<Sc>[]) { this.codex.hierarchy.attach(this.id, ...items.map(i => i.id)) this.signal.publish() return this } /** detach this item from the hierarchy completely */ detach() { this.codex.hierarchy.detach(this.id) this.signal.publish() } /** create a new item that will be a child */ create<K extends keyof Sc["specimens"]>(kind: K, specimen: Sc["specimens"][K]) { const item = this.codex.create(kind, specimen) this.attach(item) return item } /** create a new item that will be a child */ destroy() { this.codex.hierarchy.destroy(this.id) this.signal.publish() } /** iterate over this item and all its descendants */ *crawl(predicate: (item: CodexItem<Sc>, path: CodexItem<Sc>[]) => boolean = () => true) { const iterator = this.codex.hierarchy.crawl( this.id, (id, path) => predicate( this.codex.require(id), path.map(id => this.codex.require(id)), ) ) for (const [id, path] of iterator) yield [ this.codex.require(id), path.map(id => this.codex.require(id)), ] as [CodexItem<Sc>, CodexItem<Sc>[]] } }