import {
afterNextRender,
booleanAttribute,
ChangeDetectionStrategy,
Component,
computed,
DestroyRef,
ElementRef,
forwardRef,
inject,
input,
signal,
ViewEncapsulation,
} from "@angular/core";
import { SdSelect } from "./sd-select";
import { SdCheckbox } from "../checkbox/sd-checkbox";
import { SdGap } from "../gap/sd-gap";
@Component({
selector: "sd-select-item",
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
standalone: true,
imports: [SdCheckbox, SdGap],
template: `
@if (_parentControl.selectMode() === "multi") {
}
`,
styles: [
/* language=SCSS */ `
@use "../../../scss/commons/mixins";
sd-select-item {
display: block;
padding: var(--gap-sm) var(--gap-default);
cursor: pointer;
transition: background 0.1s ease-in;
background: var(--control-color);
&:hover {
transition: background 0.1s ease-out;
background: rgba(0, 0, 0, 0.07);
}
&:focus {
outline: none;
transition: background 0.1s ease-out;
background: rgba(0, 0, 0, 0.07);
}
&[data-sd-selected="true"] {
color: var(--theme-primary-default);
font-weight: bold;
background: rgba(0, 0, 0, 0.07);
}
&[data-sd-disabled="true"] {
background: var(--theme-gray-default);
opacity: 0.3;
cursor: default;
pointer-events: none;
}
&[data-sd-hidden="true"] {
display: none;
}
}
`,
],
host: {
"[attr.tabindex]": "'0'",
"[attr.data-sd-select-mode]": "_parentControl.selectMode()",
"[attr.data-sd-selected]": "isSelected()",
"[attr.data-sd-disabled]": "disabled()",
"[attr.data-sd-hidden]": "hidden()",
"(click)": "onClick($event)",
"(keydown)": "onKeydown($event)",
},
})
export class SdSelectItem {
protected readonly _parentControl = inject>(
forwardRef(() => SdSelect),
);
private readonly _elRef = inject(ElementRef);
private readonly _destroyRef = inject(DestroyRef);
value = input(undefined);
disabled = input(false, { transform: booleanAttribute });
hidden = input(false, { transform: booleanAttribute });
contentHTML = signal("");
isSelected = computed(() => {
const parentValue = this._parentControl.value();
const itemValue = this.value();
if (this._parentControl.selectMode() === "multi") {
const arr = parentValue as T[] | undefined;
return arr != null && arr.includes(itemValue as T);
}
return parentValue === itemValue;
});
constructor() {
afterNextRender(() => {
const contentEl = this._elRef.nativeElement.querySelector("._content");
if (contentEl == null) return;
this.contentHTML.set(contentEl.innerHTML);
const observer = new MutationObserver(() => {
this.contentHTML.set(contentEl.innerHTML);
});
observer.observe(contentEl, { childList: true, characterData: true, subtree: true });
this._destroyRef.onDestroy(() => observer.disconnect());
});
}
onClick(event: MouseEvent): void {
event.preventDefault();
event.stopPropagation();
if (this.disabled()) return;
this._parentControl.selectItem(this.value());
}
onKeydown(event: KeyboardEvent): void {
if (event.key === " ") {
event.preventDefault();
event.stopPropagation();
if (this.disabled()) return;
// Space always toggles without closing
this._parentControl.toggleItem(this.value());
}
if (event.key === "Enter") {
event.preventDefault();
event.stopPropagation();
if (this.disabled()) return;
if (this._parentControl.selectMode() === "single") {
this._parentControl.selectItem(this.value());
} else {
this._parentControl.toggleItem(this.value());
}
}
}
}