Untitled
unknown
plain_text
2 years ago
4.5 kB
28
Indexable
interface Item {
id: string;
index: number;
isRoot?: boolean;
level: number; // Track the depth for rendering
children: Item[];
}
class TreeNode {
data: Item;
children: TreeNode[];
constructor(data: Item) {
this.data = data;
this.children = [];
// Initialize level at the TreeNode for rendering purposes
this.data.level = this.data.level ?? 0;
}
addChild(child: TreeNode): void {
child.data.level = this.data.level + 1; // Increment child level based on parent
this.children.push(child);
}
}
class Forest {
roots: TreeNode[];
constructor() {
this.roots = [];
}
addNode(newNodeData: Item, parentId: string | null): void {
const newNode = new TreeNode(newNodeData);
if (parentId === null) {
this.roots.push(newNode);
} else {
let parentFound = false;
for (const root of this.roots) {
const parent = this.findNode(root, parentId);
if (parent) {
parent.addChild(newNode);
parentFound = true;
break;
}
}
if (!parentFound) {
throw new Error(`Parent with id ${parentId} not found.`);
}
}
}
findNode(current: TreeNode | null, id: string): TreeNode | null {
if (!current) return null;
if (current.data.id === id) {
return current;
}
for (const child of current.children) {
const result = this.findNode(child, id);
if (result) {
return result;
}
}
return null;
}
flatten(): Item[] {
return this.roots.flatMap(root => flat(root));
}
}
function flat(node: TreeNode | null): Item[] {
let result: Item[] = [];
if (node) {
result.push(node.data);
node.children.forEach(child => {
result = result.concat(flat(child));
});
}
return result;
}
// Initialize the forest and add nodes
const forest = new Forest();
forest.addNode({ id: "item1", index: 0, isRoot: true, children: [], level: 0 }, null);
forest.addNode({ id: "item1child1", index: 1, children: [], level: 1 }, "item1");
forest.addNode({ id: "item1child2", index: 2, children: [], level: 1 }, "item1");
forest.addNode({ id: "item2", index: 3, isRoot: true, children: [], level: 0 }, null);
forest.addNode({ id: "item2child1", index: 4, children: [], level: 1 }, "item2");
forest.addNode({ id: "item2child2", index: 5, children: [], level: 1 }, "item2");
forest.addNode({ id: "item2child2child1", index: 6, children: [], level: 2 }, "item2child2");
forest.addNode({ id: "item2child1child1", index: 7, children: [], level: 2 }, "item2child1");
forest.addNode({ id: "item2child1child1child1", index: 8, children: [], level: 3 }, "item2child1child1");
// Flatten the forest for rendering
let items = forest.flatten();
const { DetailsList, Selection, SelectionMode, CheckboxVisibility } = window.FluentUIReact;
let defaultRenderFn;
const getColumns = (level: number) => {
return [
{
key: "id",
minWidth: 20,
name: "ID",
onRender: (item: Item) => <span style={{paddingLeft: `${20 * item.level}px`}}>{item.id}</span>
}
];
};
const RowWithChildren = (props: any) => {
return defaultRenderFn({
...props,
itemIndex: props.item.index,
key: props.item.id,
columns: getColumns(props.item.level),
styles: { root: { paddingLeft: `${20 * props.item.level}px` } },
});
};
const onRenderRow = (props: any, defaultRender: any) => {
defaultRenderFn = defaultRender;
return <RowWithChildren {...props} item={props.item} level={props.item.level} />;
};
const Content = () => {
const [count, setCount] = React.useState(0);
const selection = new Selection({
onSelectionChanged: () => {
setCount(selection.getSelection().length);
},
getKey: (item: Item) => item.id
});
const styles = {
root: {
selectors: {
".ms-List-cell:empty": {
display: "none"
}
}
},
};
return (
<div>
<span>{count} rows selected</span>
<DetailsList
items={items}
columns={getColumns(0)}
onRenderRow={onRenderRow}
selection={selection}
selectionMode={SelectionMode.multiple}
selectionPreservedOnEmptyClick={true}
checkboxVisibility={CheckboxVisibility.always}
styles={styles}
/>
</div>
);
};
ReactDOM.render(<Content />, document.getElementById("content"));
Editor is loading...
Leave a Comment