// retoor <retoor@molodetz.nl>
import { Component } from "./Component.js";
import { assetUrl } from "../assetVersion.js";
const CSS_ID = "ai-choice-multi-css";
export class AiChoiceMulti extends Component {
static get observedAttributes() {
return ["name", "label", "help", "required", "disabled", "min-selected", "max-selected"];
}
constructor() {
super();
this._values = new Set();
}
_ensureCss() {
if (document.getElementById(CSS_ID)) return;
const link = document.createElement("link");
link.id = CSS_ID;
link.rel = "stylesheet";
link.href = assetUrl("/static/css/components/ai-choice.css");
document.head.appendChild(link);
}
connectedCallback() {
this._ensureCss();
if (this._built) return;
this._built = true;
this.classList.add("ai-choice-multi");
const name = this.attr("name", "choices");
const label = this.attr("label", "Choices");
const options = [...this.querySelectorAll("ai-option")].map((el) => ({
value: el.getAttribute("value") || "",
label: el.getAttribute("label") || el.textContent || "",
description: el.getAttribute("description") || "",
disabled: el.hasAttribute("disabled"),
selected: el.hasAttribute("selected"),
}));
this.innerHTML = "";
const title = document.createElement("div");
title.className = "ai-widget-label";
title.textContent = label;
this.appendChild(title);
if (this.attr("help")) {
const help = document.createElement("div");
help.className = "ai-widget-help";
help.textContent = this.attr("help");
this.appendChild(help);
}
const group = document.createElement("div");
group.className = "ai-choice-options multi";
for (const option of options) {
const labelEl = document.createElement("label");
labelEl.className = "ai-choice-check";
const input = document.createElement("input");
input.type = "checkbox";
input.value = option.value;
input.disabled = option.disabled;
if (option.selected) {
input.checked = true;
this._values.add(option.value);
}
input.addEventListener("change", () => {
if (input.checked) this._values.add(option.value);
else this._values.delete(option.value);
this.dispatchEvent(
new CustomEvent("ai:change", {
bubbles: true,
composed: true,
detail: { name, value: this.getValue() },
})
);
});
const span = document.createElement("span");
span.textContent = option.label;
labelEl.append(input, span);
if (option.description) {
const desc = document.createElement("small");
desc.textContent = option.description;
labelEl.appendChild(desc);
}
group.appendChild(labelEl);
}
this.appendChild(group);
}
getValue() {
return [...this._values];
}
validate() {
const min = this.intAttr("min-selected", this.boolAttr("required") ? 1 : 0);
const max = this.intAttr("max-selected", 0);
const count = this._values.size;
if (count < min) {
return { valid: false, message: `${this.attr("label", "Choices")}: select at least ${min}` };
}
if (max > 0 && count > max) {
return { valid: false, message: `${this.attr("label", "Choices")}: select at most ${max}` };
}
return { valid: true };
}
}
if (!customElements.get("ai-choice-multi")) {
customElements.define("ai-choice-multi", AiChoiceMulti);
}
export default AiChoiceMulti;