Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/vscode-tree-item/vscode-tree-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ export class VscodeTreeItem extends VscElement {
hasBranchItem: false,
rootElement: null,
activeItem: null,
highlightedItems: [],
};

@consume({context: configContext, subscribe: true})
Expand Down Expand Up @@ -335,9 +334,16 @@ export class VscodeTreeItem extends VscElement {
if (isShiftDown && this._configContext.multiSelect) {
this._selectRange();
this._treeContextState.emitSelectEvent?.();

this.updateComplete.then(() => {
this._treeContextState.highlightIndentGuides?.();
});
} else {
this._selectItem(isCtrlDown);
this._treeContextState.emitSelectEvent?.();
this.updateComplete.then(() => {
this._treeContextState.highlightIndentGuides?.();
});

if (this._configContext.expandMode === ExpandMode.singleClick) {
if (this.branch && !(this._configContext.multiSelect && isCtrlDown)) {
Expand All @@ -351,10 +357,6 @@ export class VscodeTreeItem extends VscElement {
if (!isShiftDown) {
this._treeContextState.prevFocusedItem = this;
}

this.updateComplete.then(() => {
this._treeContextState.highlightGuides?.();
});
}

private _handleDoubleClick(ev: MouseEvent) {
Expand Down
127 changes: 122 additions & 5 deletions src/vscode-tree/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {expect, fixture, html} from '@open-wc/testing';
import {findLastChildItem, findPrevItem} from './helpers';
import {findLastChildItem, findNextItem, findPrevItem} from './helpers';
import {VscodeTreeItem} from '../vscode-tree-item';
import '../vscode-tree-item/vscode-tree-item.js';
import {VscodeTree} from './vscode-tree';
Expand Down Expand Up @@ -66,7 +66,7 @@ describe('vscode-tree helpers', () => {
expect(findPrevItem(item2)).to.eq(item1);
});

it('returns last children of the opened branch', async () => {
it('returns last child of the opened branch', async () => {
const el = await fixture<VscodeTree>(html`
<vscode-tree>
<vscode-tree-item id="item1" open>
Expand Down Expand Up @@ -114,16 +114,133 @@ describe('vscode-tree helpers', () => {
<vscode-tree-item id="item1" open>
1
<vscode-tree-item>1.1</vscode-tree-item>
<vscode-tree-item id="item1_2">1.2</vscode-tree-item>
<vscode-tree-item>1.2</vscode-tree-item>
<vscode-tree-item open>
1.3
<vscode-tree-item>1.3.1</vscode-tree-item>
<vscode-tree-item>1.3.2</vscode-tree-item>
<vscode-tree-item id="item1_3_3">1.3.3</vscode-tree-item>
</vscode-tree-item>
</vscode-tree-item>
<vscode-tree-item>2</vscode-tree-item>
</vscode-tree>
`);

const item1 = el.querySelector<VscodeTreeItem>('#item1')!;
const item1_2 = el.querySelector<VscodeTreeItem>('#item1_2')!;
const item1_3_3 = el.querySelector<VscodeTreeItem>('#item1_3_3')!;

expect(findLastChildItem(item1)).to.eq(item1_3_3);
});

it('does not traverse the closed branches', async () => {
const el = await fixture(html`
<vscode-tree>
<vscode-tree-item id="item1" open>
1
<vscode-tree-item>1.1</vscode-tree-item>
<vscode-tree-item>1.2</vscode-tree-item>
<vscode-tree-item id="item1_3">
1.3
<vscode-tree-item>1.3.1</vscode-tree-item>
<vscode-tree-item>1.3.2</vscode-tree-item>
<vscode-tree-item>1.3.3</vscode-tree-item>
</vscode-tree-item>
</vscode-tree-item>
<vscode-tree-item>2</vscode-tree-item>
</vscode-tree>
`);

const item1 = el.querySelector<VscodeTreeItem>('#item1')!;
const item1_3 = el.querySelector<VscodeTreeItem>('#item1_3')!;

expect(findLastChildItem(item1)).to.eq(item1_3);
});

it('returns the passed item if it is not a tree-item', async () => {
const el = await fixture(html`<div></div>`);

expect(findLastChildItem(el as VscodeTreeItem)).to.eq(el);
});

it('returns the passed item if it does not have a child', async () => {
await fixture(
html` <vscode-tree>
<vscode-tree-item id="leaf">leaf</vscode-tree-item>
</vscode-tree>`
);

const item = document.getElementById('leaf')! as VscodeTreeItem;

expect(findLastChildItem(item)).to.eq(item);
});
});

describe('findNextItem()', () => {
it('returns null if does not have parent element', () => {
const el = document.createElement('vscode-tree-item');

expect(findNextItem(el)).to.be.null;
});

it('returns null if it is not a tree item', async () => {
const el = await fixture(
html`<vscode-tree><div id="item"></div></vscode-tree>`
);

expect(findNextItem(el.querySelector('#item') as VscodeTreeItem)).to.be
.null;
});

it('returns last children of the opened branch', async () => {
const el = await fixture<VscodeTree>(html`
<vscode-tree>
<vscode-tree-item id="item1" open>
1
<vscode-tree-item id="item1_1">1.1</vscode-tree-item>
<vscode-tree-item>1.2</vscode-tree-item>
</vscode-tree-item>
<vscode-tree-item>2</vscode-tree-item>
</vscode-tree>
`);

const item1 = el.querySelector<VscodeTreeItem>('#item1')!;
const item1_1 = el.querySelector<VscodeTreeItem>('#item1_1')!;

expect(findNextItem(item1)).to.eq(item1_1);
});

it('returns the next sibling if the opened branch does not contain any item', async () => {
const el = await fixture<VscodeTree>(html`
<vscode-tree>
<vscode-tree-item id="item1" open>1</vscode-tree-item>
<vscode-tree-item id="item2">2</vscode-tree-item>
</vscode-tree>
`);

const item1 = el.querySelector<VscodeTreeItem>('#item1')!;
const item2 = el.querySelector<VscodeTreeItem>('#item2')!;

expect(findNextItem(item1)).to.eq(item2);
});

it('returns the next ancestor', async () => {
const el = await fixture<VscodeTree>(html`
<vscode-tree>
<vscode-tree-item open>
1
<vscode-tree-item>
1.1
<vscode-tree-item id="item1_1_1"> 1.1.1 </vscode-tree-item>
</vscode-tree-item>
</vscode-tree-item>
<vscode-tree-item id="item2">2</vscode-tree-item>
</vscode-tree>
`);

const item1_1_1 = el.querySelector<VscodeTreeItem>('#item1_1_1')!;
const item2 = el.querySelector<VscodeTreeItem>('#item2')!;

expect(findLastChildItem(item1)).to.eq(item1_2);
expect(findNextItem(item1_1_1)).to.eq(item2);
});
});
});
4 changes: 2 additions & 2 deletions src/vscode-tree/tree-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export interface TreeContext {
hasBranchItem: boolean;
rootElement: VscodeTree | null;
activeItem: VscodeTreeItem | null;
highlightedItems: VscodeTreeItem[];
highlightGuides?: () => void;
highlightedItems?: Set<VscodeTreeItem>;
highlightIndentGuides?: () => void;
emitSelectEvent?: () => void;
}

Expand Down
67 changes: 31 additions & 36 deletions src/vscode-tree/vscode-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ export class VscodeTree extends VscElement {
prevFocusedItem: null,
hasBranchItem: false,
rootElement: this,
highlightedItems: [],
highlightGuides: () => {
this._highlightGuides();
highlightedItems: new Set(),
highlightIndentGuides: () => {
this._highlightIndentGuides();
},
emitSelectEvent: () => {
this._emitSelectEvent();
Expand Down Expand Up @@ -258,43 +258,37 @@ export class VscodeTree extends VscElement {
this.dispatchEvent(ev);
}

private _highlightGuides() {
const {activeItem, highlightedItems, selectedItems} =
this._treeContextState;
private _highlightIndentGuideOfItem(item: VscodeTreeItem) {
if (item.branch && item.open) {
item.highlightedGuides = true;
this._treeContextState.highlightedItems?.add(item);
} else {
const parent = findParentItem(item);

highlightedItems.forEach((i) => (i.highlightedGuides = false));
if (parent) {
parent.highlightedGuides = true;
this._treeContextState.highlightedItems?.add(parent);
}
}
}

if (activeItem) {
this._treeContextState.highlightedItems = [];
private _highlightIndentGuides() {
if (this.indentGuides === IndentGuides.none) {
return;
}

if (activeItem.branch && activeItem.open) {
activeItem.highlightedGuides = true;
this._treeContextState.highlightedItems.push(activeItem);
} else {
const parent = findParentItem(activeItem);
this._treeContextState.highlightedItems?.forEach(
(i) => (i.highlightedGuides = false)
);
this._treeContextState.highlightedItems?.clear();

if (parent && parent.branch) {
parent.highlightedGuides = true;
this._treeContextState.highlightedItems.push(parent);
}
}
if (this._treeContextState.activeItem) {
this._highlightIndentGuideOfItem(this._treeContextState.activeItem);
}

if (selectedItems) {
selectedItems.forEach((item) => {
if (item.branch && item.open) {
item.highlightedGuides = true;
this._treeContextState.highlightedItems.push(item);
} else {
const parent = findParentItem(item);

if (parent && parent.branch) {
parent.highlightedGuides = true;
this._treeContextState.highlightedItems.push(item);
}
}
});
}
this._treeContextState.selectedItems.forEach((item) => {
this._highlightIndentGuideOfItem(item);
});
}

private _updateConfigContext(changedProperties: PropertyValues) {
Expand Down Expand Up @@ -326,6 +320,7 @@ export class VscodeTree extends VscElement {

item.updateComplete.then(() => {
item.focus();
this._highlightIndentGuides();
});
}

Expand Down Expand Up @@ -430,6 +425,8 @@ export class VscodeTree extends VscElement {
this._treeContextState.selectedItems.forEach(
(li) => (li.selected = false)
);
this._treeContextState.selectedItems.clear();
this._highlightIndentGuides();

focusedItem.selected = true;
this._emitSelectEvent();
Expand Down Expand Up @@ -496,8 +493,6 @@ export class VscodeTree extends VscElement {
firstChild.active = true;
}
}

this._highlightGuides();
});
};

Expand Down