Skip to content

Commit

Permalink
🌞
Browse files Browse the repository at this point in the history
  • Loading branch information
jpzwarte committed Dec 30, 2024
1 parent 9e937cd commit 22f2880
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 9 deletions.
4 changes: 3 additions & 1 deletion packages/components/tree/src/tree-node.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
align-items: center;
background: var(--sl-elevation-surface-raised-default-idle);
border-radius: var(--sl-size-borderRadius-default);
color: var(--sl-color-text-plain);
cursor: pointer;
display: flex;
gap: var(--sl-size-075);
Expand All @@ -21,8 +22,9 @@
--_guide-color: transparent;
}

:host([aria-selected='true']) {
:host([selected]) {
background: var(--sl-color-background-selected-subtle-idle);
color: var(--sl-color-text-selected);
}

:host(:focus-visible) {
Expand Down
28 changes: 23 additions & 5 deletions packages/components/tree/src/tree-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type ScopedElementsMap, ScopedElementsMixin } from '@open-wc/scoped-ele
import { Checkbox } from '@sl-design-system/checkbox';
import { Icon } from '@sl-design-system/icon';
import { type EventEmitter, EventsController, event } from '@sl-design-system/shared';
import { type SlChangeEvent, type SlToggleEvent } from '@sl-design-system/shared/events.js';
import { type SlChangeEvent, type SlSelectEvent, type SlToggleEvent } from '@sl-design-system/shared/events.js';
import { type CSSResultGroup, LitElement, type PropertyValues, type TemplateResult, html, nothing } from 'lit';
import { property } from 'lit/decorators.js';
import { IndentGuides } from './indent-guides.js';
Expand All @@ -14,7 +14,8 @@ declare global {
}
}

export class TreeNode extends ScopedElementsMixin(LitElement) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class TreeNode<T = any> extends ScopedElementsMixin(LitElement) {
/** @internal */
static override styles: CSSResultGroup = styles;

Expand All @@ -36,6 +37,9 @@ export class TreeNode extends ScopedElementsMixin(LitElement) {
/** Determines whether the checkbox is checked or not. */
@property({ type: Boolean }) checked?: boolean;

/** The node data. */
@property({ attribute: false }) data?: T;

/** Whether the node is disabled. */
@property({ type: Boolean, reflect: true }) disabled?: boolean;

Expand All @@ -57,6 +61,9 @@ export class TreeNode extends ScopedElementsMixin(LitElement) {
/** The depth level of this node, 0 being the root of the tree. */
@property({ type: Number, reflect: true }) level = 0;

/** @internal Emits when the user clicks a the wrapper part of the tree node. */
@event({ name: 'sl-select' }) selectEvent!: EventEmitter<SlSelectEvent<T>>;

/** Whether the node is currently selected. */
@property({ type: Boolean }) selected?: boolean;

Expand All @@ -76,7 +83,7 @@ export class TreeNode extends ScopedElementsMixin(LitElement) {
override updated(changes: PropertyValues<this>): void {
super.updated(changes);

if (changes.has('selects')) {
if (changes.has('checked') || changes.has('indeterminate') || changes.has('selected') || changes.has('selects')) {
if (this.selects === 'multiple') {
this.setAttribute('aria-checked', this.checked ? 'true' : this.indeterminate ? 'mixed' : 'false');
} else {
Expand Down Expand Up @@ -136,8 +143,19 @@ export class TreeNode extends ScopedElementsMixin(LitElement) {
this.indeterminate = false;
}

#onClick(): void {
if (this.expandable) {
#onClick(event: Event): void {
const wrapper = this.renderRoot.querySelector('[part="wrapper"]');

const insideWrapper = !!event
.composedPath()
.filter((el): el is HTMLElement => el instanceof HTMLElement)
.find(el => el === wrapper);

if (insideWrapper) {
event.preventDefault();

this.selectEvent.emit(this.data!);
} else if (this.expandable) {
this.toggle();
}
}
Expand Down
21 changes: 18 additions & 3 deletions packages/components/tree/src/tree.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { virtualize } from '@lit-labs/virtualizer/virtualize.js';
import { type ScopedElementsMap, ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';
import { Icon } from '@sl-design-system/icon';
import { RovingTabindexController, SelectionController } from '@sl-design-system/shared';
import { type SlChangeEvent } from '@sl-design-system/shared/events.js';
import { type EventEmitter, RovingTabindexController, SelectionController, event } from '@sl-design-system/shared';
import { type SlChangeEvent, type SlSelectEvent } from '@sl-design-system/shared/events.js';
import { type CSSResultGroup, LitElement, type PropertyValues, type TemplateResult, html, nothing } from 'lit';
import { property } from 'lit/decorators.js';
import { TreeModel, type TreeModelArrayItem, type TreeModelId } from './tree-model.js';
Expand Down Expand Up @@ -72,6 +72,9 @@ export class Tree<T = any> extends ScopedElementsMixin(LitElement) {
/** Custom renderer function for tree items. */
@property({ attribute: false }) renderer?: TreeItemRenderer<T>;

/** @internal Emits when the user selects a tree node. */
@event({ name: 'sl-select' }) selectEvent!: EventEmitter<SlSelectEvent<T>>;

/** Contains the selection state for the tree when `selects` is defined. */
readonly selection = new SelectionController(this);

Expand Down Expand Up @@ -119,7 +122,7 @@ export class Tree<T = any> extends ScopedElementsMixin(LitElement) {
setTimeout(() => this.#rovingTabindexController.clearElementCache(), 100);

return html`
<div part="wrapper">
<div @sl-select=${this.#onSelect} part="wrapper">
${virtualize({
items,
keyFunction: (item: TreeModelArrayItem<T>) => this.model?.getId(item.dataNode),
Expand All @@ -134,6 +137,8 @@ export class Tree<T = any> extends ScopedElementsMixin(LitElement) {
icon = this.model!.getIcon(dataNode, expanded),
selected = this.selection.isSelected(this.model!.getId(dataNode));

console.log('renderItem', dataNode, selected);

return html`
<sl-tree-node
@sl-change=${(event: SlChangeEvent<boolean>) => this.#onChange(event, dataNode)}
Expand All @@ -144,6 +149,7 @@ export class Tree<T = any> extends ScopedElementsMixin(LitElement) {
?hide-guides=${this.hideGuides}
?last-node-in-level=${lastNodeInLevel}
?selected=${selected && this.selects === 'single'}
.data=${dataNode}
.level=${level}
.selects=${this.selects}
>
Expand All @@ -161,6 +167,15 @@ export class Tree<T = any> extends ScopedElementsMixin(LitElement) {
console.log('event', event, event.detail, item);
}

#onSelect(event: SlSelectEvent<T>): void {
event.preventDefault();
event.stopPropagation();

console.log('select', this.model!.getId(event.detail));

this.selection.select(this.model!.getId(event.detail));
}

#onToggle(item: T): void {
this.model?.toggle(this.model?.getId(item));
}
Expand Down

0 comments on commit 22f2880

Please sign in to comment.