blob: e7f608910cffd2f8d4d9f5967a3926c954ce39b2 [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 { define } from 'elements-sk/define';
import { html } from 'lit-html';
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 overriden by providing a custom CorpusRendererFn<T> via
* the customRendererFn property.
*/
export class CorpusSelectorSk<T extends Object> extends ElementSk {
private static template =
<T>(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>(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);