mirror of
				https://github.com/Theodor-Springmann-Stiftung/musenalm.git
				synced 2025-10-30 01:35:32 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1498 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1498 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var tt = Object.defineProperty;
 | |
| var w = (a) => {
 | |
|   throw TypeError(a);
 | |
| };
 | |
| var et = (a, s, t) => s in a ? tt(a, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[s] = t;
 | |
| var u = (a, s, t) => et(a, typeof s != "symbol" ? s + "" : s, t), S = (a, s, t) => s.has(a) || w("Cannot " + t);
 | |
| var L = (a, s, t) => (S(a, s, "read from private field"), t ? t.call(a) : s.get(a)), _ = (a, s, t) => s.has(a) ? w("Cannot add the same private member more than once") : s instanceof WeakSet ? s.add(a) : s.set(a, t), f = (a, s, t, e) => (S(a, s, "write to private field"), e ? e.call(a, t) : s.set(a, t), t), v = (a, s, t) => (S(a, s, "access private method"), t);
 | |
| class it extends HTMLElement {
 | |
|   constructor() {
 | |
|     super(), this._value = "", this.render();
 | |
|   }
 | |
|   static get observedAttributes() {
 | |
|     return ["data-text", "data-queryparam", "data-value"];
 | |
|   }
 | |
|   set value(s) {
 | |
|     this.setAttribute("data-value", s);
 | |
|   }
 | |
|   get value() {
 | |
|     return this.getAttribute("data-value") || "";
 | |
|   }
 | |
|   set text(s) {
 | |
|     this.setAttribute("data-text", s);
 | |
|   }
 | |
|   get text() {
 | |
|     return this.getAttribute("data-text") || "";
 | |
|   }
 | |
|   set queryparam(s) {
 | |
|     this.setAttribute("data-queryparam", s);
 | |
|   }
 | |
|   get queryparam() {
 | |
|     return this.getAttribute("data-queryparam") || "";
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this._filter = this.text, this._queryparam = this.queryparam, this.render(), htmx.process(this);
 | |
|   }
 | |
|   attributeChangedCallback(s, t, e) {
 | |
|     t !== e && (s === "data-text" && (this._filter = e), s === "data-queryparam" && (this._queryparam = e), s === "data-value" && (this._value = e), this.render());
 | |
|   }
 | |
|   getURL() {
 | |
|     if (this._queryparam) {
 | |
|       let s = new URL(window.location), t = new URLSearchParams(s.search);
 | |
|       return t.delete(this._queryparam), t.delete("page"), s.search = t.toString(), s.toString();
 | |
|     }
 | |
|     return "#";
 | |
|   }
 | |
|   render() {
 | |
|     this.innerHTML = `
 | |
| 		<a href="${this.getURL()}" class="!no-underline block text-base" hx-target="#searchresults" hx-select="#searchresults" hx-indicator="body" hx-swap="outerHTML show:window:top">
 | |
| 			<div class="flex flex-row filter-pill rounded-lg bg-orange-100 hover:saturate-50 px-2.5">
 | |
| 				${this.renderIcon()}
 | |
| 				<div class="flex flex-row filter-pill-label-value !items-baseline text-slate-700">
 | |
| 					<div class="filter-pill-label font-bold mr-1.5 align-baseline">${this.text}</div>
 | |
| 					${this.renderValue()}
 | |
| 				</div>
 | |
| 			</div>
 | |
| 		</a>
 | |
| 		`;
 | |
|   }
 | |
|   renderIcon() {
 | |
|     return this.value === "true" || this.value === "false" ? `
 | |
| 			<div href="${this.getURL()}" class="filter-pill-close no-underline font-bold mr-1 text-orange-900 hover:text-orange-800">
 | |
| 				<i class="ri-close-circle-line"></i>
 | |
| 			</div>
 | |
| 		` : `<div
 | |
| 				href="${this.getURL()}"
 | |
| 				class="filter-pill-close no-underline font-bold mr-1 text-orange-900 hover:text-orange-800">
 | |
| 				<i class="ri-arrow-left-s-line"></i>
 | |
| 			</div>
 | |
| 			`;
 | |
|   }
 | |
|   renderValue() {
 | |
|     return this.value === "true" || this.value === "false" ? "" : `
 | |
| 			<div class="filter-pill-value">${this.value}</div>
 | |
| 		`;
 | |
|   }
 | |
| }
 | |
| const g = "filter-list-list", st = "filter-list-item", nt = "filter-list-input", x = "filter-list-searchable";
 | |
| var h, m, y;
 | |
| class lt extends HTMLElement {
 | |
|   constructor() {
 | |
|     super();
 | |
|     _(this, m);
 | |
|     _(this, h, !1);
 | |
|     this._items = [], this._url = "", this._filterstart = !1, this._placeholder = "Liste filtern...", this._queryparam = "", this._startparams = null, this.render();
 | |
|   }
 | |
|   static get observedAttributes() {
 | |
|     return ["data-url"];
 | |
|   }
 | |
|   set items(t) {
 | |
|     Array.isArray(t) && (this._items = t, this.render());
 | |
|   }
 | |
|   get items() {
 | |
|     return this._items;
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this._url = this.getAttribute("data-url") || "./", this._filterstart = this.getAttribute("data-filterstart") === "true", this._placeholder = this.getAttribute("data-placeholder") || "Liste filtern...", this._queryparam = this.getAttribute("data-queryparam") || "", this._queryparam, this._filterstart && f(this, h, !0), this.addEventListener("input", this.onInput.bind(this)), this.addEventListener("keydown", this.onEnter.bind(this)), this.addEventListener("focusin", this.onGainFocus.bind(this)), this.addEventListener("focusout", this.onLoseFocus.bind(this));
 | |
|   }
 | |
|   attributeChangedCallback(t, e, i) {
 | |
|     t === "data-url" && e !== i && (this._url = i, this.render()), t === "data-filterstart" && e !== i && (this._filterstart = i === "true", this.render()), t === "data-placeholder" && e !== i && (this._placeholder = i, this.render()), t === "data-queryparam" && e !== i && (this._queryparam = i, this.render());
 | |
|   }
 | |
|   onInput(t) {
 | |
|     t.target && t.target.tagName.toLowerCase() === "input" && (this._filter = t.target.value, this.renderList());
 | |
|   }
 | |
|   onGainFocus(t) {
 | |
|     t.target && t.target.tagName.toLowerCase() === "input" && (f(this, h, !1), this.renderList());
 | |
|   }
 | |
|   onLoseFocus(t) {
 | |
|     let e = this.querySelector("input");
 | |
|     if (t.target && t.target === e) {
 | |
|       if (relatedElement = t.relatedTarget, relatedElement && this.contains(relatedElement))
 | |
|         return;
 | |
|       e.value = "", this._filter = "", this._filterstart && f(this, h, !0), this.renderList();
 | |
|     }
 | |
|   }
 | |
|   onEnter(t) {
 | |
|     if (t.target && t.target.tagName.toLowerCase() === "input" && t.key === "Enter") {
 | |
|       t.preventDefault();
 | |
|       const e = this.querySelector("a");
 | |
|       e && e.click();
 | |
|     }
 | |
|   }
 | |
|   mark() {
 | |
|     if (typeof Mark != "function")
 | |
|       return;
 | |
|     let t = this.querySelector("#" + g);
 | |
|     if (!t)
 | |
|       return;
 | |
|     let e = new Mark(t.querySelectorAll("." + x));
 | |
|     this._filter && e.mark(this._filter, {
 | |
|       separateWordSearch: !0
 | |
|     });
 | |
|   }
 | |
|   // INFO: allows for setting a custom HREF of the list item
 | |
|   // The function takes the item as parameter fn(item) and should return a string.
 | |
|   setHREFFunc(t) {
 | |
|     this.getHREF = t, this.render();
 | |
|   }
 | |
|   // INFO: allows for setting a custom link text of the list item
 | |
|   // The function takes the item as parameter fn(item) and should return a string or
 | |
|   // an HTML template literal.
 | |
|   setLinkTextFunc(t) {
 | |
|     this.getLinkText = t, this.render();
 | |
|   }
 | |
|   // INFO: allows for setting the text that will be filtered for.
 | |
|   // The function takes the item as parameter fn(item) and should return a string.
 | |
|   setSearchTextFunc(t) {
 | |
|     this.getSearchText = t, this.render();
 | |
|   }
 | |
|   getHREF(t) {
 | |
|     if (t) {
 | |
|       if (!t.id)
 | |
|         return "";
 | |
|     } else return "";
 | |
|     return t.id;
 | |
|   }
 | |
|   getHREFEncoded(t) {
 | |
|     return encodeURIComponent(this.getHREF(t));
 | |
|   }
 | |
|   getSearchText(t) {
 | |
|     if (t) {
 | |
|       if (!t.name)
 | |
|         return "";
 | |
|     } else return "";
 | |
|     return t.name;
 | |
|   }
 | |
|   getLinkText(t) {
 | |
|     let e = this.getSearchText(t);
 | |
|     return e === "" ? "" : `<span class="${x}">${e}</span>`;
 | |
|   }
 | |
|   getURL(t) {
 | |
|     if (this._queryparam) {
 | |
|       let e = new URL(window.location), i = new URLSearchParams(e.search);
 | |
|       return i.set(this._queryparam, this.getHREF(t)), i.delete("page"), e.search = i.toString(), e.toString();
 | |
|     }
 | |
|     return this._url + this.getHREFEncoded(t);
 | |
|   }
 | |
|   renderList() {
 | |
|     let t = this.querySelector("#" + g);
 | |
|     t && (t.outerHTML = this.List()), this.mark();
 | |
|   }
 | |
|   render() {
 | |
|     this.innerHTML = `
 | |
|             <div class="font-serif text-base shadow-inner border border-stone-100">
 | |
| 							${this.Input()}
 | |
| 							${this.List()}
 | |
|             </div>
 | |
|         `, htmx && htmx.process(this);
 | |
|   }
 | |
|   ActiveDot(t) {
 | |
|     return v(this, m, y).call(this, t), "";
 | |
|   }
 | |
|   NoItems(t) {
 | |
|     return t.length === 0 ? '<div class="px-2 py-0.5 italic text-gray-500">Keine Einträge gefunden</div>' : "";
 | |
|   }
 | |
|   Input() {
 | |
|     return `
 | |
| 			<div class="flex w-full py-0.5 border-b border-zinc-600 bg-stone-50">
 | |
| 						<i class="ri-arrow-right-s-line pl-2"></i>
 | |
| 						<div class="grow">
 | |
| 						<input
 | |
| 								type="text"
 | |
| 								placeholder="${this._placeholder}"
 | |
| 								class="${nt} w-full placeholder:italic px-2 py-0.5" />
 | |
| 						</div>
 | |
| 				</div>
 | |
| 				`;
 | |
|   }
 | |
|   List() {
 | |
|     let t = this._items;
 | |
|     if (this._filter)
 | |
|       if (this._filterstart)
 | |
|         t = this._items.filter((e) => this.getSearchText(e).toLowerCase().startsWith(this._filter.toLowerCase()));
 | |
|       else {
 | |
|         let e = this._filter.split(" ");
 | |
|         t = this._items.filter((i) => e.every((n) => this.getSearchText(i).toLowerCase().includes(n.toLowerCase())));
 | |
|       }
 | |
|     return `
 | |
| 							<div id="${g}" class="${g} pt-1 max-h-60 overflow-auto bg-stone-50 ${L(this, h) ? "hidden" : ""}">
 | |
| 								${t.map(
 | |
|       (e, i) => `
 | |
| 									<a
 | |
| 										href="${this.getURL(e)}"
 | |
| 										hx-indicator="body"
 | |
| 										hx-swap="outerHTML show:none"
 | |
| 										hx-select="main"
 | |
| 										hx-target="main"
 | |
| 										class="${st} block px-2.5 py-0.5 hover:bg-slate-200 no-underline ${i % 2 === 0 ? "bg-stone-100" : "bg-stone-50"}"
 | |
| 										${v(this, m, y).call(this, e) ? 'aria-current="page"' : ""}>
 | |
| 										${this.ActiveDot(e)}
 | |
| 										${this.getLinkText(e)}
 | |
| 									</a>
 | |
| 								`
 | |
|     ).join("")}
 | |
| 								${this.NoItems(t)}
 | |
| 							</div>
 | |
| 				`;
 | |
|   }
 | |
| }
 | |
| h = new WeakMap(), m = new WeakSet(), y = function(t) {
 | |
|   if (!t)
 | |
|     return !1;
 | |
|   let e = this.getHREF(t);
 | |
|   return e === "" ? !1 : this._queryparam && (new URLSearchParams(window.location.search).get(this._queryparam) || "") === e ? !0 : !!window.location.href.endsWith(e);
 | |
| };
 | |
| class at extends HTMLElement {
 | |
|   constructor() {
 | |
|     super(), this.handleScroll = this.handleScroll.bind(this), this.scrollToTop = this.scrollToTop.bind(this);
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this.innerHTML = `
 | |
|           <button
 | |
|             class="
 | |
|               scroll-to-top
 | |
|               fixed bottom-5 right-5
 | |
|               hidden
 | |
|               bg-gray-800 text-white
 | |
|               p-2
 | |
|               rounded-md
 | |
|               cursor-pointer
 | |
|               text-2xl
 | |
|               hover:opacity-80
 | |
|               transition-opacity
 | |
|               border-0
 | |
|             "
 | |
|             aria-label="Scroll to top"
 | |
|           >
 | |
| 					<i class="ri-arrow-up-double-line"></i>
 | |
|           </button>
 | |
|         `, this._button = this.querySelector(".scroll-to-top"), window.addEventListener("scroll", this.handleScroll), this._button.addEventListener("click", this.scrollToTop);
 | |
|   }
 | |
|   disconnectedCallback() {
 | |
|     window.removeEventListener("scroll", this.handleScroll), this._button.removeEventListener("click", this.scrollToTop);
 | |
|   }
 | |
|   handleScroll() {
 | |
|     (window.scrollY || document.documentElement.scrollTop) > 300 ? this._button.classList.remove("hidden") : this._button.classList.add("hidden");
 | |
|   }
 | |
|   scrollToTop() {
 | |
|     window.scrollTo({ top: 0, behavior: "smooth" });
 | |
|   }
 | |
| }
 | |
| class rt extends HTMLElement {
 | |
|   static get observedAttributes() {
 | |
|     return ["position", "timeout"];
 | |
|   }
 | |
|   constructor() {
 | |
|     super(), this._tooltipBox = null, this._timeout = 200, this._hideTimeout = null, this._hiddenTimeout = null;
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this.classList.add("relative", "block", "leading-none", "[&>*]:leading-normal");
 | |
|     const s = this.querySelector(".data-tip"), t = s ? s.innerHTML : "Tooltip";
 | |
|     s && s.classList.add("hidden"), this._tooltipBox = document.createElement("div"), this._tooltipBox.innerHTML = t, this._tooltipBox.className = [
 | |
|       "opacity-0",
 | |
|       "hidden",
 | |
|       "absolute",
 | |
|       "px-2",
 | |
|       "py-1",
 | |
|       "text-sm",
 | |
|       "text-white",
 | |
|       "bg-gray-900",
 | |
|       "rounded",
 | |
|       "shadow",
 | |
|       "z-10",
 | |
|       "whitespace-nowrap",
 | |
|       "transition-all",
 | |
|       "duration-200",
 | |
|       "font-sans"
 | |
|     ].join(" "), this.appendChild(this._tooltipBox), this._updatePosition(), this.addEventListener("mouseenter", () => this._showTooltip()), this.addEventListener("mouseleave", () => this._hideTooltip());
 | |
|   }
 | |
|   attributeChangedCallback(s, t, e) {
 | |
|     s === "position" && this._tooltipBox && this._updatePosition(), s === "timeout" && e && (this._timeout = parseInt(e) || 200);
 | |
|   }
 | |
|   _showTooltip() {
 | |
|     clearTimeout(this._hideTimeout), clearTimeout(this._hiddenTimeout), this._tooltipBox.classList.remove("hidden"), setTimeout(() => {
 | |
|       this._tooltipBox.classList.remove("opacity-0"), this._tooltipBox.classList.add("opacity-100");
 | |
|     }, 16);
 | |
|   }
 | |
|   _hideTooltip() {
 | |
|     this._hideTimeout = setTimeout(() => {
 | |
|       this._tooltipBox.classList.remove("opacity-100"), this._tooltipBox.classList.add("opacity-0"), this._hiddenTimeout = setTimeout(() => {
 | |
|         this._tooltipBox.classList.add("hidden");
 | |
|       }, this._timeout + 100);
 | |
|     }, this._timeout);
 | |
|   }
 | |
|   _updatePosition() {
 | |
|     switch (this._tooltipBox.classList.remove(
 | |
|       "bottom-full",
 | |
|       "left-1/2",
 | |
|       "-translate-x-1/2",
 | |
|       "mb-2",
 | |
|       // top
 | |
|       "top-full",
 | |
|       "mt-2",
 | |
|       // bottom
 | |
|       "right-full",
 | |
|       "-translate-y-1/2",
 | |
|       "mr-2",
 | |
|       "top-1/2",
 | |
|       // left
 | |
|       "left-full",
 | |
|       "ml-2"
 | |
|       // right
 | |
|     ), this.getAttribute("position") || "top") {
 | |
|       case "bottom":
 | |
|         this._tooltipBox.classList.add(
 | |
|           "top-full",
 | |
|           "left-1/2",
 | |
|           "transform",
 | |
|           "-translate-x-1/2",
 | |
|           "mt-0.5"
 | |
|         );
 | |
|         break;
 | |
|       case "left":
 | |
|         this._tooltipBox.classList.add(
 | |
|           "right-full",
 | |
|           "top-1/2",
 | |
|           "transform",
 | |
|           "-translate-y-1/2",
 | |
|           "mr-0.5"
 | |
|         );
 | |
|         break;
 | |
|       case "right":
 | |
|         this._tooltipBox.classList.add(
 | |
|           "left-full",
 | |
|           "top-1/2",
 | |
|           "transform",
 | |
|           "-translate-y-1/2",
 | |
|           "ml-0.5"
 | |
|         );
 | |
|         break;
 | |
|       case "top":
 | |
|       default:
 | |
|         this._tooltipBox.classList.add(
 | |
|           "bottom-full",
 | |
|           "left-1/2",
 | |
|           "transform",
 | |
|           "-translate-x-1/2",
 | |
|           "mb-0.5"
 | |
|         );
 | |
|     }
 | |
|   }
 | |
| }
 | |
| class ot extends HTMLElement {
 | |
|   constructor() {
 | |
|     super(), this.overlay = null, this._others = null, this._thisindex = -1, this._preview = null, this._description = null, this._imageURL = "", this._hideDLButton = !1;
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this.classList.add("cursor-pointer"), this.classList.add("select-none"), this._imageURL = this.getAttribute("data-image-url") || "", this._hideDLButton = this.getAttribute("data-hide-dl-button") || !1, this._preview = this.querySelector("img"), this._description = this.querySelector(".image-description"), this._preview && this._preview.addEventListener("click", () => {
 | |
|       this.showOverlay();
 | |
|     });
 | |
|     let s = this.closest("image-reel, .image-reel");
 | |
|     s || (s = document), this._others = Array.from(s.querySelectorAll("popup-image:not(.hidden)")), this._thisindex = this._others.indexOf(this);
 | |
|   }
 | |
|   disconnectedCallback() {
 | |
|     this.overlay && this.overlay.parentNode && this.overlay.parentNode.removeChild(this.overlay);
 | |
|   }
 | |
|   Keys(s) {
 | |
|     s.repeat || (s.preventDefault(), s.key === "ArrowRight" ? this.next() : s.key === "ArrowLeft" ? this.prev() : s.key === "Escape" && this.hideOverlay());
 | |
|   }
 | |
|   next() {
 | |
|     this._others[this._thisindex + 1] ? (this.hideOverlay(), this._others[this._thisindex + 1].showOverlay()) : document.addEventListener("keydown", this.Keys.bind(this), { once: !0 });
 | |
|   }
 | |
|   prev() {
 | |
|     this._others[this._thisindex - 1] ? (this.hideOverlay(), this._others[this._thisindex - 1].showOverlay()) : document.addEventListener("keydown", this.Keys.bind(this), { once: !0 });
 | |
|   }
 | |
|   showOverlay() {
 | |
|     this.overlay = document.createElement("div"), this.overlay.classList.add(
 | |
|       "fixed",
 | |
|       "inset-0",
 | |
|       "z-50",
 | |
|       "bg-black/70",
 | |
|       "flex",
 | |
|       "items-center",
 | |
|       "justify-center",
 | |
|       "p-4"
 | |
|     ), this.overlay.innerHTML = `
 | |
|       <div class="relative w-max max-w-dvw max-h-dvh shadow-lg flex flex-col items-center justify-center gap-4">
 | |
| 				<div>
 | |
| 				<div class="absolute -right-16 text-white text-4xl flex flex-col">
 | |
| 					<button class="hover:text-gray-300 cursor-pointer focus:outline-none" aria-label="Close popup" id="closebutton">
 | |
| 						<i class="ri-close-fill text-4xl"></i>
 | |
| 					</button>
 | |
| 						${this.downloadButton()}
 | |
| 						${this.nextButton()}
 | |
| 						${this.prevButton()}
 | |
| 				</div>
 | |
|         <img
 | |
|           src="${this._imageURL}"
 | |
|           alt="Popup Image"
 | |
|           class="full max-h-[80vh] max-w-[80vw] object-contain block relative ${this.descriptionImgClass()}"
 | |
|         />
 | |
| 				${this.description()}
 | |
| 					</div>
 | |
|       </div>
 | |
|     `;
 | |
|     const s = this.overlay.querySelector("#closebutton");
 | |
|     s && s.addEventListener("click", () => {
 | |
|       this.hideOverlay();
 | |
|     });
 | |
|     const t = this.overlay.querySelector("#nextbtn");
 | |
|     t && t.addEventListener("click", this.next.bind(this));
 | |
|     const e = this.overlay.querySelector("#prevbtn");
 | |
|     e && e.addEventListener("click", this.prev.bind(this)), this.overlay.addEventListener("click", (i) => {
 | |
|       i.target === this.overlay && this.hideOverlay();
 | |
|     }), document.addEventListener("keydown", this.Keys.bind(this), { once: !0 }), document.body.appendChild(this.overlay);
 | |
|   }
 | |
|   descriptionImgClass() {
 | |
|     return this.description ? "" : "0";
 | |
|   }
 | |
|   nextButton() {
 | |
|     return this._others[this._thisindex + 1] ? `
 | |
| 			<tool-tip position="right">
 | |
| 			<button class="hover:text-gray-300 cursor-pointer focus:outline-none" aria-label="Next image" id="nextbtn">
 | |
| 				<i class="ri-arrow-right-box-line"></i>
 | |
| 			</button>
 | |
| 			<div class="data-tip">Nächstes Bild</div>
 | |
| 			</tool-tip>
 | |
| 		` : "";
 | |
|   }
 | |
|   prevButton() {
 | |
|     return this._others[this._thisindex - 1] ? `
 | |
| 			<tool-tip position="right">
 | |
| 			<button class="hover:text-gray-300 cursor-pointer focus:outline-none" aria-label="Previous image" id="prevbtn">
 | |
| 				<i class="ri-arrow-left-box-line"></i>
 | |
| 			</button>
 | |
| 			<div class="data-tip">Vorheriges Bild</div>
 | |
| 			</tool-tip>
 | |
| 		` : "";
 | |
|   }
 | |
|   description() {
 | |
|     return this._description ? `
 | |
|         <div class="font-serif text-left description-content mt-3 text-slate-900 ">
 | |
| 					<div class="max-w-[80ch] hyphens-auto px-6 py-2 bg-stone-50 shadow-lg">
 | |
|           ${this._description.innerHTML}
 | |
| 						</div>
 | |
|         </div>
 | |
| 			` : "";
 | |
|   }
 | |
|   downloadButton() {
 | |
|     return this._hideDLButton ? "" : `
 | |
| 					<tool-tip position="right">
 | |
| 					<a href="${this._imageURL}" target="_blank" class="text-white no-underline hover:text-gray-300"><i class="ri-file-download-line"></i></a>
 | |
| 					<div class="data-tip">Bild herunterladen</div>
 | |
| 					</tool-tip>
 | |
| 		`;
 | |
|   }
 | |
|   hideOverlay() {
 | |
|     this.overlay.parentNode.removeChild(this.overlay), this.overlay = null;
 | |
|   }
 | |
| }
 | |
| class ht extends HTMLElement {
 | |
|   static get observedAttributes() {
 | |
|   }
 | |
|   constructor() {
 | |
|     super(), this._showall = !1, this.shown = -1, this._headings = [], this._contents = [];
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this._headings = Array.from(this.querySelectorAll(".tab-list-head")), this._contents = Array.from(this.querySelectorAll(".tab-list-panel")), this.hookupEvtHandlers(), this.hideDependent(), this._headings.length === 1 && this.expand(0);
 | |
|   }
 | |
|   expand(s) {
 | |
|     s < 0 || s >= this._headings.length || (this.shown = s, this._contents.forEach((t, e) => {
 | |
|       e === s ? (t.classList.remove("hidden"), this._headings[e].setAttribute("aria-pressed", "true")) : (t.classList.add("hidden"), this._headings[e].setAttribute("aria-pressed", "false"));
 | |
|     }));
 | |
|   }
 | |
|   hookupEvtHandlers() {
 | |
|     for (let s of this._headings)
 | |
|       s.addEventListener("click", this.handleTabClick.bind(this)), s.classList.add("cursor-pointer"), s.classList.add("select-none"), s.setAttribute("role", "button"), s.setAttribute("aria-pressed", "false"), s.setAttribute("tabindex", "0");
 | |
|     for (let s of this._contents)
 | |
|       s.classList.add("hidden");
 | |
|   }
 | |
|   restore() {
 | |
|     for (let s of this._headings)
 | |
|       s.classList.add("cursor-pointer"), s.classList.add("select-none"), s.setAttribute("role", "button"), s.setAttribute("aria-pressed", "false"), s.setAttribute("tabindex", "0"), s.classList.remove("pointer-events-none"), s.classList.remove("!text-slate-900");
 | |
|     for (let s of this._contents)
 | |
|       s.classList.add("hidden");
 | |
|   }
 | |
|   disable() {
 | |
|     for (let s of this._headings)
 | |
|       s.classList.remove("cursor-pointer"), s.classList.remove("select-none"), s.removeAttribute("role"), s.removeAttribute("aria-pressed"), s.removeAttribute("tabindex"), s.classList.add("pointer-events-none"), s.classList.add("!text-slate-900");
 | |
|   }
 | |
|   showAll() {
 | |
|     this._showall = !0, this.shown = -1, this.disable(), this._contents.forEach((s, t) => {
 | |
|       s.classList.remove("hidden");
 | |
|       let e = this._headings[t], i = e.querySelectorAll(".show-opened");
 | |
|       for (let l of i)
 | |
|         l.classList.add("hidden");
 | |
|       let n = e.querySelectorAll(".show-closed");
 | |
|       for (let l of n)
 | |
|         l.classList.add("hidden");
 | |
|     });
 | |
|   }
 | |
|   default() {
 | |
|     this._showall = !1, this.restore(), this.hideDependent();
 | |
|   }
 | |
|   hideDependent() {
 | |
|     if (this.shown < 0)
 | |
|       for (const s of this._headings)
 | |
|         this._hideAllDep(s, !1);
 | |
|     else
 | |
|       this._headings.forEach((s, t) => {
 | |
|         this._hideAllDep(s, t === this.shown);
 | |
|       });
 | |
|   }
 | |
|   _hideAllDep(s, t) {
 | |
|     const e = s.querySelectorAll(".show-closed");
 | |
|     for (let n of e)
 | |
|       t ? n.classList.add("hidden") : n.classList.remove("hidden");
 | |
|     const i = Array.from(s.querySelectorAll(".show-opened"));
 | |
|     for (let n of i)
 | |
|       t ? n.classList.remove("hidden") : n.classList.add("hidden");
 | |
|   }
 | |
|   handleTabClick(s) {
 | |
|     if (!s.target) {
 | |
|       console.warn("Invalid event target");
 | |
|       return;
 | |
|     }
 | |
|     const t = this.findParentWithClass(s.target, "tab-list-head");
 | |
|     if (!t) {
 | |
|       console.warn("No parent found with class 'tab-list-head'");
 | |
|       return;
 | |
|     }
 | |
|     const e = this._headings.indexOf(t);
 | |
|     e === this.shown ? (this._contents[e].classList.toggle("hidden"), this._headings[e].setAttribute("aria-pressed", "false"), this.shown = -1) : this.expand(e), this.hideDependent();
 | |
|   }
 | |
|   findParentWithClass(s, t) {
 | |
|     for (; s; ) {
 | |
|       if (s.classList && s.classList.contains(t))
 | |
|         return s;
 | |
|       s = s.parentElement;
 | |
|     }
 | |
|     return null;
 | |
|   }
 | |
| }
 | |
| class p extends HTMLElement {
 | |
|   static get observedAttributes() {
 | |
|     return ["data-text", "data-abbrevmap"];
 | |
|   }
 | |
|   static get defaultAbbrevMap() {
 | |
|     return {
 | |
|       "#": "Hinweis auf weitere Informationen in der Anmerkung.",
 | |
|       $: "vermutlich",
 | |
|       "+++": "Inhalte aus mehreren Almanachen interpoliert",
 | |
|       B: "Blatt",
 | |
|       BB: "Blätter",
 | |
|       C: "Corrigenda",
 | |
|       Diagr: "Diagramm",
 | |
|       G: "Graphik",
 | |
|       "G-Verz": "Verzeichnis der Kupfer u. ä.",
 | |
|       GG: "Graphiken",
 | |
|       Hrsg: "Herausgeber",
 | |
|       "I-Verz": "Inhaltsverzeichnis",
 | |
|       Kal: "Kalendarium",
 | |
|       Kr: "Karte",
 | |
|       MusB: "Musikbeigabe",
 | |
|       MusBB: "Musikbeigaben",
 | |
|       S: "Seite",
 | |
|       SS: "Seiten",
 | |
|       Sp: "Spiegel",
 | |
|       T: "Titel",
 | |
|       TG: "Titelgraphik, Titelportrait etc",
 | |
|       "TG r": "Titelgraphik, Titelportrait etc recto",
 | |
|       "TG v": "Titelgraphik, Titelportrait etc verso",
 | |
|       Tab: "Tabelle",
 | |
|       UG: "Umschlaggraphik",
 | |
|       "UG r": "Umschlaggraphik recto",
 | |
|       "UG v": "Umschlaggraphik verso",
 | |
|       VB: "Vorsatzblatt",
 | |
|       Vf: "Verfasser",
 | |
|       VrlgM: "Verlagsmitteilung",
 | |
|       Vrwrt: "Vorwort",
 | |
|       ar: "arabische Paginierung",
 | |
|       ar1: "erste arabische Paginierung",
 | |
|       ar2: "zweite arabische Paginierung",
 | |
|       ar3: "dritte arabische Paginierung",
 | |
|       ar4: "vierte arabische Paginierung",
 | |
|       ar5: "fünfte arabische Paginierung",
 | |
|       ar6: "sechste arabische Paginierung",
 | |
|       ar7: "siebte arabische Paginierung",
 | |
|       gA: "graphische Anleitung",
 | |
|       gT: "graphischer Titel",
 | |
|       gTzA: "graphische Tanzanleitung",
 | |
|       nT: "Nachtitel",
 | |
|       röm: "römische Paginierung",
 | |
|       röm1: "erste römische Paginierung",
 | |
|       röm2: "zweite römische Paginierung",
 | |
|       röm3: "dritte römische Paginierung",
 | |
|       röm4: "vierte römische Paginierung",
 | |
|       röm5: "fünfte römische Paginierung",
 | |
|       röm6: "sechste römische Paginierung",
 | |
|       röm7: "siebte römische Paginierung",
 | |
|       vT: "Vortitel",
 | |
|       zT: "Zwischentitel",
 | |
|       "§§": "Hinweis auf Mängel im Almanach (Beschädigungen, fehlende Graphiken, unvollständige Sammlungen etc) in der Anmerkung"
 | |
|     };
 | |
|   }
 | |
|   constructor() {
 | |
|     super(), this._abbrevMap = p.defaultAbbrevMap;
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this.render();
 | |
|   }
 | |
|   attributeChangedCallback(s, t, e) {
 | |
|     t !== e && (s === "data-abbrevmap" && this._parseAndSetAbbrevMap(e), this.render());
 | |
|   }
 | |
|   _parseAndSetAbbrevMap(s) {
 | |
|     if (!s) {
 | |
|       this._abbrevMap = p.defaultAbbrevMap;
 | |
|       return;
 | |
|     }
 | |
|     try {
 | |
|       this._abbrevMap = JSON.parse(s);
 | |
|     } catch {
 | |
|       this._abbrevMap = p.defaultAbbrevMap;
 | |
|     }
 | |
|   }
 | |
|   setAbbrevMap(s) {
 | |
|     typeof s == "object" && s !== null && (this._abbrevMap = s, this.render());
 | |
|   }
 | |
|   get text() {
 | |
|     return this.getAttribute("data-text") || "";
 | |
|   }
 | |
|   set text(s) {
 | |
|     this.setAttribute("data-text", s);
 | |
|   }
 | |
|   render() {
 | |
|     this.innerHTML = this.transformText(this.text, this._abbrevMap);
 | |
|   }
 | |
|   transformText(s, t) {
 | |
|     let e = "", i = 0;
 | |
|     for (; i < s.length; ) {
 | |
|       if (i > 0 && !this.isSpaceOrPunct(s[i - 1])) {
 | |
|         e += s[i], i++;
 | |
|         continue;
 | |
|       }
 | |
|       const n = this.findLongestAbbrevAt(s, i, t);
 | |
|       if (n) {
 | |
|         const { match: l, meaning: r } = n;
 | |
|         e += `
 | |
|             <tool-tip position="top" class="!inline" timeout="300">
 | |
|               <div class="data-tip p-2 text-sm text-white bg-gray-700 rounded shadow">
 | |
|                 ${r}
 | |
|               </div>
 | |
|               <span class="cursor-help text-blue-900 hover:text-slate-800">
 | |
|                 ${l}
 | |
|               </span>
 | |
|             </tool-tip>
 | |
|           `, i += l.length;
 | |
|       } else
 | |
|         e += s[i], i++;
 | |
|     }
 | |
|     return e;
 | |
|   }
 | |
|   findLongestAbbrevAt(s, t, e) {
 | |
|     let i = null, n = 0;
 | |
|     for (const l of Object.keys(e))
 | |
|       s.startsWith(l, t) && l.length > n && (i = l, n = l.length);
 | |
|     return i ? { match: i, meaning: e[i] } : null;
 | |
|   }
 | |
|   isSpaceOrPunct(s) {
 | |
|     return /\s|[.,;:!?]/.test(s);
 | |
|   }
 | |
| }
 | |
| class dt extends HTMLElement {
 | |
|   constructor() {
 | |
|     super();
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this.style.cursor = "pointer", this.addEventListener("click", this.handleClick);
 | |
|   }
 | |
|   disconnectedCallback() {
 | |
|     this.removeEventListener("click", this.handleClick);
 | |
|   }
 | |
|   handleClick(s) {
 | |
|     const t = this.getAttribute("data-jump");
 | |
|     if (t) {
 | |
|       const e = document.querySelector(t);
 | |
|       e ? e.scrollIntoView({ behavior: "smooth" }) : console.warn(`No element found for selector: ${t}`);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| var b;
 | |
| class ct extends HTMLElement {
 | |
|   constructor() {
 | |
|     super();
 | |
|     _(this, b, 176);
 | |
|     this._images = [];
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     this._images = Array.from(this.querySelectorAll(".primages")), this.calculateShownImages();
 | |
|     const t = new ResizeObserver((e, i) => {
 | |
|       this.calculateShownImages();
 | |
|     });
 | |
|     this._resizeObserver = t, t.observe(this);
 | |
|   }
 | |
|   disconnectedCallback() {
 | |
|     this._resizeObserver.unobserve(this);
 | |
|   }
 | |
|   calculateShownImages() {
 | |
|     const t = this.getBoundingClientRect();
 | |
|     console.log(t);
 | |
|     const e = Math.floor(t.width / (L(this, b) + 10));
 | |
|     for (let i = 0; i < this._images.length; i++)
 | |
|       i < e - 1 ? this._images[i].classList.remove("hidden") : this._images[i].classList.add("hidden");
 | |
|   }
 | |
| }
 | |
| b = new WeakMap();
 | |
| const ut = "msr-component-wrapper", O = "msr-selected-items-container", k = "msr-placeholder-no-selection-text", pt = "msr-selected-item-pill", mt = "msr-selected-item-text", _t = "msr-item-name", ft = "msr-item-additional-data", gt = "msr-selected-item-role", B = "msr-selected-item-delete-btn", Et = "msr-controls-area", M = "msr-pre-add-button", R = "msr-input-area-wrapper", E = "msr-input-area-default-border", I = "msr-input-area-staged", $ = "msr-staging-area-container", bt = "msr-staged-item-pill", St = "msr-staged-item-text", A = "msr-staged-role-select", P = "msr-staged-cancel-btn", N = "msr-text-input", D = "msr-add-button", H = "msr-options-list", q = "msr-option-item", Lt = "msr-option-item-name", vt = "msr-option-item-detail", U = "msr-option-item-highlighted", T = "msr-hidden-select", It = "msr-state-no-selection", At = "msr-state-has-selection", Tt = "msr-state-list-open", Ct = "msr-state-item-staged";
 | |
| class Y extends HTMLElement {
 | |
|   constructor() {
 | |
|     super();
 | |
|     u(this, "_blurTimeout", null);
 | |
|     this.internals_ = this.attachInternals(), this._value = [], this._stagedItem = null, this._showAddButton = !0, this._placeholderNoSelection = "Keine Elemente ausgewählt", this._placeholderSearch = "Elemente suchen...", this._placeholderRoleSelect = "Rolle auswählen...", this._options = [], this._roles = [
 | |
|       "Leitung",
 | |
|       "Unterstützung",
 | |
|       "Berater",
 | |
|       "Beobachter",
 | |
|       "Spezialist",
 | |
|       "Koordinator"
 | |
|     ], this._filteredOptions = [], this._highlightedIndex = -1, this._isOptionsListVisible = !1, this._setupTemplates(), this._bindEventHandlers();
 | |
|   }
 | |
|   static get observedAttributes() {
 | |
|     return [
 | |
|       "disabled",
 | |
|       "name",
 | |
|       "value",
 | |
|       "show-add-button",
 | |
|       "placeholder-no-selection",
 | |
|       "placeholder-search",
 | |
|       "placeholder-role-select"
 | |
|     ];
 | |
|   }
 | |
|   get showAddButton() {
 | |
|     return this._showAddButton;
 | |
|   }
 | |
|   set showAddButton(t) {
 | |
|     const e = typeof t == "string" ? t.toLowerCase() !== "false" : !!t;
 | |
|     this._showAddButton !== e && (this._showAddButton = e, this.setAttribute("show-add-button", String(e)), this.preAddButtonElement && this._updatePreAddButtonVisibility());
 | |
|   }
 | |
|   get placeholderNoSelection() {
 | |
|     return this._placeholderNoSelection;
 | |
|   }
 | |
|   set placeholderNoSelection(t) {
 | |
|     const e = String(t || "Keine Elemente ausgewählt");
 | |
|     this._placeholderNoSelection !== e && (this._placeholderNoSelection = e, this.setAttribute("placeholder-no-selection", e), this.selectedItemsContainer && this._value.length === 0 && this._renderSelectedItems());
 | |
|   }
 | |
|   get placeholderSearch() {
 | |
|     return this._placeholderSearch;
 | |
|   }
 | |
|   set placeholderSearch(t) {
 | |
|     const e = String(t || "Elemente suchen...");
 | |
|     this._placeholderSearch !== e && (this._placeholderSearch = e, this.setAttribute("placeholder-search", e), this.inputElement && (this.inputElement.placeholder = e));
 | |
|   }
 | |
|   get placeholderRoleSelect() {
 | |
|     return this._placeholderRoleSelect;
 | |
|   }
 | |
|   set placeholderRoleSelect(t) {
 | |
|     const e = String(t || "Rolle auswählen...");
 | |
|     this._placeholderRoleSelect !== e && (this._placeholderRoleSelect = e, this.setAttribute("placeholder-role-select", e), this._stagedItem && this.stagedItemPillContainer && this._renderStagedPillOrInput());
 | |
|   }
 | |
|   attributeChangedCallback(t, e, i) {
 | |
|     if (e !== i)
 | |
|       switch (t) {
 | |
|         case "disabled":
 | |
|           this.disabledCallback(this.hasAttribute("disabled"));
 | |
|           break;
 | |
|         case "name":
 | |
|           this.hiddenSelect && (this.hiddenSelect.name = i);
 | |
|           break;
 | |
|         case "value":
 | |
|           break;
 | |
|         case "show-add-button":
 | |
|           this.showAddButton = i;
 | |
|           break;
 | |
|         case "placeholder-no-selection":
 | |
|           this.placeholderNoSelection = i;
 | |
|           break;
 | |
|         case "placeholder-search":
 | |
|           this.placeholderSearch = i;
 | |
|           break;
 | |
|         case "placeholder-role-select":
 | |
|           this.placeholderRoleSelect = i;
 | |
|           break;
 | |
|       }
 | |
|   }
 | |
|   _setupTemplates() {
 | |
|     this.optionTemplate = document.createElement("template"), this.optionTemplate.innerHTML = `
 | |
|                     <li role="option" class="${q} group">
 | |
|                         <span data-ref="nameEl" class="${Lt}"></span>
 | |
|                         <span data-ref="detailEl" class="${vt}"></span>
 | |
|                     </li>
 | |
|                 `, this.selectedItemTemplate = document.createElement("template"), this.selectedItemTemplate.innerHTML = `
 | |
|                     <span class="${pt} group">
 | |
|                         <span data-ref="textEl" class="${mt}"></span>
 | |
|                         <button type="button" data-ref="deleteBtn" class="${B} ml-2">×</button>
 | |
|                     </span>
 | |
|                 `, this.stagedPlacePillTemplate = document.createElement("template"), this.stagedPlacePillTemplate.innerHTML = `
 | |
|                     <span class="${bt} flex items-center">
 | |
|                         <span data-ref="nameEl" class="${St}"></span>
 | |
|                     </span>
 | |
|                 `, this.stagedCancelBtnTemplate = document.createElement("template"), this.stagedCancelBtnTemplate.innerHTML = `
 | |
|                     <button type="button" class="${P} flex items-center justify-center">×</button>
 | |
|                 `, this.stagedRoleSelectTemplate = document.createElement("template"), this.stagedRoleSelectTemplate.innerHTML = `
 | |
|                     <select class="${A}">
 | |
|                     </select>
 | |
|                 `;
 | |
|   }
 | |
|   _bindEventHandlers() {
 | |
|     this._handleInput = this._handleInput.bind(this), this._handleKeyDown = this._handleKeyDown.bind(this), this._handleInputKeyDown = this._handleInputKeyDown.bind(this), this._handleFocus = this._handleFocus.bind(this), this._handleBlur = this._handleBlur.bind(this), this._handleOptionMouseDown = this._handleOptionMouseDown.bind(this), this._handleOptionClick = this._handleOptionClick.bind(this), this._handleAddButtonClick = this._handleAddButtonClick.bind(this), this._handleCancelStagedItem = this._handleCancelStagedItem.bind(this), this._handleStagedRoleChange = this._handleStagedRoleChange.bind(this);
 | |
|   }
 | |
|   _getItemById(t) {
 | |
|     return this._options.find((e) => e.id === t);
 | |
|   }
 | |
|   _getAvailableRolesForItem(t) {
 | |
|     const e = this._value.filter((i) => i.itemId === t).map((i) => i.role);
 | |
|     return this._roles.filter((i) => !e.includes(i));
 | |
|   }
 | |
|   setRoles(t) {
 | |
|     if (Array.isArray(t) && t.every((e) => typeof e == "string")) {
 | |
|       this._roles = [...t], this._stagedItem && this._stagedItem.item && (this._getAvailableRolesForItem(this._stagedItem.item.id).includes(this._stagedItem.currentRole) || (this._stagedItem.currentRole = ""), this._renderStagedPillOrInput(), this._updateAddButtonState());
 | |
|       const e = this._value.filter((i) => this._roles.includes(i.role));
 | |
|       e.length !== this._value.length && (this.value = e.map((i) => `${i.itemId},${i.role}`));
 | |
|     } else
 | |
|       console.error("setRoles expects an array of strings.");
 | |
|   }
 | |
|   setOptions(t) {
 | |
|     if (Array.isArray(t) && t.every((e) => e && typeof e.id == "string" && typeof e.name == "string")) {
 | |
|       this._options = [...t];
 | |
|       const e = this._value.filter((i) => this._getItemById(i.itemId));
 | |
|       e.length !== this._value.length && (this.value = e.map((i) => `${i.itemId},${i.role}`)), this._stagedItem && this._stagedItem.item && !this._getItemById(this._stagedItem.item.id) && this._handleCancelStagedItem(), this._filteredOptions = [], this._highlightedIndex = -1, this.inputElement && this.inputElement.value ? this._handleInput({ target: this.inputElement }) : this._hideOptionsList();
 | |
|     } else
 | |
|       console.error("setOptions expects an array of objects with id and name properties.");
 | |
|   }
 | |
|   get value() {
 | |
|     return this._value;
 | |
|   }
 | |
|   set value(t) {
 | |
|     if (Array.isArray(t)) {
 | |
|       const e = t.map((l) => {
 | |
|         if (typeof l == "string") {
 | |
|           const r = l.split(",");
 | |
|           if (r.length === 2) {
 | |
|             const o = r[0].trim(), d = r[1].trim();
 | |
|             if (this._getItemById(o) && this._roles.includes(d))
 | |
|               return { itemId: o, role: d, instanceId: crypto.randomUUID() };
 | |
|           }
 | |
|         }
 | |
|         return null;
 | |
|       }).filter((l) => l !== null), i = [], n = /* @__PURE__ */ new Set();
 | |
|       for (const l of e) {
 | |
|         const r = `${l.itemId},${l.role}`;
 | |
|         n.has(r) || (i.push(l), n.add(r));
 | |
|       }
 | |
|       this._value = i;
 | |
|     } else
 | |
|       this._value = [];
 | |
|     this._updateFormValue(), this.selectedItemsContainer && this._renderSelectedItems(), this._updateRootElementStateClasses();
 | |
|   }
 | |
|   get name() {
 | |
|     return this.getAttribute("name");
 | |
|   }
 | |
|   set name(t) {
 | |
|     this.setAttribute("name", t), this.hiddenSelect && (this.hiddenSelect.name = t);
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     if (this.placeholderNoSelection = this.getAttribute("placeholder-no-selection") || this._placeholderNoSelection, this.placeholderSearch = this.getAttribute("placeholder-search") || this._placeholderSearch, this.placeholderRoleSelect = this.getAttribute("placeholder-role-select") || this._placeholderRoleSelect, this._render(), this.inputAreaWrapper = this.querySelector(`.${R}`), this.inputElement = this.querySelector(`.${N}`), this.stagedItemPillContainer = this.querySelector(`.${$}`), this.optionsListElement = this.querySelector(`.${H}`), this.selectedItemsContainer = this.querySelector(`.${O}`), this.addButtonElement = this.querySelector(`.${D}`), this.preAddButtonElement = this.querySelector(`.${M}`), this.hiddenSelect = this.querySelector(`.${T}`), this.name && this.hiddenSelect && (this.hiddenSelect.name = this.name), this.hasAttribute("show-add-button") ? this.showAddButton = this.getAttribute("show-add-button") : this.setAttribute("show-add-button", String(this._showAddButton)), this.inputElement && (this.inputElement.placeholder = this.placeholderSearch), this.inputElement.addEventListener("input", this._handleInput), this.inputElement.addEventListener("keydown", this._handleInputKeyDown), this.inputElement.addEventListener("focus", this._handleFocus), this.inputElement.addEventListener("blur", this._handleBlur), this.optionsListElement.addEventListener("mousedown", this._handleOptionMouseDown), this.optionsListElement.addEventListener("click", this._handleOptionClick), this.addButtonElement.addEventListener("click", this._handleAddButtonClick), this.addEventListener("keydown", this._handleKeyDown), this._renderStagedPillOrInput(), this._updateAddButtonState(), this._updatePreAddButtonVisibility(), this._updateRootElementStateClasses(), this.hasAttribute("value")) {
 | |
|       const t = this.getAttribute("value");
 | |
|       try {
 | |
|         const e = JSON.parse(t);
 | |
|         Array.isArray(e) ? this.value = e : (console.warn("Parsed value attribute is not an array:", e), this.value = []);
 | |
|       } catch (e) {
 | |
|         if (console.warn("Failed to parse value attribute as JSON array. Attribute was:", t, e), t.startsWith("[") && t.endsWith("]"))
 | |
|           try {
 | |
|             const i = t.slice(1, -1).split(",").map((n) => n.replace(/"/g, "").trim()).filter((n) => n);
 | |
|             this.value = i;
 | |
|           } catch (i) {
 | |
|             console.error("Manual parse of value attribute also failed:", t, i), this.value = [];
 | |
|           }
 | |
|         else t.includes(",") ? this.value = [t] : this.value = [];
 | |
|       }
 | |
|     } else
 | |
|       this._renderSelectedItems(), this._synchronizeHiddenSelect();
 | |
|     this.hasAttribute("disabled") && this.disabledCallback(!0);
 | |
|   }
 | |
|   disconnectedCallback() {
 | |
|     this.inputElement && (this.inputElement.removeEventListener("input", this._handleInput), this.inputElement.removeEventListener("keydown", this._handleInputKeyDown), this.inputElement.removeEventListener("focus", this._handleFocus), this.inputElement.removeEventListener("blur", this._handleBlur)), this.optionsListElement && (this.optionsListElement.removeEventListener("mousedown", this._handleOptionMouseDown), this.optionsListElement.removeEventListener("click", this._handleOptionClick)), this.addButtonElement && this.addButtonElement.removeEventListener("click", this._handleAddButtonClick), this.removeEventListener("keydown", this._handleKeyDown), clearTimeout(this._blurTimeout);
 | |
|   }
 | |
|   formAssociatedCallback(t) {
 | |
|   }
 | |
|   formDisabledCallback(t) {
 | |
|     this.disabledCallback(t);
 | |
|   }
 | |
|   disabledCallback(t) {
 | |
|     this.inputElement && (this.inputElement.disabled = t), this.classList.toggle("pointer-events-none", t), this.querySelectorAll(`.${B}`).forEach(
 | |
|       (i) => i.disabled = t
 | |
|     );
 | |
|     const e = this.querySelector(`.${A}`);
 | |
|     e && (e.disabled = t), this.hiddenSelect && (this.hiddenSelect.disabled = t), this._updateAddButtonState(), this._updatePreAddButtonVisibility();
 | |
|   }
 | |
|   formResetCallback() {
 | |
|     this.value = [], this._stagedItem = null, this._renderStagedPillOrInput(), this._hideOptionsList(), this.inputElement && (this.inputElement.value = ""), this._updateRootElementStateClasses();
 | |
|   }
 | |
|   formStateRestoreCallback(t, e) {
 | |
|     Array.isArray(t) && t.every((i) => typeof i == "string" && i.includes(",")) ? this.value = t : this.value = [], this._updateRootElementStateClasses(), this._updatePreAddButtonVisibility();
 | |
|   }
 | |
|   _synchronizeHiddenSelect() {
 | |
|     this.hiddenSelect && (this.hiddenSelect.innerHTML = "", this._value.forEach((t) => {
 | |
|       var i;
 | |
|       const e = document.createElement("option");
 | |
|       e.value = `${t.itemId},${t.role}`, e.textContent = `${((i = this._getItemById(t.itemId)) == null ? void 0 : i.name) || t.itemId} (${t.role})`, e.selected = !0, this.hiddenSelect.appendChild(e);
 | |
|     }));
 | |
|   }
 | |
|   _updateFormValue() {
 | |
|     this.internals_.setFormValue(null), this._synchronizeHiddenSelect();
 | |
|   }
 | |
|   _updateRootElementStateClasses() {
 | |
|     this.classList.toggle(It, this._value.length === 0), this.classList.toggle(At, this._value.length > 0), this.classList.toggle(Tt, this._isOptionsListVisible), this.classList.toggle(Ct, !!this._stagedItem);
 | |
|   }
 | |
|   _render() {
 | |
|     const t = this.id || `msr-${crypto.randomUUID().slice(0, 8)}`;
 | |
|     this.id || this.setAttribute("id", t), this.innerHTML = `
 | |
|                     <style>
 | |
|                         .${T} {
 | |
|                             display: none !important; visibility: hidden !important; position: absolute !important;
 | |
|                             width: 0 !important; height: 0 !important; opacity: 0 !important; pointer-events: none !important;
 | |
|                         }
 | |
|                     </style>
 | |
|                     <div class="${ut} relative">
 | |
|                         <div class="${O} flex flex-wrap gap-1 mb-2 min-h-[2.625rem] rounded-md" aria-live="polite">
 | |
|                            ${this._value.length === 0 ? `<span class="${k}">${this.placeholderNoSelection}</span>` : ""}
 | |
|                         </div>
 | |
|                         <div class="${Et} flex items-center">
 | |
|                             <div class="${R} ${E} flex-grow min-h-[42px] flex items-center flex-wrap gap-1" tabindex="-1">
 | |
|                                 <span class="${$} flex items-center gap-2"></span>
 | |
|                                 <input type="text"
 | |
|                                        class="${N} flex-1 min-w-[100px] outline-none"
 | |
|                                        placeholder="${this.placeholderSearch}"
 | |
|                                        aria-haspopup="listbox"
 | |
|                                        aria-expanded="false">
 | |
|                             </div>
 | |
|                             <button type="button"
 | |
|                                     class="${M} hidden flex items-center justify-center ml-2"
 | |
|                                     aria-label="Element schnell hinzufügen">
 | |
|                                 +
 | |
|                             </button>
 | |
|                             <button type="button" class="${D} hidden ml-2">Hinzufügen</button>
 | |
|                         </div>
 | |
|                         <ul role="listbox" id="${t}-options-list" class="${H} absolute z-20 w-full max-h-60 overflow-y-auto mt-1 hidden"></ul>
 | |
|                         <select multiple name="${this.getAttribute("name") || "items_with_roles_default"}" id="hidden-select-${t}" class="${T}" aria-hidden="true"></select>
 | |
|                     </div>
 | |
|                 `;
 | |
|   }
 | |
|   _createStagedItemPillElement(t) {
 | |
|     const i = this.stagedPlacePillTemplate.content.cloneNode(!0).firstElementChild;
 | |
|     return i.querySelector('[data-ref="nameEl"]').textContent = t.name, i;
 | |
|   }
 | |
|   _createStagedRoleSelectElement(t, e) {
 | |
|     const n = this.stagedRoleSelectTemplate.content.cloneNode(!0).firstElementChild;
 | |
|     let l = `<option value="" disabled ${e ? "" : "selected"}>${this.placeholderRoleSelect}</option>`;
 | |
|     return t.length === 0 && !this._roles.includes(e) ? (l += "<option disabled>Keine Rollen verfügbar</option>", n.disabled = !0) : (t.forEach((r) => {
 | |
|       l += `<option value="${r}" ${r === e ? "selected" : ""}>${r}</option>`;
 | |
|     }), n.disabled = t.length === 0 && e === ""), n.innerHTML = l, n.addEventListener("change", this._handleStagedRoleChange), n;
 | |
|   }
 | |
|   _createStagedCancelButtonElement(t) {
 | |
|     const i = this.stagedCancelBtnTemplate.content.cloneNode(!0).firstElementChild;
 | |
|     return i.setAttribute("aria-label", `Auswahl von ${t} abbrechen`), i.addEventListener("click", this._handleCancelStagedItem), i;
 | |
|   }
 | |
|   _renderStagedPillOrInput() {
 | |
|     if (!(!this.stagedItemPillContainer || !this.inputElement || !this.inputAreaWrapper)) {
 | |
|       if (this.stagedItemPillContainer.innerHTML = "", this._stagedItem && this._stagedItem.item) {
 | |
|         this.inputAreaWrapper.classList.remove(E), this.inputAreaWrapper.classList.add(I);
 | |
|         const t = this._createStagedItemPillElement(this._stagedItem.item);
 | |
|         this.stagedItemPillContainer.appendChild(t);
 | |
|         const e = this._getAvailableRolesForItem(this._stagedItem.item.id), i = this._createStagedRoleSelectElement(
 | |
|           e,
 | |
|           this._stagedItem.currentRole
 | |
|         );
 | |
|         this.stagedItemPillContainer.appendChild(i);
 | |
|         const n = this._createStagedCancelButtonElement(this._stagedItem.item.name);
 | |
|         this.stagedItemPillContainer.appendChild(n), this.inputElement.classList.add("hidden"), this.inputElement.value = "", this.inputElement.removeAttribute("aria-activedescendant"), this.inputElement.setAttribute("aria-expanded", "false");
 | |
|       } else
 | |
|         this.inputAreaWrapper.classList.add(E), this.inputAreaWrapper.classList.remove(I), this.inputElement.classList.remove("hidden");
 | |
|       this._updateAddButtonState(), this._updatePreAddButtonVisibility(), this._updateRootElementStateClasses();
 | |
|     }
 | |
|   }
 | |
|   _updatePreAddButtonVisibility() {
 | |
|     if (!this.preAddButtonElement) return;
 | |
|     const t = this.hasAttribute("disabled"), e = !this._stagedItem, i = this.showAddButton && e && !t;
 | |
|     this.preAddButtonElement.classList.toggle("hidden", !i), this.preAddButtonElement.disabled = t;
 | |
|   }
 | |
|   _handleStagedRoleChange(t) {
 | |
|     this._stagedItem && (this._stagedItem.currentRole = t.target.value, this._updateAddButtonState());
 | |
|   }
 | |
|   _handleCancelStagedItem(t) {
 | |
|     t && t.stopPropagation(), this._stagedItem = null, this._renderStagedPillOrInput(), this.inputElement && (this.inputElement.value = "", this.inputElement.focus()), this._hideOptionsList();
 | |
|   }
 | |
|   _createSelectedItemElement(t) {
 | |
|     const e = this._getItemById(t.itemId);
 | |
|     if (!e) return null;
 | |
|     const n = this.selectedItemTemplate.content.cloneNode(!0).firstElementChild, l = n.querySelector('[data-ref="textEl"]');
 | |
|     let r = `<span class="${_t}">${e.name}</span>`, o = e.additional_data ? ` <span class="${ft}">(${e.additional_data})</span>` : "", d = ` <span class="${gt}">${t.role}</span>`;
 | |
|     l.innerHTML = `${r}${o}${d}`;
 | |
|     const c = n.querySelector('[data-ref="deleteBtn"]');
 | |
|     return c.setAttribute("aria-label", `Entferne ${e.name} als ${t.role}`), c.dataset.instanceId = t.instanceId, c.disabled = this.hasAttribute("disabled"), c.addEventListener("click", (Q) => {
 | |
|       Q.stopPropagation(), this._handleDeleteSelectedItem(t.instanceId);
 | |
|     }), n;
 | |
|   }
 | |
|   _renderSelectedItems() {
 | |
|     this.selectedItemsContainer && (this.selectedItemsContainer.innerHTML = "", this._value.length === 0 ? this.selectedItemsContainer.innerHTML = `<span class="${k}">${this.placeholderNoSelection}</span>` : this._value.forEach((t) => {
 | |
|       const e = this._createSelectedItemElement(t);
 | |
|       e && this.selectedItemsContainer.appendChild(e);
 | |
|     }), this._updateRootElementStateClasses());
 | |
|   }
 | |
|   _updateAddButtonState() {
 | |
|     if (this.addButtonElement) {
 | |
|       const t = this.hasAttribute("disabled"), e = this._stagedItem && this._stagedItem.currentRole && this._roles.includes(this._stagedItem.currentRole), i = !this._stagedItem || !e || t;
 | |
|       this.addButtonElement.classList.toggle("hidden", i), this.addButtonElement.disabled = i;
 | |
|     }
 | |
|   }
 | |
|   _createOptionElement(t, e) {
 | |
|     const n = this.optionTemplate.content.cloneNode(!0).firstElementChild;
 | |
|     return n.querySelector('[data-ref="nameEl"]').textContent = t.name, n.querySelector('[data-ref="detailEl"]').textContent = t.additional_data ? `(${t.additional_data})` : "", n.dataset.id = t.id, n.setAttribute("aria-selected", String(e === this._highlightedIndex)), n.id = `${this.id || "msr"}-option-${t.id}`, e === this._highlightedIndex && n.classList.add(U), n;
 | |
|   }
 | |
|   _renderOptionsList() {
 | |
|     if (!(!this.optionsListElement || !this.inputElement)) {
 | |
|       if (this.optionsListElement.innerHTML = "", this._filteredOptions.length === 0 || !this._isOptionsListVisible)
 | |
|         this.optionsListElement.classList.add("hidden"), this.inputElement.setAttribute("aria-expanded", "false"), this.inputElement.removeAttribute("aria-activedescendant"), this.inputElement.removeAttribute("aria-controls");
 | |
|       else {
 | |
|         this.optionsListElement.classList.remove("hidden"), this.inputElement.setAttribute("aria-expanded", "true"), this.inputElement.setAttribute("aria-controls", this.optionsListElement.id), this._filteredOptions.forEach((e, i) => {
 | |
|           const n = this._createOptionElement(e, i);
 | |
|           this.optionsListElement.appendChild(n);
 | |
|         });
 | |
|         const t = this.optionsListElement.querySelector(
 | |
|           `.${U}`
 | |
|         );
 | |
|         t ? (t.scrollIntoView({ block: "nearest" }), this.inputElement.setAttribute("aria-activedescendant", t.id)) : this.inputElement.removeAttribute("aria-activedescendant");
 | |
|       }
 | |
|       this._updateRootElementStateClasses();
 | |
|     }
 | |
|   }
 | |
|   _stageItem(t) {
 | |
|     if (this._getAvailableRolesForItem(t.id).length === 0)
 | |
|       return;
 | |
|     this._stagedItem = { item: t, currentRole: "" }, this.inputElement && (this.inputElement.value = "", this.inputElement.setAttribute("aria-expanded", "false"), this.inputElement.removeAttribute("aria-activedescendant")), this._renderStagedPillOrInput(), this._hideOptionsList();
 | |
|     const i = this.stagedItemPillContainer.querySelector(
 | |
|       `.${A}`
 | |
|     );
 | |
|     i && !i.disabled ? i.focus() : this.addButtonElement && !this.addButtonElement.disabled && this.addButtonElement.focus();
 | |
|   }
 | |
|   _handleAddButtonClick() {
 | |
|     if (!this.hasAttribute("disabled") && this._stagedItem && this._stagedItem.item && this._stagedItem.currentRole && this._roles.includes(this._stagedItem.currentRole)) {
 | |
|       const t = {
 | |
|         itemId: this._stagedItem.item.id,
 | |
|         role: this._stagedItem.currentRole,
 | |
|         instanceId: crypto.randomUUID()
 | |
|       };
 | |
|       if (this._value.find(
 | |
|         (i) => i.itemId === t.itemId && i.role === t.role
 | |
|       )) {
 | |
|         this._handleCancelStagedItem();
 | |
|         return;
 | |
|       }
 | |
|       this._value.push(t), this._updateFormValue(), this._renderSelectedItems(), this._stagedItem = null, this._renderStagedPillOrInput(), this.inputElement && (this.inputElement.value = "", this.inputElement.focus()), this._hideOptionsList();
 | |
|     }
 | |
|   }
 | |
|   _handleInput(t) {
 | |
|     if (this.hasAttribute("disabled")) return;
 | |
|     this._stagedItem ? (this._stagedItem = null, this._renderStagedPillOrInput()) : this._updatePreAddButtonVisibility();
 | |
|     const e = t.target.value;
 | |
|     if (e.length === 0)
 | |
|       this._filteredOptions = [], this._isOptionsListVisible = !1;
 | |
|     else {
 | |
|       const i = e.toLowerCase();
 | |
|       this._filteredOptions = this._options.filter((n) => this._getAvailableRolesForItem(n.id).length === 0 || this._stagedItem && this._stagedItem.item.id === n.id ? !1 : n.name.toLowerCase().includes(i) || n.additional_data && n.additional_data.toLowerCase().includes(i)), this._isOptionsListVisible = this._filteredOptions.length > 0;
 | |
|     }
 | |
|     this._highlightedIndex = this._filteredOptions.length > 0 ? 0 : -1, this._renderOptionsList();
 | |
|   }
 | |
|   _handleKeyDown(t) {
 | |
|     var e;
 | |
|     if (!this.hasAttribute("disabled")) {
 | |
|       if (t.key === "Enter" && this._stagedItem && this._stagedItem.item) {
 | |
|         const i = document.activeElement, n = (e = this.stagedItemPillContainer) == null ? void 0 : e.querySelector(
 | |
|           `.${P}`
 | |
|         );
 | |
|         if (i === n) {
 | |
|           t.preventDefault(), this._handleCancelStagedItem(t);
 | |
|           return;
 | |
|         } else if (this._stagedItem.currentRole && this._roles.includes(this._stagedItem.currentRole)) {
 | |
|           t.preventDefault(), this._handleAddButtonClick();
 | |
|           return;
 | |
|         }
 | |
|       }
 | |
|       t.key === "Escape" && (this._isOptionsListVisible ? (t.preventDefault(), this._hideOptionsList(), this.inputElement && this.inputElement.focus()) : this._stagedItem && (t.preventDefault(), this._handleCancelStagedItem(t)));
 | |
|     }
 | |
|   }
 | |
|   _handleInputKeyDown(t) {
 | |
|     if (!(this.hasAttribute("disabled") || this.inputElement && this.inputElement.disabled)) {
 | |
|       if (!this._isOptionsListVisible || this._filteredOptions.length === 0) {
 | |
|         t.key === "Enter" && this.inputElement && this.inputElement.value === "" && t.preventDefault();
 | |
|         return;
 | |
|       }
 | |
|       switch (t.key) {
 | |
|         case "ArrowDown":
 | |
|           t.preventDefault(), this._highlightedIndex = (this._highlightedIndex + 1) % this._filteredOptions.length, this._renderOptionsList();
 | |
|           break;
 | |
|         case "ArrowUp":
 | |
|           t.preventDefault(), this._highlightedIndex = (this._highlightedIndex - 1 + this._filteredOptions.length) % this._filteredOptions.length, this._renderOptionsList();
 | |
|           break;
 | |
|         case "Enter":
 | |
|         case "Tab":
 | |
|           this._highlightedIndex > -1 && this._filteredOptions[this._highlightedIndex] ? (t.preventDefault(), this._stageItem(this._filteredOptions[this._highlightedIndex])) : t.key === "Tab" && this._hideOptionsList();
 | |
|           break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   _hideOptionsList() {
 | |
|     this._isOptionsListVisible = !1, this._highlightedIndex = -1, this.optionsListElement && this._renderOptionsList(), this.inputElement && (this.inputElement.setAttribute("aria-expanded", "false"), this.inputElement.removeAttribute("aria-activedescendant"));
 | |
|   }
 | |
|   _handleFocus() {
 | |
|     if (!(this.hasAttribute("disabled") || this.inputElement && this.inputElement.disabled || this._stagedItem)) {
 | |
|       if (!this._stagedItem && this.inputAreaWrapper && (this.inputAreaWrapper.classList.add(E), this.inputAreaWrapper.classList.remove(I)), this.inputElement && this.inputElement.value.length > 0) {
 | |
|         const t = this.inputElement.value.toLowerCase();
 | |
|         this._filteredOptions = this._options.filter((e) => this._getAvailableRolesForItem(e.id).length === 0 ? !1 : e.name.toLowerCase().includes(t) || e.additional_data && e.additional_data.toLowerCase().includes(t)), this._filteredOptions.length > 0 ? (this._isOptionsListVisible = !0, this._highlightedIndex = 0, this._renderOptionsList()) : this._hideOptionsList();
 | |
|       } else
 | |
|         this._hideOptionsList();
 | |
|       this._updateRootElementStateClasses(), this._updatePreAddButtonVisibility();
 | |
|     }
 | |
|   }
 | |
|   _handleBlur(t) {
 | |
|     this._blurTimeout = setTimeout(() => {
 | |
|       const e = document.activeElement;
 | |
|       e !== this.addButtonElement && e !== this.preAddButtonElement && !(this.stagedItemPillContainer && this.stagedItemPillContainer.contains(e)) && !(this.optionsListElement && this.optionsListElement.contains(e)) && !this.contains(e) && this._hideOptionsList();
 | |
|     }, 150);
 | |
|   }
 | |
|   _handleOptionMouseDown(t) {
 | |
|     t.preventDefault();
 | |
|   }
 | |
|   _handleOptionClick(t) {
 | |
|     if (this.hasAttribute("disabled")) return;
 | |
|     const e = t.target.closest(`li[data-id].${q}`);
 | |
|     if (e) {
 | |
|       const i = e.dataset.id, n = this._filteredOptions.find((l) => l.id === i);
 | |
|       n && this._stageItem(n);
 | |
|     }
 | |
|   }
 | |
|   _handleDeleteSelectedItem(t) {
 | |
|     this.hasAttribute("disabled") || (this._value = this._value.filter((e) => e.instanceId !== t), this._updateFormValue(), this._renderSelectedItems(), this._stagedItem && this._stagedItem.item && this._renderStagedPillOrInput(), this.inputElement && this.inputElement.focus(), this._updatePreAddButtonVisibility());
 | |
|   }
 | |
| }
 | |
| u(Y, "formAssociated", !0);
 | |
| const yt = "mss-component-wrapper", F = "mss-selected-items-container", wt = "mss-selected-item-pill", xt = "mss-selected-item-text", Ot = "mss-selected-item-pill-detail", V = "mss-selected-item-delete-btn", W = "mss-input-controls-container", G = "mss-input-wrapper", K = "mss-input-wrapper-focused", z = "mss-text-input", j = "mss-create-new-button", J = "mss-options-list", kt = "mss-option-item", Bt = "mss-option-item-name", Mt = "mss-option-item-detail", X = "mss-option-item-highlighted", C = "mss-hidden-select", Rt = "mss-no-items-text", $t = "mss-state-no-selection", Pt = "mss-state-has-selection", Nt = "mss-state-list-open";
 | |
| class Z extends HTMLElement {
 | |
|   constructor() {
 | |
|     super();
 | |
|     u(this, "_blurTimeout", null);
 | |
|     this.internals_ = this.attachInternals(), this._value = [], this._options = [
 | |
|       { id: "marie_curie", name: "Marie Curie", additional_data: "Physicist and Chemist" },
 | |
|       { id: "leonardo_da_vinci", name: "Leonardo da Vinci", additional_data: "Polymath" },
 | |
|       { id: "albert_einstein", name: "Albert Einstein", additional_data: "Theoretical Physicist" },
 | |
|       { id: "ada_lovelace", name: "Ada Lovelace", additional_data: "Mathematician and Writer" },
 | |
|       { id: "isaac_newton", name: "Isaac Newton", additional_data: "Mathematician and Physicist" },
 | |
|       {
 | |
|         id: "galileo_galilei",
 | |
|         name: "Galileo Galilei",
 | |
|         additional_data: "Astronomer and Physicist"
 | |
|       },
 | |
|       { id: "charles_darwin", name: "Charles Darwin", additional_data: "Naturalist" },
 | |
|       { id: "nikola_tesla", name: "Nikola Tesla", additional_data: "Inventor and Engineer" },
 | |
|       { id: "jane_austen", name: "Jane Austen", additional_data: "Novelist" },
 | |
|       {
 | |
|         id: "william_shakespeare",
 | |
|         name: "William Shakespeare",
 | |
|         additional_data: "Playwright and Poet"
 | |
|       }
 | |
|     ], this._filteredOptions = [], this._highlightedIndex = -1, this._isOptionsListVisible = !1, this._placeholder = this.getAttribute("placeholder") || "Search items...", this._showCreateButton = this.getAttribute("show-create-button") !== "false", this._setupTemplates(), this._bindEventHandlers();
 | |
|   }
 | |
|   _setupTemplates() {
 | |
|     this.optionTemplate = document.createElement("template"), this.optionTemplate.innerHTML = `
 | |
|                     <li role="option" class="${kt}">
 | |
|                         <span data-ref="nameEl" class="${Bt}"></span>
 | |
|                         <span data-ref="detailEl" class="${Mt}"></span>
 | |
|                     </li>
 | |
|                 `, this.selectedItemTemplate = document.createElement("template"), this.selectedItemTemplate.innerHTML = `
 | |
|                     <span class="${wt} flex items-center">
 | |
|                         <span data-ref="textEl" class="${xt}"></span>
 | |
|                         <span data-ref="detailEl" class="${Ot} hidden"></span>
 | |
|                         <button type="button" data-ref="deleteBtn" class="${V}">×</button>
 | |
|                     </span>
 | |
|                 `;
 | |
|   }
 | |
|   _bindEventHandlers() {
 | |
|     this._handleInput = this._handleInput.bind(this), this._handleKeyDown = this._handleKeyDown.bind(this), this._handleFocus = this._handleFocus.bind(this), this._handleBlur = this._handleBlur.bind(this), this._handleOptionMouseDown = this._handleOptionMouseDown.bind(this), this._handleOptionClick = this._handleOptionClick.bind(this), this._handleCreateNewButtonClick = this._handleCreateNewButtonClick.bind(this), this._handleSelectedItemsContainerClick = this._handleSelectedItemsContainerClick.bind(this);
 | |
|   }
 | |
|   _getItemById(t) {
 | |
|     return this._options.find((e) => e.id === t);
 | |
|   }
 | |
|   get placeholder() {
 | |
|     return this._placeholder;
 | |
|   }
 | |
|   set placeholder(t) {
 | |
|     this._placeholder = t, this.inputElement && (this.inputElement.placeholder = this._placeholder), this.setAttribute("placeholder", t);
 | |
|   }
 | |
|   get showCreateButton() {
 | |
|     return this._showCreateButton;
 | |
|   }
 | |
|   set showCreateButton(t) {
 | |
|     const e = String(t).toLowerCase() !== "false" && t !== !1;
 | |
|     this._showCreateButton !== e && (this._showCreateButton = e, this.createNewButton && this.createNewButton.classList.toggle("hidden", !this._showCreateButton), this.setAttribute("show-create-button", this._showCreateButton ? "true" : "false"));
 | |
|   }
 | |
|   setOptions(t) {
 | |
|     if (Array.isArray(t) && t.every((e) => e && typeof e.id == "string" && typeof e.name == "string")) {
 | |
|       this._options = [...t];
 | |
|       const e = this._value.filter((i) => this._getItemById(i));
 | |
|       e.length !== this._value.length ? this.value = e : this.selectedItemsContainer && this._renderSelectedItems(), this._filteredOptions = [], this._highlightedIndex = -1, this.inputElement && this.inputElement.value ? this._handleInput({ target: this.inputElement }) : this._hideOptionsList();
 | |
|     } else console.error("setOptions expects an array of objects with id and name properties.");
 | |
|   }
 | |
|   get value() {
 | |
|     return this._value;
 | |
|   }
 | |
|   set value(t) {
 | |
|     const e = JSON.stringify(this._value.sort());
 | |
|     if (Array.isArray(t))
 | |
|       this._value = [
 | |
|         ...new Set(t.filter((n) => typeof n == "string" && this._getItemById(n)))
 | |
|       ];
 | |
|     else if (typeof t == "string" && t.trim() !== "") {
 | |
|       const n = t.trim();
 | |
|       this._getItemById(n) && !this._value.includes(n) ? this._value = [n] : this._getItemById(n) || (this._value = this._value.filter((l) => l !== n));
 | |
|     } else this._value = [];
 | |
|     const i = JSON.stringify(this._value.sort());
 | |
|     e !== i && (this._updateFormValue(), this.selectedItemsContainer && this._renderSelectedItems(), this._updateRootElementStateClasses(), this.dispatchEvent(new Event("change", { bubbles: !0 })));
 | |
|   }
 | |
|   get name() {
 | |
|     return this.getAttribute("name");
 | |
|   }
 | |
|   set name(t) {
 | |
|     this.setAttribute("name", t), this.hiddenSelect && (this.hiddenSelect.name = t);
 | |
|   }
 | |
|   connectedCallback() {
 | |
|     if (this._render(), this.inputControlsContainer = this.querySelector(`.${W}`), this.inputWrapper = this.querySelector(`.${G}`), this.inputElement = this.querySelector(`.${z}`), this.createNewButton = this.querySelector(`.${j}`), this.optionsListElement = this.querySelector(`.${J}`), this.selectedItemsContainer = this.querySelector(`.${F}`), this.hiddenSelect = this.querySelector(`.${C}`), this.placeholder = this.getAttribute("placeholder") || "Search items...", this.showCreateButton = this.getAttribute("show-create-button") !== "false", this.name && this.hiddenSelect && (this.hiddenSelect.name = this.name), this.inputElement.addEventListener("input", this._handleInput), this.inputElement.addEventListener("keydown", this._handleKeyDown), this.inputElement.addEventListener("focus", this._handleFocus), this.inputElement.addEventListener("blur", this._handleBlur), this.optionsListElement.addEventListener("mousedown", this._handleOptionMouseDown), this.optionsListElement.addEventListener("click", this._handleOptionClick), this.createNewButton.addEventListener("click", this._handleCreateNewButtonClick), this.selectedItemsContainer.addEventListener("click", this._handleSelectedItemsContainerClick), this._updateRootElementStateClasses(), this.hasAttribute("value")) {
 | |
|       const t = this.getAttribute("value");
 | |
|       try {
 | |
|         this.value = JSON.parse(t);
 | |
|       } catch {
 | |
|         this.value = t.split(",").map((i) => i.trim()).filter(Boolean);
 | |
|       }
 | |
|     } else
 | |
|       this._renderSelectedItems(), this._synchronizeHiddenSelect();
 | |
|     this.hasAttribute("disabled") && this.disabledCallback(!0);
 | |
|   }
 | |
|   disconnectedCallback() {
 | |
|     this.inputElement && (this.inputElement.removeEventListener("input", this._handleInput), this.inputElement.removeEventListener("keydown", this._handleKeyDown), this.inputElement.removeEventListener("focus", this._handleFocus), this.inputElement.removeEventListener("blur", this._handleBlur)), this.optionsListElement && (this.optionsListElement.removeEventListener("mousedown", this._handleOptionMouseDown), this.optionsListElement.removeEventListener("click", this._handleOptionClick)), this.createNewButton && this.createNewButton.removeEventListener("click", this._handleCreateNewButtonClick), this.selectedItemsContainer && this.selectedItemsContainer.removeEventListener(
 | |
|       "click",
 | |
|       this._handleSelectedItemsContainerClick
 | |
|     ), clearTimeout(this._blurTimeout);
 | |
|   }
 | |
|   static get observedAttributes() {
 | |
|     return ["disabled", "name", "value", "placeholder", "show-create-button"];
 | |
|   }
 | |
|   attributeChangedCallback(t, e, i) {
 | |
|     if (e !== i)
 | |
|       if (t === "disabled") this.disabledCallback(this.hasAttribute("disabled"));
 | |
|       else if (t === "name" && this.hiddenSelect) this.hiddenSelect.name = i;
 | |
|       else if (t === "value" && this.inputElement)
 | |
|         try {
 | |
|           this.value = JSON.parse(i);
 | |
|         } catch {
 | |
|           this.value = i.split(",").map((l) => l.trim()).filter(Boolean);
 | |
|         }
 | |
|       else t === "placeholder" ? this.placeholder = i : t === "show-create-button" && (this.showCreateButton = i);
 | |
|   }
 | |
|   formAssociatedCallback(t) {
 | |
|   }
 | |
|   formDisabledCallback(t) {
 | |
|     this.disabledCallback(t);
 | |
|   }
 | |
|   formResetCallback() {
 | |
|     this.value = [], this._hideOptionsList(), this.inputElement && (this.inputElement.value = ""), this.placeholder = this.getAttribute("placeholder") || "Search items...", this.showCreateButton = this.getAttribute("show-create-button") !== "false", this._updateRootElementStateClasses(), this._renderSelectedItems();
 | |
|   }
 | |
|   formStateRestoreCallback(t, e) {
 | |
|     this.value = Array.isArray(t) ? t : [], this._updateRootElementStateClasses();
 | |
|   }
 | |
|   _synchronizeHiddenSelect() {
 | |
|     this.hiddenSelect && (this.hiddenSelect.innerHTML = "", this._value.forEach((t) => {
 | |
|       const e = document.createElement("option");
 | |
|       e.value = t;
 | |
|       const i = this._getItemById(t);
 | |
|       e.textContent = i ? i.name : t, e.selected = !0, this.hiddenSelect.appendChild(e);
 | |
|     }));
 | |
|   }
 | |
|   _updateFormValue() {
 | |
|     this.internals_.setFormValue(null), this._synchronizeHiddenSelect();
 | |
|   }
 | |
|   disabledCallback(t) {
 | |
|     this.inputElement && (this.inputElement.disabled = t), this.createNewButton && (this.createNewButton.disabled = t), this.toggleAttribute("disabled", t), this.querySelectorAll(`.${V}`).forEach(
 | |
|       (e) => e.disabled = t
 | |
|     ), this.hiddenSelect && (this.hiddenSelect.disabled = t), t && this._hideOptionsList();
 | |
|   }
 | |
|   _updateRootElementStateClasses() {
 | |
|     this.classList.toggle($t, this._value.length === 0), this.classList.toggle(Pt, this._value.length > 0), this.classList.toggle(Nt, this._isOptionsListVisible);
 | |
|   }
 | |
|   _render() {
 | |
|     const t = this.id || `mss-${crypto.randomUUID().slice(0, 8)}`;
 | |
|     this.id || this.setAttribute("id", t), this.innerHTML = `
 | |
|                     <style>
 | |
|                         .${C} { display: block !important; visibility: hidden !important; position: absolute !important; width: 0px !important; height: 0px !important; opacity: 0 !important; pointer-events: none !important; margin: -1px !important; padding: 0 !important; border: 0 !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; }
 | |
|                     </style>
 | |
|                     <div class="${yt} relative">
 | |
|                         <div class="${F} flex flex-wrap gap-1 mb-1 min-h-[38px]" aria-live="polite" tabindex="-1"></div>
 | |
|                         <div class="${W} flex items-center space-x-2">
 | |
|                             <div class="${G} relative rounded-md flex items-center flex-grow">
 | |
|                                 <input type="text"
 | |
|                                        class="${z} w-full outline-none bg-transparent text-sm"
 | |
|                                        placeholder="${this.placeholder}"
 | |
|                                        aria-autocomplete="list"
 | |
|                                        aria-expanded="${this._isOptionsListVisible}"
 | |
|                                        aria-controls="options-list-${t}"
 | |
|                                        autocomplete="off" autocorrect="off" autocapitalize="none" spellcheck="false" role="combobox" />
 | |
|                             </div>
 | |
|                             <button type="button" class="${j} ${this.showCreateButton ? "" : "hidden"}" title="Create new item from input">+</button>
 | |
|                         </div>
 | |
|                         <ul id="options-list-${t}" role="listbox" class="${J} absolute z-20 w-full max-h-60 overflow-y-auto mt-1 hidden"></ul>
 | |
|                         <select multiple name="${this.getAttribute("name") || "mss_default_name"}" id="hidden-select-${t}" class="${C}" aria-hidden="true"></select>
 | |
|                     </div>
 | |
|                 `;
 | |
|   }
 | |
|   _createSelectedItemElement(t) {
 | |
|     const e = this._getItemById(t);
 | |
|     if (!e) return null;
 | |
|     const n = this.selectedItemTemplate.content.cloneNode(!0).firstElementChild, l = n.querySelector('[data-ref="textEl"]'), r = n.querySelector('[data-ref="detailEl"]'), o = n.querySelector('[data-ref="deleteBtn"]');
 | |
|     return l.textContent = e.name, e.additional_data ? (r.textContent = `(${e.additional_data})`, r.classList.remove("hidden")) : r.classList.add("hidden"), o.setAttribute("aria-label", `Remove ${e.name}`), o.dataset.id = t, o.disabled = this.hasAttribute("disabled"), o.addEventListener("click", (d) => {
 | |
|       d.stopPropagation(), this._handleDeleteSelectedItem(t);
 | |
|     }), n;
 | |
|   }
 | |
|   _renderSelectedItems() {
 | |
|     this.selectedItemsContainer && (this.selectedItemsContainer.innerHTML = "", this._value.length === 0 ? this.selectedItemsContainer.innerHTML = `<span class="${Rt}">No items selected</span>` : this._value.forEach((t) => {
 | |
|       const e = this._createSelectedItemElement(t);
 | |
|       e && this.selectedItemsContainer.appendChild(e);
 | |
|     }), this._updateRootElementStateClasses());
 | |
|   }
 | |
|   _createOptionElement(t, e) {
 | |
|     const n = this.optionTemplate.content.cloneNode(!0).firstElementChild, l = n.querySelector('[data-ref="nameEl"]'), r = n.querySelector('[data-ref="detailEl"]');
 | |
|     l.textContent = t.name, r.textContent = t.additional_data ? `(${t.additional_data})` : "", n.dataset.id = t.id, n.setAttribute("aria-selected", String(e === this._highlightedIndex));
 | |
|     const o = `option-${this.id || "mss"}-${t.id}`;
 | |
|     return n.id = o, e === this._highlightedIndex && (n.classList.add(X), this.inputElement && this.inputElement.setAttribute("aria-activedescendant", o)), n;
 | |
|   }
 | |
|   _renderOptionsList() {
 | |
|     if (!(!this.optionsListElement || !this.inputElement)) {
 | |
|       if (this.optionsListElement.innerHTML = "", this.inputElement.removeAttribute("aria-activedescendant"), this._filteredOptions.length === 0 || !this._isOptionsListVisible)
 | |
|         this.optionsListElement.classList.add("hidden"), this.inputElement.setAttribute("aria-expanded", "false");
 | |
|       else {
 | |
|         this.optionsListElement.classList.remove("hidden"), this.inputElement.setAttribute("aria-expanded", "true"), this._filteredOptions.forEach((e, i) => {
 | |
|           const n = this._createOptionElement(e, i);
 | |
|           this.optionsListElement.appendChild(n);
 | |
|         });
 | |
|         const t = this.optionsListElement.querySelector(
 | |
|           `.${X}`
 | |
|         );
 | |
|         t && (t.scrollIntoView({ block: "nearest" }), this.inputElement.setAttribute("aria-activedescendant", t.id));
 | |
|       }
 | |
|       this._updateRootElementStateClasses();
 | |
|     }
 | |
|   }
 | |
|   _handleSelectedItemsContainerClick(t) {
 | |
|     t.target === this.selectedItemsContainer && this.inputElement && !this.inputElement.disabled && this.inputElement.focus();
 | |
|   }
 | |
|   _handleCreateNewButtonClick() {
 | |
|     if (this.hasAttribute("disabled") || !this.showCreateButton) return;
 | |
|     const t = this.inputElement ? this.inputElement.value.trim() : "";
 | |
|     this.dispatchEvent(
 | |
|       new CustomEvent("createnew", {
 | |
|         detail: { value: t },
 | |
|         bubbles: !0,
 | |
|         composed: !0
 | |
|       })
 | |
|     );
 | |
|   }
 | |
|   _handleInput(t) {
 | |
|     const e = t.target.value;
 | |
|     if (e.length === 0)
 | |
|       this._filteredOptions = [], this._isOptionsListVisible = !1;
 | |
|     else {
 | |
|       const i = e.toLowerCase();
 | |
|       this._filteredOptions = this._options.filter((n) => {
 | |
|         if (this._value.includes(n.id)) return !1;
 | |
|         const l = n.name.toLowerCase().includes(i), r = n.additional_data && n.additional_data.toLowerCase().includes(i);
 | |
|         return l || r;
 | |
|       }), this._isOptionsListVisible = this._filteredOptions.length > 0;
 | |
|     }
 | |
|     this._highlightedIndex = this._filteredOptions.length > 0 ? 0 : -1, this._renderOptionsList();
 | |
|   }
 | |
|   _handleKeyDown(t) {
 | |
|     if (!this.inputElement.disabled) {
 | |
|       if (!this._isOptionsListVisible || this._filteredOptions.length === 0) {
 | |
|         t.key === "Escape" && this._hideOptionsList(), (t.key === "ArrowDown" || t.key === "ArrowUp") && this.inputElement.value.length > 0 && this._handleInput({ target: this.inputElement });
 | |
|         return;
 | |
|       }
 | |
|       switch (t.key) {
 | |
|         case "ArrowDown":
 | |
|           t.preventDefault(), this._highlightedIndex = (this._highlightedIndex + 1) % this._filteredOptions.length, this._renderOptionsList();
 | |
|           break;
 | |
|         case "ArrowUp":
 | |
|           t.preventDefault(), this._highlightedIndex = (this._highlightedIndex - 1 + this._filteredOptions.length) % this._filteredOptions.length, this._renderOptionsList();
 | |
|           break;
 | |
|         case "Enter":
 | |
|           t.preventDefault(), this._highlightedIndex > -1 && this._filteredOptions[this._highlightedIndex] && this._selectItem(this._filteredOptions[this._highlightedIndex].id);
 | |
|           break;
 | |
|         case "Escape":
 | |
|           t.preventDefault(), this._hideOptionsList();
 | |
|           break;
 | |
|         case "Tab":
 | |
|           this._hideOptionsList();
 | |
|           break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   _hideOptionsList() {
 | |
|     this._isOptionsListVisible = !1, this._highlightedIndex = -1, this.optionsListElement && this._renderOptionsList();
 | |
|   }
 | |
|   _handleFocus() {
 | |
|     this.inputElement.disabled || (this.inputWrapper && this.inputWrapper.classList.add(K), this.inputElement.value.length > 0 && this._handleInput({ target: this.inputElement }), this._updateRootElementStateClasses());
 | |
|   }
 | |
|   _handleBlur() {
 | |
|     this.inputWrapper && this.inputWrapper.classList.remove(K), this._blurTimeout = setTimeout(() => {
 | |
|       this.contains(document.activeElement) || this._hideOptionsList();
 | |
|     }, 150);
 | |
|   }
 | |
|   _handleOptionMouseDown(t) {
 | |
|     t.preventDefault();
 | |
|   }
 | |
|   _handleOptionClick(t) {
 | |
|     const e = t.target.closest("li[data-id]");
 | |
|     e && e.dataset.id && this._selectItem(e.dataset.id);
 | |
|   }
 | |
|   _selectItem(t) {
 | |
|     t && !this._value.includes(t) && (this.value = [...this._value, t]), this.inputElement && (this.inputElement.value = ""), this._filteredOptions = [], this._hideOptionsList(), this.inputElement && !this.hasAttribute("disabled") && this.inputElement.focus();
 | |
|   }
 | |
|   _handleDeleteSelectedItem(t) {
 | |
|     this.value = this._value.filter((e) => e !== t), this.inputElement && this.inputElement.value && this._handleInput({ target: this.inputElement }), this.inputElement && !this.hasAttribute("disabled") && this.inputElement.focus();
 | |
|   }
 | |
| }
 | |
| u(Z, "formAssociated", !0);
 | |
| const Dt = "filter-list", Ht = "scroll-button", qt = "tool-tip", Ut = "abbrev-tooltips", Ft = "int-link", Vt = "popup-image", Wt = "tab-list", Gt = "filter-pill", Kt = "image-reel", zt = "multi-select-places", jt = "multi-select-simple";
 | |
| customElements.define(Ft, dt);
 | |
| customElements.define(Ut, p);
 | |
| customElements.define(Dt, lt);
 | |
| customElements.define(Ht, at);
 | |
| customElements.define(qt, rt);
 | |
| customElements.define(Vt, ot);
 | |
| customElements.define(Wt, ht);
 | |
| customElements.define(Gt, it);
 | |
| customElements.define(Kt, ct);
 | |
| customElements.define(zt, Y);
 | |
| customElements.define(jt, Z);
 | |
| export {
 | |
|   p as AbbreviationTooltips,
 | |
|   lt as FilterList,
 | |
|   at as ScrollButton
 | |
| };
 | 
