Skip to content

Commit

Permalink
Node sorter
Browse files Browse the repository at this point in the history
  • Loading branch information
jameskerr committed Mar 28, 2024
1 parent 8ba482f commit f717e78
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 25 deletions.
29 changes: 29 additions & 0 deletions modules/react-arborist/src/nodes/default-accessors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { SourceDataAccessors } from "./source-data-accessor";

export function createDefaultAccessors<T>(): SourceDataAccessors<T> {
return {
id: (d: T) => {
if (d && typeof d === "object" && "id" in d) {
return d.id as string;
} else {
throw new Error("No id found for node data. Specify an id accessor.");
}
},
children: (d: T) => {
if (d && typeof d === "object" && "children" in d) {
return d.children as T[];
} else {
return null;
}
},
isLeaf: (d: T) => {
if (d && typeof d === "object" && "children" in d) {
return false;
} else {
return true;
}
},
sortBy: (_d: T) => 0,
sortOrder: "asc",
};
}
51 changes: 30 additions & 21 deletions modules/react-arborist/src/nodes/source-data-accessor.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,46 @@
import { createDefaultAccessors } from "./default-accessors";

export type SourceDataAccessors<T> = {
id: (d: T) => string;
children: (d: T) => T[];
children: (d: T) => T[] | null;
isLeaf: (d: T) => boolean;
sortBy: (d: T) => number | string | boolean;
sortOrder: "asc" | "desc";
};

export class SourceDataAccessor<T> {
constructor(public accessors: Partial<SourceDataAccessors<T>> = {}) {}
access: SourceDataAccessors<T>;

constructor(accessors: Partial<SourceDataAccessors<T>> = {}) {
this.access = { ...createDefaultAccessors(), ...accessors };
}

getId(d: T): string {
if (this.accessors.id) {
return this.accessors.id(d);
} else if (d && typeof d === "object" && "id" in d) {
return d.id as string;
} else {
throw new Error("No id found for node data. Specify an id accessor.");
}
return this.access.id(d);
}

getChildren(d: T): null | T[] {
if (this.accessors.children) {
return this.accessors.children(d);
} else if (d && typeof d === "object" && "children" in d) {
return d.children as T[];
} else {
return null;
}
return this.access.children(d);
}

getIsLeaf(d: T): boolean {
if (this.accessors.isLeaf) {
return this.accessors.isLeaf(d);
} else {
return !this.getChildren(d);
}
return this.access.isLeaf(d);
}

sort(array: T[]) {
return array.sort((a, b) => {
const first = this.access.sortBy(a);
const second = this.access.sortBy(b);

if (this.asc) {
return first < second ? -1 : 1;
} else {
return first > second ? -1 : 1;
}
});
}

get asc() {
return this.access.sortOrder === "asc";
}
}
9 changes: 7 additions & 2 deletions modules/react-arborist/src/nodes/source-data-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ export class SourceDataProxy<T> implements NodeObject<T> {
) {
this.id = this.accessor.getId(sourceData);
this.level = parent === null ? 0 : parent.level + 1;
const initChild = (d: T) => new SourceDataProxy(this, d, accessor);
this.children = this.sourceChildren?.map(initChild) || null;
if (this.sourceChildren) {
this.children = accessor
.sort(this.sourceChildren)
.map((d: T) => new SourceDataProxy(this, d, accessor));
} else {
this.children = null;
}
}

get isLeaf() {
Expand Down
4 changes: 2 additions & 2 deletions modules/react-arborist/src/nodes/tree-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export class TreeManager<T> {

constructor(
public sourceData: T[],
public accessors: Partial<SourceDataAccessors<T>>,
accessors: Partial<SourceDataAccessors<T>>,
) {
this.accessor = new SourceDataAccessor(accessors);
this.nodes = sourceData.map((data) => {
this.nodes = this.accessor.sort(sourceData).map((data) => {
return new SourceDataProxy(null, data, this.accessor);
});
}
Expand Down

0 comments on commit f717e78

Please sign in to comment.