yamultiselect = (data, options = {}) => {
const { width, locale, disabled, label, placeholder } = Object.assign(
{
width: 240,
disabled: false,
placeholder: "Search…"
},
options
);
const keyof = options.keyof ? options.keyof : isMap(data) ? first : identity;
const valueof = options.valueof
? options.valueof
: isMap(data)
? second
: identity;
const keys = getKeys(data, keyof);
const values = getValues(data, valueof);
const initialIndices = Array.isArray(options.value)
? indicesFromValues(options.value)
: [];
let selectedIndices = new Set(initialIndices);
const id = newId();
const datalistId = `${id}-datalist`;
const inputEl = html`<input id="${id}"
class="${blockClass}__input"
type="text"
list="${datalistId}"
placeholder=${placeholder}
disabled=${disabled}
/>`;
const selectionEl = html`<ul class="${blockClass}__selected-items" region="status"></ul>`;
const labelEl = label ? html`<label for="${id}">${label}</label>` : "";
const datalistEl = html`<datalist id=${datalistId}></datalist>`;
const form = html`<form class="${ns} ${blockClass}" style=${cssPropWidth(
width
)} disabled=${disabled}>
${labelEl}
<div class="${blockClass}__wrapper">
${selectionEl}
${inputEl}
${datalistEl}
</div>
</form>`;
function dispatchInputEvent() {
form.dispatchEvent(new Event("input", { bubbles: true }));
}
function indicesFromValues(value) {
let indices = [];
value.forEach((v) => {
const index = values.indexOf(v);
if (index >= 0) {
indices.push(index);
}
});
return indices;
}
function oninput(event) {
preventDefault(event);
const pickedKey = event.target?.value;
if (pickedKey) {
const iOfIndex = keys.indexOf(pickedKey);
if (iOfIndex >= 0) {
inputEl.value = "";
selectedIndices.add(iOfIndex);
updateUI();
dispatchInputEvent();
}
}
}
function removeIndex(index) {
const result = selectedIndices.delete(index);
if (result) {
updateUI();
dispatchInputEvent();
}
}
function updateOptions() {
datalistEl.innerHTML = null;
const options = dataList(keys, selectedIndices);
options.forEach((option) => datalistEl.append(option));
}
function updateSelectedPills() {
selectionEl.innerHTML = null;
let items = [];
for (let i of selectedIndices) {
const k = keys[i];
items.push(html`<li class="${blockClass}__selected-item">
<span class="${blockClass}__selected-item-label">${k}</span>
<button class="${blockClass}__remove"
type="button"
title="Remove"
onclick=${() => removeIndex(i)}
disabled=${disabled}>
<span class="${blockClass}__icon">${icons.close()}</span>
</button>
</li>`);
}
items.forEach((el) => selectionEl.append(el));
}
function updateUI() {
updateOptions();
updateSelectedPills();
}
function generateValues() {
let items = [];
for (let i of selectedIndices) {
items.push(values[i]);
}
return items;
}
form.onchange = preventDefault;
form.oninput = oninput;
form.onsubmit = preventDefault;
attachStyles(invalidation);
updateUI();
return Object.defineProperty(form, "value", {
get() {
return selectedIndices.size ? generateValues() : [];
},
set(value) {
if (Array.isArray(value)) {
const indices = indicesFromValues(value);
selectedIndices = new Set(indices);
updateUI();
dispatchInputEvent();
}
}
});
}