blob: f45026f5ab374d7336d4bbad879a5551a90de963 [file] [log] [blame]
/**
* @module modules/corpus-selector-sk
* @description <h2><code>corpus-selector-sk</code></h2>
*
* An element that allows the user to select a corpus from a list of available corpora.
*
* Events:
*
* corpus-selected: Emitted when the user selects a corpus. The event details contains the
* selected corpus.
*/
import { html } from 'lit/html.js';
import { define } from '../../../elements-sk/modules/define';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
/**
* Takes a corpus object and returns a string used to represent the corpus on the CorpusSelectorSk
* element's UI.
*/
export type CorpusRendererFn<T extends Object> = (corpus: T) => string;
/**
* An element that allows the user to select a corpus from a list of available corpora.
*
* Corpora are objects of the generic type T, and are transformed to text to be displayed in the UI
* using T#toString(). This behavior can be overridden by providing a custom CorpusRendererFn<T>
* via the customRendererFn property.
*/
export class CorpusSelectorSk<T extends Object> extends ElementSk {
private static template = <T extends Object>(el: CorpusSelectorSk<T>) =>
el._corpora.length
? html` <ul>
${el._corpora.map((corpus) =>
CorpusSelectorSk.corpusTemplate(el, corpus)
)}
</ul>`
: html`<p>Loading corpora details...</p>`;
private static corpusTemplate = <T extends Object>(
el: CorpusSelectorSk<T>,
corpus: T
) =>
html` <li
class=${el._selectedCorpus === corpus ? 'selected' : ''}
title="${el._corpusRendererFn(corpus)}"
@click=${() => el._handleCorpusClick(corpus)}>
${el._corpusRendererFn(corpus)}
</li>`;
private _corpora: T[] = [];
// Default to the corpus object's toString() method.
private _corpusRendererFn: CorpusRendererFn<T> = (corpus) =>
corpus.toString();
private _selectedCorpus: T | null = null;
constructor() {
super(CorpusSelectorSk.template);
}
connectedCallback() {
super.connectedCallback();
this._render();
}
/** The corpora available for the user to select from. */
get corpora() {
return this._corpora;
}
set corpora(value) {
this._corpora = value;
this._render();
}
/** A function that takes a corpus and returns the text to display on the UI. */
get corpusRendererFn() {
return this._corpusRendererFn;
}
set corpusRendererFn(fn) {
this._corpusRendererFn = fn;
this._render();
}
/** The currently selected corpus. */
get selectedCorpus() {
return this._selectedCorpus;
}
set selectedCorpus(corpus) {
this._selectedCorpus = corpus;
this._render();
}
private _handleCorpusClick(corpus: T) {
if (this.selectedCorpus !== corpus) {
this.selectedCorpus = corpus;
this._sendCorpusSelected();
}
}
private _sendCorpusSelected() {
this.dispatchEvent(
new CustomEvent<T>('corpus-selected', {
detail: this._selectedCorpus!,
bubbles: true,
})
);
}
}
define('corpus-selector-sk', CorpusSelectorSk);