blob: b4529025c3147d0362638811cdc779d8d6b36512 [file] [log] [blame]
/**
* @module modules/query-values-sk
* @description <h2><code>query-values-sk</code></h2>
*
* The right-hand side of the query-sk element, the values for a single key
* in a query/paramset.
*
* @evt query-values-changed - Triggered only when the selections have actually
* changed. The selection is available in e.detail.
*
* @attr {boolean} hide_invert - If the option to invert a query should be made available to
* the user.
* @attr {boolean} hide_regex - If the option to include regex in the query should be made
* available to the user.
*/
import { define } from 'elements-sk/define';
import { html } from 'lit-html';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { CheckOrRadio } from 'elements-sk/checkbox-sk/checkbox-sk';
import {
MultiSelectSk,
MultiSelectSkSelectionChangedEventDetail,
} from 'elements-sk/multi-select-sk/multi-select-sk';
import 'elements-sk/checkbox-sk';
import 'elements-sk/multi-select-sk';
export interface QueryValuesSkQueryValuesChangedEventDetail {
invert: boolean;
regex: boolean;
values: string[];
}
export class QueryValuesSk extends ElementSk {
private static template = (ele: QueryValuesSk) => html`
<checkbox-sk
id="invert"
@change=${ele._invertChange}
title="Match items not selected below."
label="Invert"
?hidden=${ele.hide_invert}
></checkbox-sk>
<checkbox-sk
id="regex"
@change=${ele._regexChange}
title="Match items via regular expression."
label="Regex"
?hidden=${ele.hide_regex}
></checkbox-sk>
<input
type="text"
id="regexValue"
class="hidden"
@input=${ele._regexInputChange}
/>
<multi-select-sk id="values" @selection-changed=${ele._selectionChange}>
${QueryValuesSk.valuesTemplate(ele)}
</multi-select-sk>
`;
private static valuesTemplate = (ele: QueryValuesSk) => {
return ele._options.map(
(v) => html`
<div value=${v} ?selected=${ele._selected.indexOf(v) !== -1}>${v}</div>
`
);
};
private _options: string[] = [];
private _selected: string[] = [];
private _invert: CheckOrRadio | null = null;
private _regex: CheckOrRadio | null = null;
private _regexValue: HTMLInputElement | null = null;
private _values: MultiSelectSk | null = null;
constructor() {
super(QueryValuesSk.template);
}
connectedCallback() {
super.connectedCallback();
this._render();
this._invert = this.querySelector('#invert');
this._regex = this.querySelector('#regex');
this._values = this.querySelector('#values');
this._regexValue = this.querySelector('#regexValue');
this._upgradeProperty('options');
this._upgradeProperty('selected');
this._upgradeProperty('hide_invert');
this._upgradeProperty('hide_regex');
}
private _invertChange() {
if (this._regex!.checked) {
this._regex!.checked = false;
}
this._render();
this._fireEvent();
}
private _regexChange() {
if (this._invert!.checked) {
this._invert!.checked = false;
}
this._render();
this._fireEvent();
}
private _regexInputChange() {
this._fireEvent();
}
private _selectionChange(
e: CustomEvent<MultiSelectSkSelectionChangedEventDetail>
) {
this._selected = e.detail.selection.map((i) => this._options[i]);
this._render();
this._fireEvent();
}
private _fireEvent() {
const prefix = this._invert!.checked ? '!' : '';
let selected = this._values!.selection.map(
(i) => prefix + this._options[i]
);
if (this._regex!.checked) {
selected = [`~${this._regexValue!.value}`];
}
this.dispatchEvent(
new CustomEvent<QueryValuesSkQueryValuesChangedEventDetail>(
'query-values-changed',
{
detail: {
invert: this._invert!.checked,
regex: this._regex!.checked,
values: selected,
},
bubbles: true,
}
)
);
}
/** Mirrors the hide_invert attribute. */
get hide_invert() {
return this.hasAttribute('hide_invert');
}
set hide_invert(val) {
if (val) {
this.setAttribute('hide_invert', '');
} else {
this.removeAttribute('hide_invert');
}
this._render();
}
/** Mirrors the hide_regex attribute. */
get hide_regex() {
return this.hasAttribute('hide_regex');
}
set hide_regex(val) {
if (val) {
this.setAttribute('hide_regex', '');
} else {
this.removeAttribute('hide_regex');
}
this._render();
}
/** The available options. */
get options() {
return this._options;
}
set options(val) {
this._options = val;
this._selected = [];
this._render();
}
/** Current selections. */
get selected() {
return this._selected;
}
set selected(val) {
this._selected = val;
this._invert!.checked = !!(
this._selected.length >= 1 && this._selected[0][0] === '!'
);
this._regex!.checked = !!(
this._selected.length === 1 && this._selected[0][0] === '~'
);
this._cleanSelected();
if (this._selected!.length && this._regex!.checked) {
this._regexValue!.value = this._selected[0];
}
this._render();
}
private _cleanSelected() {
// Remove prefixes from _selected.
this._selected = this._selected.map((val) => {
if ('~!'.includes(val[0])) {
return val.slice(1);
} else {
return val;
}
});
}
static get observedAttributes() {
return ['hide_invert', 'hide_regex'];
}
attributeChangedCallback() {
this._render();
}
}
define('query-values-sk', QueryValuesSk);