@siteping/widget 0.9.9 → 0.9.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/{chunk-OTJZRTBK.js → chunk-EF2HNCBX.js} +68 -35
- package/dist/chunk-EF2HNCBX.js.map +1 -0
- package/dist/index.global.js +81 -48
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +47 -47
- package/dist/index.js.map +1 -1
- package/dist/panel-47WTS3KH.js +2 -0
- package/dist/{panel-HDPPIATU.js.map → panel-47WTS3KH.js.map} +1 -1
- package/dist/react.js +47 -47
- package/dist/react.js.map +1 -1
- package/dist/schema.d.ts +64 -22
- package/dist/siteping-core.d.ts +7 -4
- package/dist/types.d.ts +103 -25
- package/package.json +1 -1
- package/dist/chunk-OTJZRTBK.js.map +0 -1
- package/dist/panel-HDPPIATU.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {b,c,a,k,v,K,V,l,S,M as M$1,O,Z,W,X,d,P,Q,R,x,I,y,e,u,m,r,n,o,p,q,t,s}from'./chunk-EF2HNCBX.js';var M=class{element;current;opts;onChange;datasetKey;constructor(e){this.opts=e.options,this.current=e.value,this.onChange=e.onChange,this.datasetKey=e.datasetKey,this.element=b("div",{class:`sp-segmented${e.extraClass?` ${e.extraClass}`:""}`,role:"radiogroup"}),this.element.setAttribute("aria-label",e.ariaLabel);for(let t of this.opts){let s=document.createElement("button");s.type="button",s.className=e.modifierPrefix!==void 0?`sp-segmented__btn ${e.modifierPrefix}${t.value}`:"sp-segmented__btn",s.dataset[this.datasetKey]=t.value,s.setAttribute("role","radio");let n=this.current===t.value;if(s.setAttribute("aria-checked",String(n)),s.tabIndex=n?0:-1,n&&s.classList.add("sp-segmented__btn--active"),t.color&&s.style.setProperty("--sp-chip-color",t.color),t.bg&&s.style.setProperty("--sp-chip-bg",t.bg),t.icon){let a$1=b("span",{class:"sp-segmented__icon"});a$1.appendChild(a(t.icon)),s.appendChild(a$1);}let o=b("span",{class:"sp-segmented__label"});c(o,t.label),s.appendChild(o),s.addEventListener("click",()=>this.select(t.value)),s.addEventListener("keydown",a=>this.handleKey(a,t.value)),this.element.appendChild(s);}}select(e){this.current=e,this.syncSelection(),this.onChange(e);}syncSelection(){let e=this.element.querySelectorAll(".sp-segmented__btn");for(let t of e){let s=t.dataset[this.datasetKey]===this.current;t.classList.toggle("sp-segmented__btn--active",s),t.setAttribute("aria-checked",String(s)),t.tabIndex=s?0:-1;}}setOptionVisible(e,t){let s=this.element.querySelector(`[data-${this.kebabKey()}="${e}"]`);return s?(s.style.display=t?"":"none",true):false}get value(){return this.current}focusOption(e){this.element.querySelector(`[data-${this.kebabKey()}="${e}"]`)?.focus();}handleKey(e,t){let s=this.opts.map(l=>l.value).filter(l=>{let c=this.element.querySelector(`[data-${this.kebabKey()}="${l}"]`);return c!==null&&c.style.display!=="none"}),n=s.indexOf(t);if(n<0)return;let o;switch(e.key){case "ArrowLeft":o=(n-1+s.length)%s.length;break;case "ArrowRight":o=(n+1)%s.length;break;case "Home":o=0;break;case "End":o=s.length-1;break;default:return}e.preventDefault();let a=s[o];a!==void 0&&(this.select(a),this.focusOption(a));}kebabKey(){return this.datasetKey.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}};var oe=class{constructor(e,t,s,n,o,a$1,l$1,c$1,v$1){this.colors=t;this.bus=s;this.client=n;this.projectName=o;this.markers=a$1;this.t=l$1;this.locale=c$1;this.shadowRoot=e,this.getScope=v$1?.getScope??(()=>({url:window.location.pathname,urlPattern:null})),this.scopeAnnotationsByUrl=v$1?.scopeAnnotationsByUrl??true,this.root=b("div",{class:"sp-panel"}),this.root.setAttribute("role","complementary"),this.root.setAttribute("aria-label",this.t("panel.ariaLabel")),this.root.setAttribute("aria-hidden","true");let h=b("div",{class:"sp-panel-header"}),u=b("span",{class:"sp-panel-title"});c(u,this.t("panel.title")),this.closeBtn=document.createElement("button"),this.closeBtn.className="sp-panel-close",this.closeBtn.setAttribute("aria-label",this.t("panel.close")),this.closeBtn.appendChild(a(k)),this.closeBtn.addEventListener("click",()=>this.close()),this.deleteAllBtn=document.createElement("button"),this.deleteAllBtn.className="sp-btn-delete-all",this.deleteAllBtn.setAttribute("aria-label",this.t("panel.deleteAll")),this.deleteAllBtn.appendChild(a(v));let m=document.createElement("span");c(m,` ${this.t("panel.deleteAll")}`),this.deleteAllBtn.appendChild(m),this.deleteAllBtn.addEventListener("click",()=>this.confirmDeleteAll()),this.exportBtn=new K(t,()=>this.feedbacks,this.t);let k$1=b("div",{class:"sp-panel-header-right"});k$1.appendChild(this.exportBtn.element),k$1.appendChild(this.deleteAllBtn),k$1.appendChild(this.closeBtn),h.appendChild(u),h.appendChild(k$1),this.stats=new V(t,this.t);let y=b("div",{class:"sp-filters"}),f=b("div",{class:"sp-search-wrap"}),T=a(l);T.setAttribute("class","sp-search-icon"),this.searchInput=document.createElement("input"),this.searchInput.type="text",this.searchInput.className="sp-search",this.searchInput.placeholder=this.t("panel.search"),this.searchInput.setAttribute("aria-label",this.t("panel.searchAria")),this.searchInput.addEventListener("input",()=>{this.searchTimeout&&clearTimeout(this.searchTimeout),this.searchTimeout=setTimeout(()=>this.loadFeedbacks().catch(()=>{}),200);}),f.appendChild(T),f.appendChild(this.searchInput);let g=b("div",{class:"sp-filter-bar"});g.appendChild(this.buildTypeDropdown()),g.appendChild(this.buildStatusSegmented()),g.appendChild(this.buildScopeSegmented()),this.sortControls=new S(t,()=>this.renderList(),this.t),y.appendChild(f),y.appendChild(g),y.appendChild(this.sortControls.element),this.listContainer=b("div",{class:"sp-list"}),this.listContainer.setAttribute("role","list"),this.listContainer.setAttribute("aria-label",this.t("panel.feedbackList")),this.bulk=new M$1(t,{onResolve:i=>this.bulkResolve(i),onDelete:i=>this.bulkDelete(i)},this.t),this.bulk.setListContainer(this.listContainer),this.detail=new O(t,{onBack:()=>this.detail.hide(),onResolve:async i=>{let d=i.status!=="resolved";await this.client.resolveFeedback(i.id,d),await this.loadFeedbacks(),this.detail.hide();},onDelete:async i=>{await this.client.deleteFeedback(i.id),this.bus.emit("feedback:deleted",i.id),await this.loadFeedbacks(),this.detail.hide();},onGoToAnnotation:i=>{if(i.annotations.length>0){let d=i.annotations[0];if(!d)return;window.scrollTo({left:d.scrollX,top:d.scrollY,behavior:"smooth"}),this.markers.pinHighlight(i);}}},this.t,c$1),this.shortcuts=new Z(t,{onNavigate:i=>{let d=W(this.listContainer);X(this.listContainer,i==="down"?d+1:d-1);},onResolve:()=>{let i=this.getFocusedFeedback();if(i&&!this.pendingMutations.has(i.id)){let p=this.listContainer.querySelector(`[data-feedback-id="${CSS.escape(i.id)}"]`)?.querySelector('[data-action="resolve"]');p&&this.toggleResolve(i,p).catch(()=>{});}},onDelete:()=>{let i=this.getFocusedFeedback();if(i&&!this.pendingMutations.has(i.id)){let p=this.listContainer.querySelector(`[data-feedback-id="${CSS.escape(i.id)}"]`)?.querySelector('[data-action="delete"]');p&&this.deleteFeedback(i,p).catch(()=>{});}},onFocusSearch:()=>this.searchInput.focus(),onToggleSelect:()=>{let i=this.getFocusedFeedback();i&&this.bulk.toggle(i.id);}},this.t),this.root.appendChild(h),this.root.appendChild(this.stats.element),this.root.appendChild(y),this.root.appendChild(this.listContainer),this.root.appendChild(this.bulk.barElement),this.root.appendChild(this.detail.element),this.root.appendChild(this.shortcuts.helpOverlay),this.root.appendChild(this.shortcuts.hintButton),e.appendChild(this.root),this.onListClick=i=>{let d=i.target;if(d.closest(".sp-bulk-checkbox"))return;let p=d.closest("[data-action]");if(p){i.stopPropagation();let A=p.closest(".sp-card");if(!A)return;let L=A.dataset.feedbackId,C=this.feedbacks.find(E=>E.id===L);if(!C)return;let B=p.dataset.action;if(B==="expand"){let E=A.querySelector(".sp-card-message");if(!E)return;let I=E.classList.toggle("sp-card-message--expanded");c(p,I?this.t("panel.showLess"):this.t("panel.showMore")),p.setAttribute("aria-expanded",String(I));}else if(B==="resolve"){if(this.pendingMutations.has(C.id))return;let E=p;this.toggleResolve(C,E).catch(()=>{});}else if(B==="delete"){if(this.pendingMutations.has(C.id))return;let E=p;this.deleteFeedback(C,E).catch(()=>{});}return}let w=d.closest(".sp-card");if(w){let A=w.dataset.feedbackId,L=this.feedbacks.find(C=>C.id===A);if(L){let C=this.feedbacks.indexOf(L)+1;this.detail.show(L,C);}}},this.listContainer.addEventListener("click",this.onListClick),this.onListKeydown=i=>{let d=i;if(d.key!=="Enter"&&d.key!==" ")return;let p=d.target,w=p.closest(".sp-card");if(!w||p!==w)return;d.preventDefault();let A=w.dataset.feedbackId,L=this.feedbacks.find(C=>C.id===A);if(L){let C=this.feedbacks.indexOf(L)+1;this.detail.show(L,C);}},this.listContainer.addEventListener("keydown",this.onListKeydown),this.onListMouseover=i=>{let p=i.target.closest(".sp-card");if(!p)return;let w=p.dataset.feedbackId;w&&this.markers.highlight(w);},this.listContainer.addEventListener("mouseover",this.onListMouseover),this.onListMouseout=i=>{let d=i.relatedTarget;d&&this.listContainer.contains(d)||this.markers.highlight("");},this.listContainer.addEventListener("mouseout",this.onListMouseout),this.bus.on("panel:toggle",i=>{i?this.open():this.close();}),e.addEventListener("keydown",i=>{let d=i;if(d.key==="Escape"&&this.isOpen){if(this.detail.isVisible){this.detail.hide();return}this.close();return}if(d.key==="Tab"&&this.isOpen){let p=B=>{let E=B;for(;E&&E!==this.root;){if(E.style.display==="none")return false;E=E.parentElement;}return true},w=Array.from(this.root.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')).filter(B=>p(B)&&!B.hasAttribute("disabled"));if(w.length===0)return;let A=w[0],L=w[w.length-1];if(!A||!L)return;let C=e.activeElement;d.shiftKey&&C===A?(d.preventDefault(),L.focus()):!d.shiftKey&&C===L&&(d.preventDefault(),A.focus());}}),this.onMarkerClick=(i=>{this.scrollToFeedback(i.detail.feedbackId);}),document.addEventListener("sp-marker-click",this.onMarkerClick);}colors;bus;client;projectName;markers;t;locale;root;listContainer;searchInput;closeBtn;deleteAllBtn;activeFilters=new Set(["all"]);typeDropdownBtn;typeDropdownContainer;typeDropdownMenu=null;typeDropdownOutsideHandler=null;statusSegmented;typeOptions;feedbacks=[];currentPage=1;totalFeedbacks=0;isLoadingMore=false;isOpen=false;searchTimeout=null;loadController=null;pendingMutations=new Set;stats;sortControls;bulk;exportBtn;shortcuts;detail;shadowRoot;getScope;scopeAnnotationsByUrl;scopeSegmented;initialScopeFilter="this";onMarkerClick;onListClick;onListKeydown;onListMouseover;onListMouseout;async open(){this.isOpen||(this.isOpen=true,this.root.classList.add("sp-panel--open"),this.root.setAttribute("aria-hidden","false"),this.bus.emit("open"),this.shortcuts.enable(this.shadowRoot),await this.loadFeedbacks(),requestAnimationFrame(()=>{this.searchInput?this.searchInput.focus():this.closeBtn.focus();}));}close(){if(!this.isOpen)return;this.isOpen=false,this.root.classList.remove("sp-panel--open"),this.root.setAttribute("aria-hidden","true"),this.bus.emit("close"),this.shortcuts.disable(),this.detail.hide(),this.root.getRootNode().querySelector(".sp-fab")?.focus();}showLoading(){this.listContainer.replaceChildren();let e=b("div",{class:"sp-loading"});e.setAttribute("role","status"),e.setAttribute("aria-live","polite"),e.setAttribute("aria-label",this.t("panel.loading"));let t=b("div",{class:"sp-spinner"});e.appendChild(t),this.listContainer.appendChild(e);}showError(){this.listContainer.replaceChildren();let e=b("div",{class:"sp-empty"});e.setAttribute("role","status"),e.setAttribute("aria-live","polite");let t=b("div",{class:"sp-empty-text"});c(t,this.t("panel.loadError"));let s=document.createElement("button");s.className="sp-btn-ghost",s.style.marginTop="8px",c(s,this.t("panel.retry")),s.addEventListener("click",()=>this.loadFeedbacks().catch(()=>{})),e.appendChild(t),e.appendChild(s),this.listContainer.appendChild(e);}async loadFeedbacks(){this.loadController?.abort(),this.loadController=new AbortController;let{signal:e}=this.loadController;this.currentPage=1;let t=this.searchInput.value.trim()||void 0,s=this.activeFilters.has("all")?void 0:Array.from(this.activeFilters)[0],n=this.statusSegmented.value,o=n==="all"?void 0:n,a=this.getScope();this.syncScopeAvailability();let l=this.scopeSegmented.value,c={page:1,limit:20};s&&(c.type=s),o&&(c.status=o),t&&(c.search=t),l==="this"?c.url=a.url:l==="template"&&a.urlPattern&&(c.urlPattern=a.urlPattern);let v=this.feedbacks.length>0;v||this.showLoading();try{let{feedbacks:h,total:u}=await this.client.getFeedbacks(this.projectName,c);if(e.aborted)return;this.feedbacks=h,this.totalFeedbacks=u,this.stats.update(h,u),this.bulk.reset(),this.renderList();let m=this.scopeAnnotationsByUrl?h.filter(k=>k.url===a.url):h;this.markers.render(m);}catch(h){if(e.aborted)return;v||this.showError(),this.bus.emit("feedback:error",h instanceof Error?h:new Error(String(h)));}}async loadMoreFeedbacks(){if(this.isLoadingMore)return;this.isLoadingMore=true;let e=this.loadController,t=this.currentPage+1,s=this.searchInput.value.trim()||void 0,n=this.activeFilters.has("all")?void 0:Array.from(this.activeFilters)[0],o=this.statusSegmented.value,a=o==="all"?void 0:o,l=this.getScope(),c=this.scopeSegmented.value,v={page:t,limit:20};n&&(v.type=n),a&&(v.status=a),s&&(v.search=s),c==="this"?v.url=l.url:c==="template"&&l.urlPattern&&(v.urlPattern=l.urlPattern);let h=this.listContainer.querySelector(".sp-btn-load-more"),u;h&&(u=d(h));try{let{feedbacks:m,total:k}=await this.client.getFeedbacks(this.projectName,v);if(e!==this.loadController)return;this.currentPage=t,this.totalFeedbacks=k,this.feedbacks=[...this.feedbacks,...m],this.stats.update(this.feedbacks,k),this.renderList();let y=this.scopeAnnotationsByUrl?this.feedbacks.filter(f=>f.url===l.url):this.feedbacks;this.markers.render(y);}catch(m){u&&u(),this.bus.emit("feedback:error",m instanceof Error?m:new Error(String(m)));}finally{this.isLoadingMore=false;}}renderList(){if(this.listContainer.replaceChildren(),this.feedbacks.length===0){let o=b("div",{class:"sp-empty"});o.setAttribute("role","status"),o.setAttribute("aria-live","polite");let a=b("div",{class:"sp-empty-text"});c(a,this.t("panel.empty")),o.appendChild(a),this.listContainer.appendChild(o);return}let e=P(this.feedbacks,this.sortControls.sortMode),t=e.map(o=>o.id),s=this.bulk.createSelectAllBar(t,this.t("bulk.selectAll"));if(this.listContainer.appendChild(s),this.sortControls.groupByPage){let o=Q(e),a=0;for(let[l,c]of o){let v=R(l,c.length,this.colors);this.listContainer.appendChild(v);let h=b("div",{class:"sp-group-content"});for(let u of c){let m=this.createCard(u,a+1);m.style.setProperty("--sp-card-i",String(a)),h.appendChild(m),a++;}this.listContainer.appendChild(h);}}else e.forEach((o,a)=>{let l=this.createCard(o,a+1);l.style.setProperty("--sp-card-i",String(a)),this.listContainer.appendChild(l);});let n=this.totalFeedbacks-this.feedbacks.length;if(n>0){let o=b("div",{class:"sp-load-more-wrap"}),a=document.createElement("button");a.className="sp-btn-ghost sp-btn-load-more",c(a,this.t("panel.loadMore").replace("{remaining}",String(n))),a.addEventListener("click",()=>this.loadMoreFeedbacks().catch(()=>{})),o.appendChild(a),this.listContainer.appendChild(o);}}createCard(e$1,t){let s=e$1.status==="resolved",n=x(e$1.type,this.colors),o=b("div",{class:`sp-card ${s?"sp-card--resolved":""}`});o.setAttribute("role","listitem"),o.setAttribute("tabindex","0"),o.setAttribute("aria-label",`Feedback #${t}: ${I(e$1.type,this.t)} \u2014 ${e$1.message.slice(0,80)}`),o.dataset.feedbackId=e$1.id;let a$1=b("div",{class:"sp-card-bar"});a$1.style.background=s?"#9ca3af":n;let l=b("div",{class:"sp-card-body"}),c$1=b("div",{class:"sp-card-header"}),v$1=this.bulk.createCheckbox(e$1.id);c$1.appendChild(v$1);let h=b("span",{class:"sp-card-number"});c(h,`#${t}`);let u$1=b("span",{class:"sp-badge"}),m$1=y(e$1.type,this.colors);u$1.style.background=m$1,u$1.style.color=n,c(u$1,I(e$1.type,this.t));let k=b("span",{class:"sp-card-date"});c(k,e(e$1.createdAt,this.locale)),c$1.appendChild(h),c$1.appendChild(u$1),c$1.appendChild(k);let y$1=b("div",{class:"sp-card-message"});c(y$1,e$1.message);let f=document.createElement("button");f.className="sp-card-expand",f.dataset.action="expand",c(f,this.t("panel.showMore")),f.style.display="none",f.setAttribute("aria-expanded","false"),requestAnimationFrame(()=>{y$1.scrollHeight>y$1.clientHeight&&(f.style.display="block");});let T=b("div",{class:"sp-card-footer"}),g=document.createElement("button");if(g.className="sp-btn-resolve",g.dataset.action="resolve",s){g.appendChild(a(u));let p=document.createElement("span");c(p,` ${this.t("panel.reopen")}`),g.appendChild(p);}else {g.appendChild(a(m));let p=document.createElement("span");c(p,` ${this.t("panel.resolve")}`),g.appendChild(p);}let i=document.createElement("button");i.className="sp-btn-delete",i.dataset.action="delete",i.appendChild(a(v));let d=document.createElement("span");return c(d,` ${this.t("panel.delete")}`),i.appendChild(d),T.appendChild(g),T.appendChild(i),l.appendChild(c$1),l.appendChild(y$1),l.appendChild(f),l.appendChild(T),o.appendChild(a$1),o.appendChild(l),o}async bulkResolve(e){try{await Promise.all(e.map(t=>this.client.resolveFeedback(t,!0))),await this.loadFeedbacks();}catch(t){throw this.bus.emit("feedback:error",t instanceof Error?t:new Error(String(t))),t}}async bulkDelete(e){try{await Promise.all(e.map(t=>this.client.deleteFeedback(t)));for(let t of e)this.bus.emit("feedback:deleted",t);await this.loadFeedbacks();}catch(t){throw this.bus.emit("feedback:error",t instanceof Error?t:new Error(String(t))),t}}async confirmDeleteAll(){if(await this.showConfirmDialog(this.t("panel.deleteAllConfirmTitle"),this.t("panel.deleteAllConfirmMessage"))){this.deleteAllBtn.disabled=true;try{await this.client.deleteAllFeedbacks(this.projectName),this.bus.emit("feedback:all-deleted"),await this.loadFeedbacks();}catch(t){this.bus.emit("feedback:error",t instanceof Error?t:new Error(String(t)));}finally{this.deleteAllBtn.disabled=false;}}}showConfirmDialog(e,t){return new Promise(s=>{let n=b("div",{class:"sp-confirm-backdrop"}),o=`sp-confirm-title-${Date.now()}`,a=`sp-confirm-msg-${Date.now()}`,l=b("div",{class:"sp-confirm-dialog"});l.setAttribute("role","alertdialog"),l.setAttribute("aria-modal","true"),l.setAttribute("aria-labelledby",o),l.setAttribute("aria-describedby",a);let c$1=b("div",{class:"sp-confirm-title"});c$1.id=o,c(c$1,e);let v=b("div",{class:"sp-confirm-message"});v.id=a,c(v,t);let h=b("div",{class:"sp-confirm-actions"}),u=document.createElement("button");u.type="button",u.className="sp-btn-ghost",c(u,this.t("panel.cancel"));let m=document.createElement("button");m.type="button",m.className="sp-btn-danger",c(m,this.t("panel.confirmDelete"));let k=false,y=T=>{k||(k=true,n.removeEventListener("keydown",f),n.style.opacity="0",l.style.transform="translateY(8px) scale(0.97)",setTimeout(()=>{n.remove(),s(T);},200));},f=T=>{let g=T;if(g.key==="Escape"){y(false);return}g.key==="Tab"&&(g.preventDefault(),n.getRootNode().activeElement===u?m.focus():u.focus());};n.addEventListener("keydown",f),u.addEventListener("click",()=>y(false)),m.addEventListener("click",()=>y(true)),n.addEventListener("click",T=>{T.target===n&&y(false);}),h.appendChild(u),h.appendChild(m),l.appendChild(c$1),l.appendChild(v),l.appendChild(h),n.appendChild(l),this.root.getRootNode()instanceof ShadowRoot?this.root.getRootNode().appendChild(n):this.root.appendChild(n),requestAnimationFrame(()=>{n.style.opacity="1",l.style.transform="translateY(0) scale(1)",u.focus();});})}async deleteFeedback(e,t){this.pendingMutations.add(e.id);let s=d(t);try{await this.client.deleteFeedback(e.id),this.bus.emit("feedback:deleted",e.id),await this.loadFeedbacks();}catch(n){s(),this.bus.emit("feedback:error",n instanceof Error?n:new Error(String(n)));}finally{this.pendingMutations.delete(e.id);}}async toggleResolve(e,t){this.pendingMutations.add(e.id);let s=d(t);try{let n=e.status!=="resolved";await this.client.resolveFeedback(e.id,n),await this.loadFeedbacks();}catch(n){s(),this.bus.emit("feedback:error",n instanceof Error?n:new Error(String(n)));}finally{this.pendingMutations.delete(e.id);}}buildTypeDropdown(){return this.typeOptions=[{value:"all",label:this.t("panel.filterAll"),icon:r,color:this.colors.accent,bg:this.colors.accentLight},{value:"question",label:this.t("type.question"),icon:n,color:this.colors.typeQuestion,bg:this.colors.typeQuestionBg},{value:"change",label:this.t("type.change"),icon:o,color:this.colors.typeChange,bg:this.colors.typeChangeBg},{value:"bug",label:this.t("type.bug"),icon:p,color:this.colors.typeBug,bg:this.colors.typeBugBg},{value:"other",label:this.t("type.other"),icon:q,color:this.colors.typeOther,bg:this.colors.typeOtherBg}],this.typeDropdownContainer=b("div",{class:"sp-filter-dropdown"}),this.typeDropdownBtn=document.createElement("button"),this.typeDropdownBtn.type="button",this.typeDropdownBtn.className="sp-filter-dropdown-btn",this.typeDropdownBtn.setAttribute("aria-haspopup","listbox"),this.typeDropdownBtn.setAttribute("aria-expanded","false"),this.renderTypeDropdownTrigger(),this.typeDropdownBtn.addEventListener("click",e=>{e.stopPropagation(),this.typeDropdownMenu?this.closeTypeDropdown():this.openTypeDropdown();}),this.typeDropdownContainer.appendChild(this.typeDropdownBtn),this.typeDropdownContainer}renderTypeDropdownTrigger(){let e=this.typeOptions.find(l=>this.activeFilters.has(l.value))??this.typeOptions[0];if(!e)return;this.typeDropdownBtn.replaceChildren(),this.typeDropdownBtn.style.setProperty("--sp-chip-color",e.color),this.typeDropdownBtn.style.setProperty("--sp-chip-bg",e.bg),this.typeDropdownBtn.dataset.filter=e.value,this.typeDropdownBtn.classList.toggle("sp-filter-dropdown-btn--filtered",e.value!=="all"),this.typeDropdownBtn.setAttribute("aria-label",`${this.t("type.label")}: ${e.label}`);let t$1=b("span",{class:"sp-filter-dropdown-btn__icon"});t$1.appendChild(a(e.icon)),this.typeDropdownBtn.appendChild(t$1);let s=b("span",{class:"sp-filter-dropdown-btn__label"}),n=b("span",{class:"sp-filter-dropdown-btn__prefix"});c(n,this.t("type.label"));let o=b("span",{class:"sp-filter-dropdown-btn__value"});c(o,e.label),s.appendChild(n),s.appendChild(o),this.typeDropdownBtn.appendChild(s);let a$1=b("span",{class:"sp-filter-dropdown-btn__chevron"});a$1.appendChild(a(t)),this.typeDropdownBtn.appendChild(a$1);}openTypeDropdown(){this.typeDropdownMenu=b("div",{class:"sp-filter-dropdown-menu"}),this.typeDropdownMenu.setAttribute("role","listbox"),this.typeDropdownMenu.setAttribute("aria-label",this.t("type.label")),this.typeDropdownBtn.setAttribute("aria-expanded","true");for(let e of this.typeOptions){let t=document.createElement("button");t.type="button";let s=this.activeFilters.has(e.value);t.className=`sp-filter-dropdown-option${s?" sp-filter-dropdown-option--active":""}`,t.style.setProperty("--sp-chip-color",e.color),t.style.setProperty("--sp-chip-bg",e.bg),t.dataset.filter=e.value,t.setAttribute("role","option"),t.setAttribute("aria-selected",String(s));let n=b("span",{class:"sp-filter-dropdown-option__icon"});n.appendChild(a(e.icon)),t.appendChild(n);let o=b("span",{class:"sp-filter-dropdown-option__label"});if(c(o,e.label),t.appendChild(o),s){let a$1=b("span",{class:"sp-filter-dropdown-option__check"});a$1.appendChild(a(m)),t.appendChild(a$1);}t.addEventListener("click",a=>{a.stopPropagation(),this.selectTypeFilter(e.value);}),this.typeDropdownMenu.appendChild(t);}this.typeDropdownContainer.appendChild(this.typeDropdownMenu),requestAnimationFrame(()=>{this.typeDropdownOutsideHandler=e=>{this.typeDropdownMenu&&!this.typeDropdownContainer.contains(e.target)&&this.closeTypeDropdown();},document.addEventListener("click",this.typeDropdownOutsideHandler,true);}),this.typeDropdownMenu.addEventListener("keydown",e=>{e.key==="Escape"&&(this.closeTypeDropdown(),this.typeDropdownBtn.focus());});}closeTypeDropdown(){this.typeDropdownMenu&&(this.typeDropdownMenu.remove(),this.typeDropdownMenu=null),this.typeDropdownBtn.setAttribute("aria-expanded","false"),this.typeDropdownOutsideHandler&&(document.removeEventListener("click",this.typeDropdownOutsideHandler,true),this.typeDropdownOutsideHandler=null);}selectTypeFilter(e){this.activeFilters.clear(),this.activeFilters.add(e),this.renderTypeDropdownTrigger(),this.closeTypeDropdown(),this.loadFeedbacks().catch(()=>{});}buildStatusSegmented(){return this.statusSegmented=new M({options:[{value:"all",label:this.t("panel.statusAll"),icon:r,color:this.colors.accent,bg:this.colors.accentLight},{value:"open",label:this.t("panel.statusOpen"),icon:s,color:this.colors.statusOpen,bg:this.colors.statusOpenBg},{value:"resolved",label:this.t("panel.statusResolved"),icon:m,color:this.colors.statusResolved,bg:this.colors.statusResolvedBg}],value:"all",onChange:()=>{this.loadFeedbacks().catch(()=>{});},ariaLabel:this.t("status.label"),datasetKey:"statusFilter",modifierPrefix:"sp-segmented__btn--"}),this.statusSegmented.element}buildScopeSegmented(){return this.scopeSegmented=new M({options:[{value:"this",label:this.t("scope.thisPage")},{value:"template",label:this.t("scope.thisType")},{value:"all",label:this.t("scope.all")}],value:this.initialScopeFilter,onChange:()=>{this.loadFeedbacks().catch(()=>{});},ariaLabel:this.t("scope.label"),datasetKey:"scopeFilter",modifierPrefix:"sp-segmented__btn--scope-",extraClass:"sp-segmented--scope"}),this.syncScopeAvailability(),this.scopeSegmented.element}syncScopeAvailability(){if(!this.scopeSegmented)return;let t=!!this.getScope().urlPattern;this.scopeSegmented.setOptionVisible("template",t),!t&&this.scopeSegmented.value==="template"&&this.scopeSegmented.select("this");}getFocusedFeedback(){let e=W(this.listContainer);if(e<0)return;let t=this.listContainer.querySelectorAll(".sp-card")[e];if(t)return this.feedbacks.find(s=>s.id===t.dataset.feedbackId)}scrollToFeedback(e){let t=CSS.escape(e),s=this.listContainer.querySelector(`[data-feedback-id="${t}"]`);s&&(s.scrollIntoView({behavior:"smooth",block:"center"}),s.classList.add("sp-anim-flash"),s.addEventListener("animationend",()=>{s.classList.remove("sp-anim-flash");},{once:true}));}async refresh(){this.isOpen&&await this.loadFeedbacks();}get isCurrentlyOpen(){return this.isOpen}destroy(){this.loadController?.abort(),this.searchTimeout&&clearTimeout(this.searchTimeout),this.listContainer.removeEventListener("click",this.onListClick),this.listContainer.removeEventListener("keydown",this.onListKeydown),this.listContainer.removeEventListener("mouseover",this.onListMouseover),this.listContainer.removeEventListener("mouseout",this.onListMouseout),document.removeEventListener("sp-marker-click",this.onMarkerClick),this.closeTypeDropdown(),this.sortControls.destroy(),this.bulk.destroy(),this.exportBtn.destroy(),this.shortcuts.destroy(),this.detail.destroy(),this.root.remove();}};export{oe as Panel};//# sourceMappingURL=panel-47WTS3KH.js.map
|
|
2
|
+
//# sourceMappingURL=panel-47WTS3KH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/segmented-control.ts","../src/panel.ts"],"names":["SegmentedControl","config","el","option","btn","isActive","iconWrap","parseSvg","labelEl","setText","e","value","buttons","visible","current","visibleValues","o","v","idx","nextIdx","next","m","Panel","shadowRoot","colors","bus","client","projectName","markers","t","locale","pageScopeOptions","header","title","ICON_CLOSE","ICON_TRASH","deleteAllLabel","ExportButton","headerRight","PanelStats","filters","searchWrap","searchIcon","ICON_SEARCH","filterBar","PanelSortControls","BulkActions","ids","DetailView","fb","newResolved","ann","KeyboardShortcuts","dir","getFocusedCardIndex","focusCardByIndex","target","actionEl","card","feedbackId","feedback","f","action","message","isExpanded","number","ke","open","isVisible","cur","focusable","first","last","active","loading","spinner","empty","text","retryBtn","signal","search","typeFilter","currentStatus","statusFilter","scope","currentScope","options","hasContent","feedbacks","total","markerFeedbacks","error","controller","nextPage","loadMoreBtn","restoreBtn","setButtonLoading","emptyText","sorted","sortFeedbacks","feedbackIds","selectAllBar","groups","groupFeedbacksByPage","globalIndex","pagePath","groupFeedbacks","groupHeader","createPageGroupHeader","groupContent","index","remaining","loadMoreWrap","isResolved","typeColor","getTypeColor","getTypeLabel","bar","body","checkbox","num","badge","typeBg","getTypeBgColor","date","formatRelativeDate","expandBtn","footer","resolveBtn","ICON_UNDO","span","ICON_CHECK","deleteBtn","deleteBtnLabel","id","resolve","backdrop","titleId","messageId","dialog","titleEl","messageEl","btnRow","cancelBtn","confirmBtn","closed","close","result","onKeydown","restore","ICON_LAYERS","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","labelWrap","prefix","chevron","ICON_CHEVRON_DOWN","item","checkWrap","ICON_DOT_OPEN","showTemplate","escapedId"],"mappings":"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","file":"panel-HDPPIATU.js","sourcesContent":["/**\n * Accessible segmented (radiogroup) control.\n *\n * Replaces the near-identical `buildStatusSegmented` / `buildScopeSegmented`\n * pairs that previously lived inline in `panel.ts`: keyboard navigation\n * (ArrowLeft/Right, Home/End), aria-checked toggling, `tabIndex` roving,\n * and optional icon+colour decoration.\n *\n * Visibility filtering — needed by the scope control which hides the\n * \"this type\" option when there is no urlPattern — is handled by\n * `setOptionVisible(value, visible)` and is respected by keyboard\n * navigation so users can't focus a hidden option via arrow keys.\n */\n\nimport { el, parseSvg, setText } from \"../dom-utils.js\";\n\n/**\n * Visual decoration for a segmented option.\n * Both fields are optional: scope options omit them entirely.\n */\nexport interface SegmentedDecoration {\n icon?: string;\n color?: string;\n bg?: string;\n}\n\nexport interface SegmentedOption<T extends string> extends SegmentedDecoration {\n value: T;\n label: string;\n}\n\nexport interface SegmentedControlConfig<T extends string> {\n /** Options to render — order is preserved. */\n options: ReadonlyArray<SegmentedOption<T>>;\n /** Initial selected value — must appear in `options`. */\n value: T;\n /** Called whenever selection changes (click or keyboard). */\n onChange: (value: T) => void;\n /** Accessible label exposed via `aria-label` on the radiogroup. */\n ariaLabel: string;\n /** Extra CSS class appended to the wrapper (e.g. `sp-segmented--scope`). */\n extraClass?: string;\n /** dataset attribute name used per-button, e.g. `statusFilter` → `data-status-filter`. */\n datasetKey: string;\n /** Class prefix used for per-option modifier, e.g. `sp-segmented__btn--` + option.value. */\n modifierPrefix?: string;\n}\n\n/**\n * Build a segmented (radiogroup) control. Returns both the root element and\n * the imperative API for updating selection / visibility from outside —\n * Panel needs the latter when scope availability changes between SPA\n * navigations.\n */\nexport class SegmentedControl<T extends string> {\n readonly element: HTMLElement;\n private current: T;\n private readonly opts: ReadonlyArray<SegmentedOption<T>>;\n private readonly onChange: (value: T) => void;\n private readonly datasetKey: string;\n\n constructor(config: SegmentedControlConfig<T>) {\n this.opts = config.options;\n this.current = config.value;\n this.onChange = config.onChange;\n this.datasetKey = config.datasetKey;\n\n this.element = el(\"div\", {\n class: `sp-segmented${config.extraClass ? ` ${config.extraClass}` : \"\"}`,\n role: \"radiogroup\",\n });\n this.element.setAttribute(\"aria-label\", config.ariaLabel);\n\n for (const option of this.opts) {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className =\n config.modifierPrefix !== undefined\n ? `sp-segmented__btn ${config.modifierPrefix}${option.value}`\n : \"sp-segmented__btn\";\n btn.dataset[this.datasetKey] = option.value;\n btn.setAttribute(\"role\", \"radio\");\n const isActive = this.current === option.value;\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n if (isActive) btn.classList.add(\"sp-segmented__btn--active\");\n if (option.color) btn.style.setProperty(\"--sp-chip-color\", option.color);\n if (option.bg) btn.style.setProperty(\"--sp-chip-bg\", option.bg);\n\n if (option.icon) {\n const iconWrap = el(\"span\", { class: \"sp-segmented__icon\" });\n iconWrap.appendChild(parseSvg(option.icon));\n btn.appendChild(iconWrap);\n }\n\n const labelEl = el(\"span\", { class: \"sp-segmented__label\" });\n setText(labelEl, option.label);\n btn.appendChild(labelEl);\n\n btn.addEventListener(\"click\", () => this.select(option.value));\n btn.addEventListener(\"keydown\", (e) => this.handleKey(e, option.value));\n\n this.element.appendChild(btn);\n }\n }\n\n /** Imperatively change the selected option (also fires `onChange`). */\n select(value: T): void {\n this.current = value;\n this.syncSelection();\n this.onChange(value);\n }\n\n /** Apply selection-only DOM updates without firing `onChange`. Useful on init refresh. */\n private syncSelection(): void {\n const buttons = this.element.querySelectorAll<HTMLButtonElement>(\".sp-segmented__btn\");\n for (const btn of buttons) {\n const isActive = btn.dataset[this.datasetKey] === this.current;\n btn.classList.toggle(\"sp-segmented__btn--active\", isActive);\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n }\n }\n\n /**\n * Show / hide a specific option. Hidden options are skipped during keyboard\n * navigation. Returns true when an option was actually toggled.\n */\n setOptionVisible(value: T, visible: boolean): boolean {\n const btn = this.element.querySelector<HTMLButtonElement>(`[data-${this.kebabKey()}=\"${value}\"]`);\n if (!btn) return false;\n btn.style.display = visible ? \"\" : \"none\";\n return true;\n }\n\n /** Current selection. */\n get value(): T {\n return this.current;\n }\n\n /** Focus the button matching `value`, if it exists. */\n focusOption(value: T): void {\n const btn = this.element.querySelector<HTMLButtonElement>(`[data-${this.kebabKey()}=\"${value}\"]`);\n btn?.focus();\n }\n\n private handleKey(e: KeyboardEvent, current: T): void {\n const visibleValues = this.opts\n .map((o) => o.value)\n .filter((v) => {\n const btn = this.element.querySelector<HTMLButtonElement>(`[data-${this.kebabKey()}=\"${v}\"]`);\n return btn !== null && btn.style.display !== \"none\";\n });\n const idx = visibleValues.indexOf(current);\n if (idx < 0) return;\n\n let nextIdx: number;\n switch (e.key) {\n case \"ArrowLeft\":\n nextIdx = (idx - 1 + visibleValues.length) % visibleValues.length;\n break;\n case \"ArrowRight\":\n nextIdx = (idx + 1) % visibleValues.length;\n break;\n case \"Home\":\n nextIdx = 0;\n break;\n case \"End\":\n nextIdx = visibleValues.length - 1;\n break;\n default:\n return;\n }\n e.preventDefault();\n const next = visibleValues[nextIdx];\n if (next === undefined) return;\n this.select(next);\n this.focusOption(next);\n }\n\n /** Convert datasetKey (\"statusFilter\") to its DOM attribute form (\"status-filter\"). */\n private kebabKey(): string {\n return this.datasetKey.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);\n }\n}\n","import type { FeedbackResponse, FeedbackStatus, FeedbackType, PageScope } from \"@siteping/core\";\nimport type { GetFeedbacksOptions, WidgetClient } from \"./api-client.js\";\nimport { SegmentedControl } from \"./components/segmented-control.js\";\nimport { PAGE_SIZE } from \"./constants.js\";\nimport { el, formatRelativeDate, parseSvg, setButtonLoading, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { ExportButton } from \"./export-utils.js\";\nimport { getTypeLabel, type TFunction } from \"./i18n/index.js\";\nimport {\n ICON_BUG,\n ICON_CHANGE,\n ICON_CHECK,\n ICON_CHEVRON_DOWN,\n ICON_CLOSE,\n ICON_DOT_OPEN,\n ICON_LAYERS,\n ICON_OTHER,\n ICON_QUESTION,\n ICON_SEARCH,\n ICON_TRASH,\n ICON_UNDO,\n} from \"./icons.js\";\nimport type { MarkerManager } from \"./markers.js\";\nimport { BulkActions } from \"./panel-bulk.js\";\nimport { DetailView } from \"./panel-detail.js\";\nimport { createPageGroupHeader, groupFeedbacksByPage, PanelSortControls, sortFeedbacks } from \"./panel-sort.js\";\nimport { PanelStats } from \"./panel-stats.js\";\nimport { focusCardByIndex, getFocusedCardIndex, KeyboardShortcuts } from \"./shortcuts.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n/**\n * Side panel (400px) with feedback history, filters, search, stats,\n * sort/group, bulk actions, export, detail view, and keyboard shortcuts.\n *\n * Lives inside the Shadow DOM.\n * Glassmorphism: glass background, staggered card animations,\n * loading states, resolve feedback with disabled state.\n */\nexport class Panel {\n private root: HTMLElement;\n private listContainer: HTMLElement;\n private searchInput: HTMLInputElement;\n private closeBtn: HTMLButtonElement;\n private deleteAllBtn: HTMLButtonElement;\n private activeFilters = new Set<string>([\"all\"]);\n private typeDropdownBtn!: HTMLButtonElement;\n private typeDropdownContainer!: HTMLElement;\n private typeDropdownMenu: HTMLElement | null = null;\n private typeDropdownOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private statusSegmented!: SegmentedControl<\"all\" | FeedbackStatus>;\n private typeOptions!: ReadonlyArray<{ value: string; label: string; icon: string; color: string; bg: string }>;\n private feedbacks: FeedbackResponse[] = [];\n private currentPage = 1;\n private totalFeedbacks = 0;\n private isLoadingMore = false;\n private isOpen = false;\n private searchTimeout: ReturnType<typeof setTimeout> | null = null;\n private loadController: AbortController | null = null;\n /** Tracks feedback IDs with in-flight mutations to prevent spam-click race conditions */\n private pendingMutations = new Set<string>();\n\n // New feature modules\n private readonly stats: PanelStats;\n private readonly sortControls: PanelSortControls;\n private readonly bulk: BulkActions;\n private readonly exportBtn: ExportButton;\n private readonly shortcuts: KeyboardShortcuts;\n private readonly detail: DetailView;\n private readonly shadowRoot: ShadowRoot;\n\n // i18n: t is shared with all submodules.\n\n // Page scope — supplied by launcher so the panel can scope its results to\n // the current page (or template) and filter markers accordingly.\n private readonly getScope: () => PageScope;\n private readonly scopeAnnotationsByUrl: boolean;\n /** \"this\" = current url, \"template\" = url pattern, \"all\" = no scope filter */\n private scopeSegmented!: SegmentedControl<\"this\" | \"template\" | \"all\">;\n /** Cached initial scope value — applied after construction in `buildScopeSegmented`. */\n private readonly initialScopeFilter: \"this\" | \"template\" | \"all\" = \"this\";\n\n constructor(\n shadowRoot: ShadowRoot,\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly client: WidgetClient,\n private readonly projectName: string,\n private readonly markers: MarkerManager,\n private readonly t: TFunction,\n private readonly locale: string,\n pageScopeOptions?: { getScope: () => PageScope; scopeAnnotationsByUrl: boolean },\n ) {\n this.shadowRoot = shadowRoot;\n this.getScope = pageScopeOptions?.getScope ?? (() => ({ url: window.location.pathname, urlPattern: null }));\n this.scopeAnnotationsByUrl = pageScopeOptions?.scopeAnnotationsByUrl ?? true;\n\n this.root = el(\"div\", { class: \"sp-panel\" });\n this.root.setAttribute(\"role\", \"complementary\");\n this.root.setAttribute(\"aria-label\", this.t(\"panel.ariaLabel\"));\n this.root.setAttribute(\"aria-hidden\", \"true\");\n\n // --- Header ---\n const header = el(\"div\", { class: \"sp-panel-header\" });\n const title = el(\"span\", { class: \"sp-panel-title\" });\n setText(title, this.t(\"panel.title\"));\n\n this.closeBtn = document.createElement(\"button\");\n this.closeBtn.className = \"sp-panel-close\";\n this.closeBtn.setAttribute(\"aria-label\", this.t(\"panel.close\"));\n this.closeBtn.appendChild(parseSvg(ICON_CLOSE));\n this.closeBtn.addEventListener(\"click\", () => this.close());\n\n this.deleteAllBtn = document.createElement(\"button\");\n this.deleteAllBtn.className = \"sp-btn-delete-all\";\n this.deleteAllBtn.setAttribute(\"aria-label\", this.t(\"panel.deleteAll\"));\n this.deleteAllBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteAllLabel = document.createElement(\"span\");\n setText(deleteAllLabel, ` ${this.t(\"panel.deleteAll\")}`);\n this.deleteAllBtn.appendChild(deleteAllLabel);\n this.deleteAllBtn.addEventListener(\"click\", () => this.confirmDeleteAll());\n\n // Export button\n this.exportBtn = new ExportButton(colors, () => this.feedbacks, this.t);\n\n const headerRight = el(\"div\", { class: \"sp-panel-header-right\" });\n headerRight.appendChild(this.exportBtn.element);\n headerRight.appendChild(this.deleteAllBtn);\n headerRight.appendChild(this.closeBtn);\n\n header.appendChild(title);\n header.appendChild(headerRight);\n\n // --- Stats ---\n this.stats = new PanelStats(colors, this.t);\n\n // --- Filters ---\n const filters = el(\"div\", { class: \"sp-filters\" });\n\n // Search\n const searchWrap = el(\"div\", { class: \"sp-search-wrap\" });\n const searchIcon = parseSvg(ICON_SEARCH);\n searchIcon.setAttribute(\"class\", \"sp-search-icon\");\n this.searchInput = document.createElement(\"input\");\n this.searchInput.type = \"text\";\n this.searchInput.className = \"sp-search\";\n this.searchInput.placeholder = this.t(\"panel.search\");\n this.searchInput.setAttribute(\"aria-label\", this.t(\"panel.searchAria\"));\n this.searchInput.addEventListener(\"input\", () => {\n if (this.searchTimeout) clearTimeout(this.searchTimeout);\n this.searchTimeout = setTimeout(() => this.loadFeedbacks().catch(() => {}), 200);\n });\n searchWrap.appendChild(searchIcon);\n searchWrap.appendChild(this.searchInput);\n\n // Filter bar (type dropdown + status segmented + scope segmented).\n // The scope control gives users a fast way to widen results to \"this type\n // of page\" or \"all pages\" when the host provides a route template.\n const filterBar = el(\"div\", { class: \"sp-filter-bar\" });\n filterBar.appendChild(this.buildTypeDropdown());\n filterBar.appendChild(this.buildStatusSegmented());\n filterBar.appendChild(this.buildScopeSegmented());\n\n // Sort controls\n this.sortControls = new PanelSortControls(colors, () => this.renderList(), this.t);\n\n filters.appendChild(searchWrap);\n filters.appendChild(filterBar);\n filters.appendChild(this.sortControls.element);\n\n // --- List ---\n this.listContainer = el(\"div\", { class: \"sp-list\" });\n this.listContainer.setAttribute(\"role\", \"list\");\n this.listContainer.setAttribute(\"aria-label\", this.t(\"panel.feedbackList\"));\n\n // --- Bulk Actions ---\n this.bulk = new BulkActions(\n colors,\n {\n onResolve: (ids) => this.bulkResolve(ids),\n onDelete: (ids) => this.bulkDelete(ids),\n },\n this.t,\n );\n this.bulk.setListContainer(this.listContainer);\n\n // --- Detail View ---\n this.detail = new DetailView(\n colors,\n {\n onBack: () => this.detail.hide(),\n onResolve: async (fb) => {\n const newResolved = fb.status !== \"resolved\";\n await this.client.resolveFeedback(fb.id, newResolved);\n await this.loadFeedbacks();\n this.detail.hide();\n },\n onDelete: async (fb) => {\n await this.client.deleteFeedback(fb.id);\n this.bus.emit(\"feedback:deleted\", fb.id);\n await this.loadFeedbacks();\n this.detail.hide();\n },\n onGoToAnnotation: (fb) => {\n if (fb.annotations.length > 0) {\n const ann = fb.annotations[0];\n if (!ann) return;\n window.scrollTo({ left: ann.scrollX, top: ann.scrollY, behavior: \"smooth\" });\n this.markers.pinHighlight(fb);\n }\n },\n },\n this.t,\n locale,\n );\n\n // --- Keyboard Shortcuts ---\n this.shortcuts = new KeyboardShortcuts(\n colors,\n {\n onNavigate: (dir) => {\n const idx = getFocusedCardIndex(this.listContainer);\n focusCardByIndex(this.listContainer, dir === \"down\" ? idx + 1 : idx - 1);\n },\n onResolve: () => {\n const fb = this.getFocusedFeedback();\n if (fb && !this.pendingMutations.has(fb.id)) {\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${CSS.escape(fb.id)}\"]`);\n const btn = card?.querySelector<HTMLButtonElement>('[data-action=\"resolve\"]');\n if (btn) this.toggleResolve(fb, btn).catch(() => {});\n }\n },\n onDelete: () => {\n const fb = this.getFocusedFeedback();\n if (fb && !this.pendingMutations.has(fb.id)) {\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${CSS.escape(fb.id)}\"]`);\n const btn = card?.querySelector<HTMLButtonElement>('[data-action=\"delete\"]');\n if (btn) this.deleteFeedback(fb, btn).catch(() => {});\n }\n },\n onFocusSearch: () => this.searchInput.focus(),\n onToggleSelect: () => {\n const fb = this.getFocusedFeedback();\n if (fb) this.bulk.toggle(fb.id);\n },\n },\n this.t,\n );\n\n // --- Assemble DOM ---\n this.root.appendChild(header);\n this.root.appendChild(this.stats.element);\n this.root.appendChild(filters);\n this.root.appendChild(this.listContainer);\n this.root.appendChild(this.bulk.barElement);\n this.root.appendChild(this.detail.element);\n this.root.appendChild(this.shortcuts.helpOverlay);\n this.root.appendChild(this.shortcuts.hintButton);\n shadowRoot.appendChild(this.root);\n\n // --- Event delegation on listContainer ---\n\n this.onListClick = (e: Event) => {\n const target = e.target as Element;\n\n // Bulk checkbox clicks are handled by BulkActions, skip\n if (target.closest(\".sp-bulk-checkbox\")) return;\n\n // Action buttons (expand, resolve, delete)\n const actionEl = target.closest<HTMLElement>(\"[data-action]\");\n if (actionEl) {\n e.stopPropagation();\n const card = actionEl.closest<HTMLElement>(\".sp-card\");\n if (!card) return;\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (!feedback) return;\n\n const action = actionEl.dataset.action;\n if (action === \"expand\") {\n const message = card.querySelector<HTMLElement>(\".sp-card-message\");\n if (!message) return;\n const isExpanded = message.classList.toggle(\"sp-card-message--expanded\");\n setText(actionEl, isExpanded ? this.t(\"panel.showLess\") : this.t(\"panel.showMore\"));\n actionEl.setAttribute(\"aria-expanded\", String(isExpanded));\n } else if (action === \"resolve\") {\n if (this.pendingMutations.has(feedback.id)) return;\n const btn = actionEl as HTMLButtonElement;\n this.toggleResolve(feedback, btn).catch(() => {});\n } else if (action === \"delete\") {\n if (this.pendingMutations.has(feedback.id)) return;\n const btn = actionEl as HTMLButtonElement;\n this.deleteFeedback(feedback, btn).catch(() => {});\n }\n return;\n }\n\n // Card click → open detail view\n const card = target.closest<HTMLElement>(\".sp-card\");\n if (card) {\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (feedback) {\n const number = this.feedbacks.indexOf(feedback) + 1;\n this.detail.show(feedback, number);\n }\n }\n };\n this.listContainer.addEventListener(\"click\", this.onListClick);\n\n this.onListKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key !== \"Enter\" && ke.key !== \" \") return;\n const target = ke.target as Element;\n const card = target.closest<HTMLElement>(\".sp-card\");\n // Only activate if the card itself is focused, not a button inside it\n if (!card || target !== card) return;\n ke.preventDefault();\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (feedback) {\n const number = this.feedbacks.indexOf(feedback) + 1;\n this.detail.show(feedback, number);\n }\n };\n this.listContainer.addEventListener(\"keydown\", this.onListKeydown);\n\n // mouseover/mouseout bubble (unlike mouseenter/mouseleave), enabling delegation\n this.onListMouseover = (e: Event) => {\n const target = (e as MouseEvent).target as Element;\n const card = target.closest<HTMLElement>(\".sp-card\");\n if (!card) return;\n const feedbackId = card.dataset.feedbackId;\n if (feedbackId) this.markers.highlight(feedbackId);\n };\n this.listContainer.addEventListener(\"mouseover\", this.onListMouseover);\n\n this.onListMouseout = (e: Event) => {\n const target = (e as MouseEvent).relatedTarget as Element | null;\n // Only clear highlight when leaving all cards (relatedTarget is outside listContainer)\n if (target && this.listContainer.contains(target)) return;\n this.markers.highlight(\"\");\n };\n this.listContainer.addEventListener(\"mouseout\", this.onListMouseout);\n\n // Events\n this.bus.on(\"panel:toggle\", (open) => {\n open ? this.open() : this.close();\n });\n\n // Keyboard handling: Escape to close + focus trap\n shadowRoot.addEventListener(\"keydown\", (e) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\" && this.isOpen) {\n // If detail view is open, close it instead\n if (this.detail.isVisible) {\n this.detail.hide();\n return;\n }\n this.close();\n return;\n }\n if (ke.key === \"Tab\" && this.isOpen) {\n // Filter out non-tabbable elements: those hidden via `display: none`\n // (either on themselves or any ancestor up to this.root) and elements\n // explicitly disabled. Without this filter, the trap can jump to a\n // button inside a closed detail view and effectively swallow the Tab\n // key. We use a walk of style.display rather than `offsetParent`\n // because the latter is unreliable in jsdom (always null without\n // layout) and breaks unit tests.\n const isVisible = (el: HTMLElement): boolean => {\n let cur: HTMLElement | null = el;\n while (cur && cur !== this.root) {\n if (cur.style.display === \"none\") return false;\n cur = cur.parentElement;\n }\n return true;\n };\n const focusable = Array.from(\n this.root.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n ),\n ).filter((el) => isVisible(el) && !el.hasAttribute(\"disabled\"));\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (!first || !last) return;\n const active = (shadowRoot as ShadowRoot).activeElement;\n if (ke.shiftKey && active === first) {\n ke.preventDefault();\n last.focus();\n } else if (!ke.shiftKey && active === last) {\n ke.preventDefault();\n first.focus();\n }\n }\n });\n\n // Listen for marker clicks\n this.onMarkerClick = ((e: CustomEvent) => {\n this.scrollToFeedback(e.detail.feedbackId);\n }) as EventListener;\n document.addEventListener(\"sp-marker-click\", this.onMarkerClick);\n }\n\n private onMarkerClick: EventListener;\n private onListClick: (e: Event) => void;\n private onListKeydown: (e: Event) => void;\n private onListMouseover: (e: Event) => void;\n private onListMouseout: (e: Event) => void;\n\n async open(): Promise<void> {\n if (this.isOpen) return;\n this.isOpen = true;\n this.root.classList.add(\"sp-panel--open\");\n this.root.setAttribute(\"aria-hidden\", \"false\");\n this.bus.emit(\"open\");\n this.shortcuts.enable(this.shadowRoot);\n await this.loadFeedbacks();\n // Move focus into the panel (search input or close button)\n requestAnimationFrame(() => {\n if (this.searchInput) {\n this.searchInput.focus();\n } else {\n this.closeBtn.focus();\n }\n });\n }\n\n close(): void {\n if (!this.isOpen) return;\n this.isOpen = false;\n this.root.classList.remove(\"sp-panel--open\");\n this.root.setAttribute(\"aria-hidden\", \"true\");\n this.bus.emit(\"close\");\n this.shortcuts.disable();\n this.detail.hide();\n // Restore focus to the FAB\n const fab = (this.root.getRootNode() as ShadowRoot).querySelector<HTMLButtonElement>(\".sp-fab\");\n fab?.focus();\n }\n\n private showLoading(): void {\n this.listContainer.replaceChildren();\n const loading = el(\"div\", { class: \"sp-loading\" });\n loading.setAttribute(\"role\", \"status\");\n loading.setAttribute(\"aria-live\", \"polite\");\n loading.setAttribute(\"aria-label\", this.t(\"panel.loading\"));\n const spinner = el(\"div\", { class: \"sp-spinner\" });\n loading.appendChild(spinner);\n this.listContainer.appendChild(loading);\n }\n\n private showError(): void {\n this.listContainer.replaceChildren();\n const empty = el(\"div\", { class: \"sp-empty\" });\n empty.setAttribute(\"role\", \"status\");\n empty.setAttribute(\"aria-live\", \"polite\");\n const text = el(\"div\", { class: \"sp-empty-text\" });\n setText(text, this.t(\"panel.loadError\"));\n const retryBtn = document.createElement(\"button\");\n retryBtn.className = \"sp-btn-ghost\";\n retryBtn.style.marginTop = \"8px\";\n setText(retryBtn, this.t(\"panel.retry\"));\n retryBtn.addEventListener(\"click\", () => this.loadFeedbacks().catch(() => {}));\n empty.appendChild(text);\n empty.appendChild(retryBtn);\n this.listContainer.appendChild(empty);\n }\n\n private async loadFeedbacks(): Promise<void> {\n // Cancel any in-flight request to prevent stale responses from overwriting newer results\n this.loadController?.abort();\n this.loadController = new AbortController();\n const { signal } = this.loadController;\n\n // Reset to page 1 on fresh load (filter/search change)\n this.currentPage = 1;\n\n const search = this.searchInput.value.trim() || undefined;\n const typeFilter = this.activeFilters.has(\"all\") ? undefined : (Array.from(this.activeFilters)[0] as FeedbackType);\n const currentStatus = this.statusSegmented.value;\n const statusFilter = currentStatus === \"all\" ? undefined : currentStatus;\n\n const scope = this.getScope();\n // Refresh scope-filter button visibility based on current scope (SPA nav).\n this.syncScopeAvailability();\n const currentScope = this.scopeSegmented.value;\n const options: GetFeedbacksOptions & { page: number; limit: number } = {\n page: 1,\n limit: PAGE_SIZE,\n };\n if (typeFilter) options.type = typeFilter;\n if (statusFilter) options.status = statusFilter;\n if (search) options.search = search;\n if (currentScope === \"this\") {\n options.url = scope.url;\n } else if (currentScope === \"template\" && scope.urlPattern) {\n options.urlPattern = scope.urlPattern;\n }\n\n // Only show spinner on first load (empty list) — otherwise keep current content visible\n const hasContent = this.feedbacks.length > 0;\n if (!hasContent) this.showLoading();\n\n try {\n const { feedbacks, total } = await this.client.getFeedbacks(this.projectName, options);\n if (signal.aborted) return; // Stale response — a newer request superseded this one\n this.feedbacks = feedbacks;\n this.totalFeedbacks = total;\n this.stats.update(feedbacks, total);\n this.bulk.reset();\n this.renderList();\n // Markers always render only the current-URL slice — even when the panel\n // shows a wider scope (\"template\" or \"all\"), markers stay strictly local\n // so the user never sees out-of-context dots on the page.\n const markerFeedbacks = this.scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === scope.url) : feedbacks;\n this.markers.render(markerFeedbacks);\n } catch (error) {\n if (signal.aborted) return; // Expected abort, not a real error\n if (!hasContent) this.showError();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private async loadMoreFeedbacks(): Promise<void> {\n if (this.isLoadingMore) return;\n this.isLoadingMore = true;\n\n // Capture current controller — if loadFeedbacks() runs while we're in-flight,\n // it replaces the controller, signaling that our results are stale.\n const controller = this.loadController;\n\n const nextPage = this.currentPage + 1;\n const search = this.searchInput.value.trim() || undefined;\n const typeFilter = this.activeFilters.has(\"all\") ? undefined : (Array.from(this.activeFilters)[0] as FeedbackType);\n const currentStatus = this.statusSegmented.value;\n const statusFilter = currentStatus === \"all\" ? undefined : currentStatus;\n\n const scope = this.getScope();\n const currentScope = this.scopeSegmented.value;\n const options: GetFeedbacksOptions & { page: number; limit: number } = {\n page: nextPage,\n limit: PAGE_SIZE,\n };\n if (typeFilter) options.type = typeFilter;\n if (statusFilter) options.status = statusFilter;\n if (search) options.search = search;\n if (currentScope === \"this\") {\n options.url = scope.url;\n } else if (currentScope === \"template\" && scope.urlPattern) {\n options.urlPattern = scope.urlPattern;\n }\n\n // Show spinner on the \"Load more\" button\n const loadMoreBtn = this.listContainer.querySelector<HTMLButtonElement>(\".sp-btn-load-more\");\n let restoreBtn: (() => void) | undefined;\n if (loadMoreBtn) restoreBtn = setButtonLoading(loadMoreBtn);\n\n try {\n const { feedbacks, total } = await this.client.getFeedbacks(this.projectName, options);\n if (controller !== this.loadController) return; // Filter/search changed — discard stale page\n this.currentPage = nextPage;\n this.totalFeedbacks = total;\n this.feedbacks = [...this.feedbacks, ...feedbacks];\n this.stats.update(this.feedbacks, total);\n this.renderList();\n const markerFeedbacks = this.scopeAnnotationsByUrl\n ? this.feedbacks.filter((f) => f.url === scope.url)\n : this.feedbacks;\n this.markers.render(markerFeedbacks);\n } catch (error) {\n if (restoreBtn) restoreBtn();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.isLoadingMore = false;\n }\n }\n\n private renderList(): void {\n this.listContainer.replaceChildren();\n\n if (this.feedbacks.length === 0) {\n const empty = el(\"div\", { class: \"sp-empty\" });\n empty.setAttribute(\"role\", \"status\");\n empty.setAttribute(\"aria-live\", \"polite\");\n const emptyText = el(\"div\", { class: \"sp-empty-text\" });\n setText(emptyText, this.t(\"panel.empty\"));\n empty.appendChild(emptyText);\n this.listContainer.appendChild(empty);\n return;\n }\n\n // Apply sorting\n const sorted = sortFeedbacks(this.feedbacks, this.sortControls.sortMode);\n\n // Select all bar\n const feedbackIds = sorted.map((f) => f.id);\n const selectAllBar = this.bulk.createSelectAllBar(feedbackIds, this.t(\"bulk.selectAll\"));\n this.listContainer.appendChild(selectAllBar);\n\n if (this.sortControls.groupByPage) {\n // Group by page rendering\n const groups = groupFeedbacksByPage(sorted);\n let globalIndex = 0;\n for (const [pagePath, groupFeedbacks] of groups) {\n const groupHeader = createPageGroupHeader(pagePath, groupFeedbacks.length, this.colors);\n this.listContainer.appendChild(groupHeader);\n\n const groupContent = el(\"div\", { class: \"sp-group-content\" });\n for (const feedback of groupFeedbacks) {\n const card = this.createCard(feedback, globalIndex + 1);\n card.style.setProperty(\"--sp-card-i\", String(globalIndex));\n groupContent.appendChild(card);\n globalIndex++;\n }\n this.listContainer.appendChild(groupContent);\n }\n } else {\n // Flat list rendering\n sorted.forEach((feedback, index) => {\n const card = this.createCard(feedback, index + 1);\n card.style.setProperty(\"--sp-card-i\", String(index));\n this.listContainer.appendChild(card);\n });\n }\n\n // \"Load more\" button when there are remaining feedbacks\n const remaining = this.totalFeedbacks - this.feedbacks.length;\n if (remaining > 0) {\n const loadMoreWrap = el(\"div\", { class: \"sp-load-more-wrap\" });\n const loadMoreBtn = document.createElement(\"button\");\n loadMoreBtn.className = \"sp-btn-ghost sp-btn-load-more\";\n setText(loadMoreBtn, this.t(\"panel.loadMore\").replace(\"{remaining}\", String(remaining)));\n loadMoreBtn.addEventListener(\"click\", () => this.loadMoreFeedbacks().catch(() => {}));\n loadMoreWrap.appendChild(loadMoreBtn);\n this.listContainer.appendChild(loadMoreWrap);\n }\n }\n\n private createCard(feedback: FeedbackResponse, number: number): HTMLElement {\n const isResolved = feedback.status === \"resolved\";\n const typeColor = getTypeColor(feedback.type, this.colors);\n\n const card = el(\"div\", {\n class: `sp-card ${isResolved ? \"sp-card--resolved\" : \"\"}`,\n });\n card.setAttribute(\"role\", \"listitem\");\n card.setAttribute(\"tabindex\", \"0\");\n card.setAttribute(\n \"aria-label\",\n `Feedback #${number}: ${getTypeLabel(feedback.type, this.t)} — ${feedback.message.slice(0, 80)}`,\n );\n card.dataset.feedbackId = feedback.id;\n\n // Color bar\n const bar = el(\"div\", { class: \"sp-card-bar\" });\n bar.style.background = isResolved ? \"#9ca3af\" : typeColor;\n\n // Body\n const body = el(\"div\", { class: \"sp-card-body\" });\n\n // Header: checkbox + #number + badge + date\n const header = el(\"div\", { class: \"sp-card-header\" });\n\n // Bulk checkbox — inline in the header row\n const checkbox = this.bulk.createCheckbox(feedback.id);\n header.appendChild(checkbox);\n\n const num = el(\"span\", { class: \"sp-card-number\" });\n setText(num, `#${number}`);\n\n const badge = el(\"span\", { class: \"sp-badge\" });\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n badge.style.background = typeBg;\n badge.style.color = typeColor;\n setText(badge, getTypeLabel(feedback.type, this.t));\n\n const date = el(\"span\", { class: \"sp-card-date\" });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(num);\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message\n const message = el(\"div\", { class: \"sp-card-message\" });\n setText(message, feedback.message);\n\n // Expand button\n const expandBtn = document.createElement(\"button\");\n expandBtn.className = \"sp-card-expand\";\n expandBtn.dataset.action = \"expand\";\n setText(expandBtn, this.t(\"panel.showMore\"));\n expandBtn.style.display = \"none\";\n expandBtn.setAttribute(\"aria-expanded\", \"false\");\n\n // Check if text is clamped (after render)\n requestAnimationFrame(() => {\n if (message.scrollHeight > message.clientHeight) {\n expandBtn.style.display = \"block\";\n }\n });\n\n // Footer: resolve button\n const footer = el(\"div\", { class: \"sp-card-footer\" });\n\n const resolveBtn = document.createElement(\"button\");\n resolveBtn.className = \"sp-btn-resolve\";\n resolveBtn.dataset.action = \"resolve\";\n if (isResolved) {\n resolveBtn.appendChild(parseSvg(ICON_UNDO));\n const span = document.createElement(\"span\");\n setText(span, ` ${this.t(\"panel.reopen\")}`);\n resolveBtn.appendChild(span);\n } else {\n resolveBtn.appendChild(parseSvg(ICON_CHECK));\n const span = document.createElement(\"span\");\n setText(span, ` ${this.t(\"panel.resolve\")}`);\n resolveBtn.appendChild(span);\n }\n\n const deleteBtn = document.createElement(\"button\");\n deleteBtn.className = \"sp-btn-delete\";\n deleteBtn.dataset.action = \"delete\";\n deleteBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteBtnLabel = document.createElement(\"span\");\n setText(deleteBtnLabel, ` ${this.t(\"panel.delete\")}`);\n deleteBtn.appendChild(deleteBtnLabel);\n\n footer.appendChild(resolveBtn);\n footer.appendChild(deleteBtn);\n\n body.appendChild(header);\n body.appendChild(message);\n body.appendChild(expandBtn);\n body.appendChild(footer);\n\n card.appendChild(bar);\n card.appendChild(body);\n\n return card;\n }\n\n // ---------------------------------------------------------------------------\n // Bulk operations\n // ---------------------------------------------------------------------------\n\n private async bulkResolve(ids: string[]): Promise<void> {\n try {\n await Promise.all(ids.map((id) => this.client.resolveFeedback(id, true)));\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n\n private async bulkDelete(ids: string[]): Promise<void> {\n try {\n await Promise.all(ids.map((id) => this.client.deleteFeedback(id)));\n for (const id of ids) this.bus.emit(\"feedback:deleted\", id);\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Existing methods (preserved)\n // ---------------------------------------------------------------------------\n\n private async confirmDeleteAll(): Promise<void> {\n const confirmed = await this.showConfirmDialog(\n this.t(\"panel.deleteAllConfirmTitle\"),\n this.t(\"panel.deleteAllConfirmMessage\"),\n );\n if (!confirmed) return;\n\n this.deleteAllBtn.disabled = true;\n try {\n await this.client.deleteAllFeedbacks(this.projectName);\n this.bus.emit(\"feedback:all-deleted\");\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.deleteAllBtn.disabled = false;\n }\n }\n\n private showConfirmDialog(title: string, message: string): Promise<boolean> {\n return new Promise((resolve) => {\n const backdrop = el(\"div\", { class: \"sp-confirm-backdrop\" });\n\n const titleId = `sp-confirm-title-${Date.now()}`;\n const messageId = `sp-confirm-msg-${Date.now()}`;\n\n const dialog = el(\"div\", { class: \"sp-confirm-dialog\" });\n dialog.setAttribute(\"role\", \"alertdialog\");\n dialog.setAttribute(\"aria-modal\", \"true\");\n dialog.setAttribute(\"aria-labelledby\", titleId);\n dialog.setAttribute(\"aria-describedby\", messageId);\n\n const titleEl = el(\"div\", { class: \"sp-confirm-title\" });\n titleEl.id = titleId;\n setText(titleEl, title);\n\n const messageEl = el(\"div\", { class: \"sp-confirm-message\" });\n messageEl.id = messageId;\n setText(messageEl, message);\n\n const btnRow = el(\"div\", { class: \"sp-confirm-actions\" });\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.type = \"button\";\n cancelBtn.className = \"sp-btn-ghost\";\n setText(cancelBtn, this.t(\"panel.cancel\"));\n\n const confirmBtn = document.createElement(\"button\");\n confirmBtn.type = \"button\";\n confirmBtn.className = \"sp-btn-danger\";\n setText(confirmBtn, this.t(\"panel.confirmDelete\"));\n\n let closed = false;\n const close = (result: boolean) => {\n if (closed) return;\n closed = true;\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n dialog.style.transform = \"translateY(8px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n resolve(result);\n }, 200);\n };\n\n // Focus trap: Tab cycles between cancel and confirm\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n close(false);\n return;\n }\n if (ke.key === \"Tab\") {\n ke.preventDefault();\n const active = (backdrop.getRootNode() as ShadowRoot).activeElement;\n if (active === cancelBtn) {\n confirmBtn.focus();\n } else {\n cancelBtn.focus();\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n cancelBtn.addEventListener(\"click\", () => close(false));\n confirmBtn.addEventListener(\"click\", () => close(true));\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) close(false);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(confirmBtn);\n dialog.appendChild(titleEl);\n dialog.appendChild(messageEl);\n dialog.appendChild(btnRow);\n backdrop.appendChild(dialog);\n\n this.root.getRootNode() instanceof ShadowRoot\n ? (this.root.getRootNode() as ShadowRoot).appendChild(backdrop)\n : this.root.appendChild(backdrop);\n\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n dialog.style.transform = \"translateY(0) scale(1)\";\n cancelBtn.focus();\n });\n });\n }\n\n private async deleteFeedback(feedback: FeedbackResponse, btn: HTMLButtonElement): Promise<void> {\n this.pendingMutations.add(feedback.id);\n const restore = setButtonLoading(btn);\n try {\n await this.client.deleteFeedback(feedback.id);\n this.bus.emit(\"feedback:deleted\", feedback.id);\n await this.loadFeedbacks();\n } catch (error) {\n restore();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.pendingMutations.delete(feedback.id);\n }\n }\n\n private async toggleResolve(feedback: FeedbackResponse, btn: HTMLButtonElement): Promise<void> {\n this.pendingMutations.add(feedback.id);\n const restore = setButtonLoading(btn);\n try {\n const newResolved = feedback.status !== \"resolved\";\n await this.client.resolveFeedback(feedback.id, newResolved);\n await this.loadFeedbacks();\n } catch (error) {\n restore();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.pendingMutations.delete(feedback.id);\n }\n }\n\n private buildTypeDropdown(): HTMLElement {\n this.typeOptions = [\n {\n value: \"all\",\n label: this.t(\"panel.filterAll\"),\n icon: ICON_LAYERS,\n color: this.colors.accent,\n bg: this.colors.accentLight,\n },\n {\n value: \"question\",\n label: this.t(\"type.question\"),\n icon: ICON_QUESTION,\n color: this.colors.typeQuestion,\n bg: this.colors.typeQuestionBg,\n },\n {\n value: \"change\",\n label: this.t(\"type.change\"),\n icon: ICON_CHANGE,\n color: this.colors.typeChange,\n bg: this.colors.typeChangeBg,\n },\n {\n value: \"bug\",\n label: this.t(\"type.bug\"),\n icon: ICON_BUG,\n color: this.colors.typeBug,\n bg: this.colors.typeBugBg,\n },\n {\n value: \"other\",\n label: this.t(\"type.other\"),\n icon: ICON_OTHER,\n color: this.colors.typeOther,\n bg: this.colors.typeOtherBg,\n },\n ];\n\n this.typeDropdownContainer = el(\"div\", { class: \"sp-filter-dropdown\" });\n\n this.typeDropdownBtn = document.createElement(\"button\");\n this.typeDropdownBtn.type = \"button\";\n this.typeDropdownBtn.className = \"sp-filter-dropdown-btn\";\n this.typeDropdownBtn.setAttribute(\"aria-haspopup\", \"listbox\");\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"false\");\n this.renderTypeDropdownTrigger();\n\n this.typeDropdownBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n if (this.typeDropdownMenu) this.closeTypeDropdown();\n else this.openTypeDropdown();\n });\n\n this.typeDropdownContainer.appendChild(this.typeDropdownBtn);\n return this.typeDropdownContainer;\n }\n\n private renderTypeDropdownTrigger(): void {\n const active = this.typeOptions.find((o) => this.activeFilters.has(o.value)) ?? this.typeOptions[0];\n if (!active) return;\n\n this.typeDropdownBtn.replaceChildren();\n this.typeDropdownBtn.style.setProperty(\"--sp-chip-color\", active.color);\n this.typeDropdownBtn.style.setProperty(\"--sp-chip-bg\", active.bg);\n this.typeDropdownBtn.dataset.filter = active.value;\n this.typeDropdownBtn.classList.toggle(\"sp-filter-dropdown-btn--filtered\", active.value !== \"all\");\n this.typeDropdownBtn.setAttribute(\"aria-label\", `${this.t(\"type.label\")}: ${active.label}`);\n\n const iconWrap = el(\"span\", { class: \"sp-filter-dropdown-btn__icon\" });\n iconWrap.appendChild(parseSvg(active.icon));\n this.typeDropdownBtn.appendChild(iconWrap);\n\n const labelWrap = el(\"span\", { class: \"sp-filter-dropdown-btn__label\" });\n const prefix = el(\"span\", { class: \"sp-filter-dropdown-btn__prefix\" });\n setText(prefix, this.t(\"type.label\"));\n const value = el(\"span\", { class: \"sp-filter-dropdown-btn__value\" });\n setText(value, active.label);\n labelWrap.appendChild(prefix);\n labelWrap.appendChild(value);\n this.typeDropdownBtn.appendChild(labelWrap);\n\n const chevron = el(\"span\", { class: \"sp-filter-dropdown-btn__chevron\" });\n chevron.appendChild(parseSvg(ICON_CHEVRON_DOWN));\n this.typeDropdownBtn.appendChild(chevron);\n }\n\n private openTypeDropdown(): void {\n this.typeDropdownMenu = el(\"div\", { class: \"sp-filter-dropdown-menu\" });\n this.typeDropdownMenu.setAttribute(\"role\", \"listbox\");\n this.typeDropdownMenu.setAttribute(\"aria-label\", this.t(\"type.label\"));\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"true\");\n\n for (const option of this.typeOptions) {\n const item = document.createElement(\"button\");\n item.type = \"button\";\n const isActive = this.activeFilters.has(option.value);\n item.className = `sp-filter-dropdown-option${isActive ? \" sp-filter-dropdown-option--active\" : \"\"}`;\n item.style.setProperty(\"--sp-chip-color\", option.color);\n item.style.setProperty(\"--sp-chip-bg\", option.bg);\n item.dataset.filter = option.value;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"aria-selected\", String(isActive));\n\n const iconWrap = el(\"span\", { class: \"sp-filter-dropdown-option__icon\" });\n iconWrap.appendChild(parseSvg(option.icon));\n item.appendChild(iconWrap);\n\n const labelEl = el(\"span\", { class: \"sp-filter-dropdown-option__label\" });\n setText(labelEl, option.label);\n item.appendChild(labelEl);\n\n if (isActive) {\n const checkWrap = el(\"span\", { class: \"sp-filter-dropdown-option__check\" });\n checkWrap.appendChild(parseSvg(ICON_CHECK));\n item.appendChild(checkWrap);\n }\n\n item.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.selectTypeFilter(option.value);\n });\n\n this.typeDropdownMenu.appendChild(item);\n }\n\n this.typeDropdownContainer.appendChild(this.typeDropdownMenu);\n\n requestAnimationFrame(() => {\n this.typeDropdownOutsideHandler = (e: MouseEvent) => {\n if (this.typeDropdownMenu && !this.typeDropdownContainer.contains(e.target as Node)) {\n this.closeTypeDropdown();\n }\n };\n document.addEventListener(\"click\", this.typeDropdownOutsideHandler, true);\n });\n\n this.typeDropdownMenu.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\") {\n this.closeTypeDropdown();\n this.typeDropdownBtn.focus();\n }\n });\n }\n\n private closeTypeDropdown(): void {\n if (this.typeDropdownMenu) {\n this.typeDropdownMenu.remove();\n this.typeDropdownMenu = null;\n }\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"false\");\n if (this.typeDropdownOutsideHandler) {\n document.removeEventListener(\"click\", this.typeDropdownOutsideHandler, true);\n this.typeDropdownOutsideHandler = null;\n }\n }\n\n private selectTypeFilter(value: string): void {\n this.activeFilters.clear();\n this.activeFilters.add(value);\n this.renderTypeDropdownTrigger();\n this.closeTypeDropdown();\n this.loadFeedbacks().catch(() => {});\n }\n\n private buildStatusSegmented(): HTMLElement {\n this.statusSegmented = new SegmentedControl<\"all\" | FeedbackStatus>({\n options: [\n {\n value: \"all\",\n label: this.t(\"panel.statusAll\"),\n icon: ICON_LAYERS,\n color: this.colors.accent,\n bg: this.colors.accentLight,\n },\n {\n value: \"open\",\n label: this.t(\"panel.statusOpen\"),\n icon: ICON_DOT_OPEN,\n color: this.colors.statusOpen,\n bg: this.colors.statusOpenBg,\n },\n {\n value: \"resolved\",\n label: this.t(\"panel.statusResolved\"),\n icon: ICON_CHECK,\n color: this.colors.statusResolved,\n bg: this.colors.statusResolvedBg,\n },\n ],\n value: \"all\",\n onChange: () => {\n this.loadFeedbacks().catch(() => {});\n },\n ariaLabel: this.t(\"status.label\"),\n datasetKey: \"statusFilter\",\n modifierPrefix: \"sp-segmented__btn--\",\n });\n\n return this.statusSegmented.element;\n }\n\n /**\n * Build the page-scope segmented control: \"this page / this type / all\".\n * The \"this type\" button is hidden when the current scope has no urlPattern\n * (host did not provide one for this route). Visibility is refreshed on\n * every `loadFeedbacks` so SPA navigation stays consistent.\n */\n private buildScopeSegmented(): HTMLElement {\n this.scopeSegmented = new SegmentedControl<\"this\" | \"template\" | \"all\">({\n options: [\n { value: \"this\", label: this.t(\"scope.thisPage\") },\n { value: \"template\", label: this.t(\"scope.thisType\") },\n { value: \"all\", label: this.t(\"scope.all\") },\n ],\n value: this.initialScopeFilter,\n onChange: () => {\n this.loadFeedbacks().catch(() => {});\n },\n ariaLabel: this.t(\"scope.label\"),\n datasetKey: \"scopeFilter\",\n modifierPrefix: \"sp-segmented__btn--scope-\",\n extraClass: \"sp-segmented--scope\",\n });\n\n // Initial visibility — \"this type\" only meaningful when scope has urlPattern\n this.syncScopeAvailability();\n return this.scopeSegmented.element;\n }\n\n /**\n * Hide the \"this type\" button when the current scope has no urlPattern, and\n * fall back to \"this page\" if it was the active selection. Called on every\n * `loadFeedbacks` so SPA navigation stays consistent.\n */\n private syncScopeAvailability(): void {\n if (!this.scopeSegmented) return;\n const scope = this.getScope();\n const showTemplate = !!scope.urlPattern;\n this.scopeSegmented.setOptionVisible(\"template\", showTemplate);\n if (!showTemplate && this.scopeSegmented.value === \"template\") {\n this.scopeSegmented.select(\"this\");\n }\n }\n\n /** Get the focused feedback (for keyboard shortcuts) */\n private getFocusedFeedback(): FeedbackResponse | undefined {\n const idx = getFocusedCardIndex(this.listContainer);\n if (idx < 0) return undefined;\n const card = this.listContainer.querySelectorAll<HTMLElement>(\".sp-card\")[idx];\n if (!card) return undefined;\n return this.feedbacks.find((f) => f.id === card.dataset.feedbackId);\n }\n\n scrollToFeedback(feedbackId: string): void {\n const escapedId = CSS.escape(feedbackId);\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${escapedId}\"]`);\n if (card) {\n card.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n card.classList.add(\"sp-anim-flash\");\n card.addEventListener(\n \"animationend\",\n () => {\n card.classList.remove(\"sp-anim-flash\");\n },\n { once: true },\n );\n }\n }\n\n /** Refresh the panel after a new feedback is submitted */\n async refresh(): Promise<void> {\n if (this.isOpen) {\n await this.loadFeedbacks();\n }\n }\n\n /** Whether the panel is currently open — used by the launcher to coordinate marker refreshes. */\n get isCurrentlyOpen(): boolean {\n return this.isOpen;\n }\n\n destroy(): void {\n this.loadController?.abort();\n if (this.searchTimeout) clearTimeout(this.searchTimeout);\n this.listContainer.removeEventListener(\"click\", this.onListClick);\n this.listContainer.removeEventListener(\"keydown\", this.onListKeydown);\n this.listContainer.removeEventListener(\"mouseover\", this.onListMouseover);\n this.listContainer.removeEventListener(\"mouseout\", this.onListMouseout);\n document.removeEventListener(\"sp-marker-click\", this.onMarkerClick);\n this.closeTypeDropdown();\n this.sortControls.destroy();\n this.bulk.destroy();\n this.exportBtn.destroy();\n this.shortcuts.destroy();\n this.detail.destroy();\n this.root.remove();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/segmented-control.ts","../src/panel.ts"],"names":["SegmentedControl","config","el","option","btn","isActive","iconWrap","parseSvg","labelEl","setText","e","value","buttons","visible","current","visibleValues","o","v","idx","nextIdx","next","m","Panel","shadowRoot","colors","bus","client","projectName","markers","t","locale","pageScopeOptions","header","title","ICON_CLOSE","ICON_TRASH","deleteAllLabel","ExportButton","headerRight","PanelStats","filters","searchWrap","searchIcon","ICON_SEARCH","filterBar","PanelSortControls","BulkActions","ids","DetailView","fb","newResolved","ann","KeyboardShortcuts","dir","getFocusedCardIndex","focusCardByIndex","target","actionEl","card","feedbackId","feedback","f","action","message","isExpanded","number","ke","open","isVisible","cur","focusable","first","last","active","loading","spinner","empty","text","retryBtn","signal","search","typeFilter","currentStatus","statusFilter","scope","currentScope","options","hasContent","feedbacks","total","markerFeedbacks","error","controller","nextPage","loadMoreBtn","restoreBtn","setButtonLoading","emptyText","sorted","sortFeedbacks","feedbackIds","selectAllBar","groups","groupFeedbacksByPage","globalIndex","pagePath","groupFeedbacks","groupHeader","createPageGroupHeader","groupContent","index","remaining","loadMoreWrap","isResolved","typeColor","getTypeColor","getTypeLabel","bar","body","checkbox","num","badge","typeBg","getTypeBgColor","date","formatRelativeDate","expandBtn","footer","resolveBtn","ICON_UNDO","span","ICON_CHECK","deleteBtn","deleteBtnLabel","id","resolve","backdrop","titleId","messageId","dialog","titleEl","messageEl","btnRow","cancelBtn","confirmBtn","closed","close","result","onKeydown","restore","ICON_LAYERS","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","labelWrap","prefix","chevron","ICON_CHEVRON_DOWN","item","checkWrap","ICON_DOT_OPEN","showTemplate","escapedId"],"mappings":"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","file":"panel-47WTS3KH.js","sourcesContent":["/**\n * Accessible segmented (radiogroup) control.\n *\n * Replaces the near-identical `buildStatusSegmented` / `buildScopeSegmented`\n * pairs that previously lived inline in `panel.ts`: keyboard navigation\n * (ArrowLeft/Right, Home/End), aria-checked toggling, `tabIndex` roving,\n * and optional icon+colour decoration.\n *\n * Visibility filtering — needed by the scope control which hides the\n * \"this type\" option when there is no urlPattern — is handled by\n * `setOptionVisible(value, visible)` and is respected by keyboard\n * navigation so users can't focus a hidden option via arrow keys.\n */\n\nimport { el, parseSvg, setText } from \"../dom-utils.js\";\n\n/**\n * Visual decoration for a segmented option.\n * Both fields are optional: scope options omit them entirely.\n */\nexport interface SegmentedDecoration {\n icon?: string;\n color?: string;\n bg?: string;\n}\n\nexport interface SegmentedOption<T extends string> extends SegmentedDecoration {\n value: T;\n label: string;\n}\n\nexport interface SegmentedControlConfig<T extends string> {\n /** Options to render — order is preserved. */\n options: ReadonlyArray<SegmentedOption<T>>;\n /** Initial selected value — must appear in `options`. */\n value: T;\n /** Called whenever selection changes (click or keyboard). */\n onChange: (value: T) => void;\n /** Accessible label exposed via `aria-label` on the radiogroup. */\n ariaLabel: string;\n /** Extra CSS class appended to the wrapper (e.g. `sp-segmented--scope`). */\n extraClass?: string;\n /** dataset attribute name used per-button, e.g. `statusFilter` → `data-status-filter`. */\n datasetKey: string;\n /** Class prefix used for per-option modifier, e.g. `sp-segmented__btn--` + option.value. */\n modifierPrefix?: string;\n}\n\n/**\n * Build a segmented (radiogroup) control. Returns both the root element and\n * the imperative API for updating selection / visibility from outside —\n * Panel needs the latter when scope availability changes between SPA\n * navigations.\n */\nexport class SegmentedControl<T extends string> {\n readonly element: HTMLElement;\n private current: T;\n private readonly opts: ReadonlyArray<SegmentedOption<T>>;\n private readonly onChange: (value: T) => void;\n private readonly datasetKey: string;\n\n constructor(config: SegmentedControlConfig<T>) {\n this.opts = config.options;\n this.current = config.value;\n this.onChange = config.onChange;\n this.datasetKey = config.datasetKey;\n\n this.element = el(\"div\", {\n class: `sp-segmented${config.extraClass ? ` ${config.extraClass}` : \"\"}`,\n role: \"radiogroup\",\n });\n this.element.setAttribute(\"aria-label\", config.ariaLabel);\n\n for (const option of this.opts) {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className =\n config.modifierPrefix !== undefined\n ? `sp-segmented__btn ${config.modifierPrefix}${option.value}`\n : \"sp-segmented__btn\";\n btn.dataset[this.datasetKey] = option.value;\n btn.setAttribute(\"role\", \"radio\");\n const isActive = this.current === option.value;\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n if (isActive) btn.classList.add(\"sp-segmented__btn--active\");\n if (option.color) btn.style.setProperty(\"--sp-chip-color\", option.color);\n if (option.bg) btn.style.setProperty(\"--sp-chip-bg\", option.bg);\n\n if (option.icon) {\n const iconWrap = el(\"span\", { class: \"sp-segmented__icon\" });\n iconWrap.appendChild(parseSvg(option.icon));\n btn.appendChild(iconWrap);\n }\n\n const labelEl = el(\"span\", { class: \"sp-segmented__label\" });\n setText(labelEl, option.label);\n btn.appendChild(labelEl);\n\n btn.addEventListener(\"click\", () => this.select(option.value));\n btn.addEventListener(\"keydown\", (e) => this.handleKey(e, option.value));\n\n this.element.appendChild(btn);\n }\n }\n\n /** Imperatively change the selected option (also fires `onChange`). */\n select(value: T): void {\n this.current = value;\n this.syncSelection();\n this.onChange(value);\n }\n\n /** Apply selection-only DOM updates without firing `onChange`. Useful on init refresh. */\n private syncSelection(): void {\n const buttons = this.element.querySelectorAll<HTMLButtonElement>(\".sp-segmented__btn\");\n for (const btn of buttons) {\n const isActive = btn.dataset[this.datasetKey] === this.current;\n btn.classList.toggle(\"sp-segmented__btn--active\", isActive);\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n }\n }\n\n /**\n * Show / hide a specific option. Hidden options are skipped during keyboard\n * navigation. Returns true when an option was actually toggled.\n */\n setOptionVisible(value: T, visible: boolean): boolean {\n const btn = this.element.querySelector<HTMLButtonElement>(`[data-${this.kebabKey()}=\"${value}\"]`);\n if (!btn) return false;\n btn.style.display = visible ? \"\" : \"none\";\n return true;\n }\n\n /** Current selection. */\n get value(): T {\n return this.current;\n }\n\n /** Focus the button matching `value`, if it exists. */\n focusOption(value: T): void {\n const btn = this.element.querySelector<HTMLButtonElement>(`[data-${this.kebabKey()}=\"${value}\"]`);\n btn?.focus();\n }\n\n private handleKey(e: KeyboardEvent, current: T): void {\n const visibleValues = this.opts\n .map((o) => o.value)\n .filter((v) => {\n const btn = this.element.querySelector<HTMLButtonElement>(`[data-${this.kebabKey()}=\"${v}\"]`);\n return btn !== null && btn.style.display !== \"none\";\n });\n const idx = visibleValues.indexOf(current);\n if (idx < 0) return;\n\n let nextIdx: number;\n switch (e.key) {\n case \"ArrowLeft\":\n nextIdx = (idx - 1 + visibleValues.length) % visibleValues.length;\n break;\n case \"ArrowRight\":\n nextIdx = (idx + 1) % visibleValues.length;\n break;\n case \"Home\":\n nextIdx = 0;\n break;\n case \"End\":\n nextIdx = visibleValues.length - 1;\n break;\n default:\n return;\n }\n e.preventDefault();\n const next = visibleValues[nextIdx];\n if (next === undefined) return;\n this.select(next);\n this.focusOption(next);\n }\n\n /** Convert datasetKey (\"statusFilter\") to its DOM attribute form (\"status-filter\"). */\n private kebabKey(): string {\n return this.datasetKey.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);\n }\n}\n","import type { FeedbackResponse, FeedbackStatus, FeedbackType, PageScope } from \"@siteping/core\";\nimport type { GetFeedbacksOptions, WidgetClient } from \"./api-client.js\";\nimport { SegmentedControl } from \"./components/segmented-control.js\";\nimport { PAGE_SIZE } from \"./constants.js\";\nimport { el, formatRelativeDate, parseSvg, setButtonLoading, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { ExportButton } from \"./export-utils.js\";\nimport { getTypeLabel, type TFunction } from \"./i18n/index.js\";\nimport {\n ICON_BUG,\n ICON_CHANGE,\n ICON_CHECK,\n ICON_CHEVRON_DOWN,\n ICON_CLOSE,\n ICON_DOT_OPEN,\n ICON_LAYERS,\n ICON_OTHER,\n ICON_QUESTION,\n ICON_SEARCH,\n ICON_TRASH,\n ICON_UNDO,\n} from \"./icons.js\";\nimport type { MarkerManager } from \"./markers.js\";\nimport { BulkActions } from \"./panel-bulk.js\";\nimport { DetailView } from \"./panel-detail.js\";\nimport { createPageGroupHeader, groupFeedbacksByPage, PanelSortControls, sortFeedbacks } from \"./panel-sort.js\";\nimport { PanelStats } from \"./panel-stats.js\";\nimport { focusCardByIndex, getFocusedCardIndex, KeyboardShortcuts } from \"./shortcuts.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n/**\n * Side panel (400px) with feedback history, filters, search, stats,\n * sort/group, bulk actions, export, detail view, and keyboard shortcuts.\n *\n * Lives inside the Shadow DOM.\n * Glassmorphism: glass background, staggered card animations,\n * loading states, resolve feedback with disabled state.\n */\nexport class Panel {\n private root: HTMLElement;\n private listContainer: HTMLElement;\n private searchInput: HTMLInputElement;\n private closeBtn: HTMLButtonElement;\n private deleteAllBtn: HTMLButtonElement;\n private activeFilters = new Set<string>([\"all\"]);\n private typeDropdownBtn!: HTMLButtonElement;\n private typeDropdownContainer!: HTMLElement;\n private typeDropdownMenu: HTMLElement | null = null;\n private typeDropdownOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private statusSegmented!: SegmentedControl<\"all\" | FeedbackStatus>;\n private typeOptions!: ReadonlyArray<{ value: string; label: string; icon: string; color: string; bg: string }>;\n private feedbacks: FeedbackResponse[] = [];\n private currentPage = 1;\n private totalFeedbacks = 0;\n private isLoadingMore = false;\n private isOpen = false;\n private searchTimeout: ReturnType<typeof setTimeout> | null = null;\n private loadController: AbortController | null = null;\n /** Tracks feedback IDs with in-flight mutations to prevent spam-click race conditions */\n private pendingMutations = new Set<string>();\n\n // New feature modules\n private readonly stats: PanelStats;\n private readonly sortControls: PanelSortControls;\n private readonly bulk: BulkActions;\n private readonly exportBtn: ExportButton;\n private readonly shortcuts: KeyboardShortcuts;\n private readonly detail: DetailView;\n private readonly shadowRoot: ShadowRoot;\n\n // i18n: t is shared with all submodules.\n\n // Page scope — supplied by launcher so the panel can scope its results to\n // the current page (or template) and filter markers accordingly.\n private readonly getScope: () => PageScope;\n private readonly scopeAnnotationsByUrl: boolean;\n /** \"this\" = current url, \"template\" = url pattern, \"all\" = no scope filter */\n private scopeSegmented!: SegmentedControl<\"this\" | \"template\" | \"all\">;\n /** Cached initial scope value — applied after construction in `buildScopeSegmented`. */\n private readonly initialScopeFilter: \"this\" | \"template\" | \"all\" = \"this\";\n\n constructor(\n shadowRoot: ShadowRoot,\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly client: WidgetClient,\n private readonly projectName: string,\n private readonly markers: MarkerManager,\n private readonly t: TFunction,\n private readonly locale: string,\n pageScopeOptions?: { getScope: () => PageScope; scopeAnnotationsByUrl: boolean },\n ) {\n this.shadowRoot = shadowRoot;\n this.getScope = pageScopeOptions?.getScope ?? (() => ({ url: window.location.pathname, urlPattern: null }));\n this.scopeAnnotationsByUrl = pageScopeOptions?.scopeAnnotationsByUrl ?? true;\n\n this.root = el(\"div\", { class: \"sp-panel\" });\n this.root.setAttribute(\"role\", \"complementary\");\n this.root.setAttribute(\"aria-label\", this.t(\"panel.ariaLabel\"));\n this.root.setAttribute(\"aria-hidden\", \"true\");\n\n // --- Header ---\n const header = el(\"div\", { class: \"sp-panel-header\" });\n const title = el(\"span\", { class: \"sp-panel-title\" });\n setText(title, this.t(\"panel.title\"));\n\n this.closeBtn = document.createElement(\"button\");\n this.closeBtn.className = \"sp-panel-close\";\n this.closeBtn.setAttribute(\"aria-label\", this.t(\"panel.close\"));\n this.closeBtn.appendChild(parseSvg(ICON_CLOSE));\n this.closeBtn.addEventListener(\"click\", () => this.close());\n\n this.deleteAllBtn = document.createElement(\"button\");\n this.deleteAllBtn.className = \"sp-btn-delete-all\";\n this.deleteAllBtn.setAttribute(\"aria-label\", this.t(\"panel.deleteAll\"));\n this.deleteAllBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteAllLabel = document.createElement(\"span\");\n setText(deleteAllLabel, ` ${this.t(\"panel.deleteAll\")}`);\n this.deleteAllBtn.appendChild(deleteAllLabel);\n this.deleteAllBtn.addEventListener(\"click\", () => this.confirmDeleteAll());\n\n // Export button\n this.exportBtn = new ExportButton(colors, () => this.feedbacks, this.t);\n\n const headerRight = el(\"div\", { class: \"sp-panel-header-right\" });\n headerRight.appendChild(this.exportBtn.element);\n headerRight.appendChild(this.deleteAllBtn);\n headerRight.appendChild(this.closeBtn);\n\n header.appendChild(title);\n header.appendChild(headerRight);\n\n // --- Stats ---\n this.stats = new PanelStats(colors, this.t);\n\n // --- Filters ---\n const filters = el(\"div\", { class: \"sp-filters\" });\n\n // Search\n const searchWrap = el(\"div\", { class: \"sp-search-wrap\" });\n const searchIcon = parseSvg(ICON_SEARCH);\n searchIcon.setAttribute(\"class\", \"sp-search-icon\");\n this.searchInput = document.createElement(\"input\");\n this.searchInput.type = \"text\";\n this.searchInput.className = \"sp-search\";\n this.searchInput.placeholder = this.t(\"panel.search\");\n this.searchInput.setAttribute(\"aria-label\", this.t(\"panel.searchAria\"));\n this.searchInput.addEventListener(\"input\", () => {\n if (this.searchTimeout) clearTimeout(this.searchTimeout);\n this.searchTimeout = setTimeout(() => this.loadFeedbacks().catch(() => {}), 200);\n });\n searchWrap.appendChild(searchIcon);\n searchWrap.appendChild(this.searchInput);\n\n // Filter bar (type dropdown + status segmented + scope segmented).\n // The scope control gives users a fast way to widen results to \"this type\n // of page\" or \"all pages\" when the host provides a route template.\n const filterBar = el(\"div\", { class: \"sp-filter-bar\" });\n filterBar.appendChild(this.buildTypeDropdown());\n filterBar.appendChild(this.buildStatusSegmented());\n filterBar.appendChild(this.buildScopeSegmented());\n\n // Sort controls\n this.sortControls = new PanelSortControls(colors, () => this.renderList(), this.t);\n\n filters.appendChild(searchWrap);\n filters.appendChild(filterBar);\n filters.appendChild(this.sortControls.element);\n\n // --- List ---\n this.listContainer = el(\"div\", { class: \"sp-list\" });\n this.listContainer.setAttribute(\"role\", \"list\");\n this.listContainer.setAttribute(\"aria-label\", this.t(\"panel.feedbackList\"));\n\n // --- Bulk Actions ---\n this.bulk = new BulkActions(\n colors,\n {\n onResolve: (ids) => this.bulkResolve(ids),\n onDelete: (ids) => this.bulkDelete(ids),\n },\n this.t,\n );\n this.bulk.setListContainer(this.listContainer);\n\n // --- Detail View ---\n this.detail = new DetailView(\n colors,\n {\n onBack: () => this.detail.hide(),\n onResolve: async (fb) => {\n const newResolved = fb.status !== \"resolved\";\n await this.client.resolveFeedback(fb.id, newResolved);\n await this.loadFeedbacks();\n this.detail.hide();\n },\n onDelete: async (fb) => {\n await this.client.deleteFeedback(fb.id);\n this.bus.emit(\"feedback:deleted\", fb.id);\n await this.loadFeedbacks();\n this.detail.hide();\n },\n onGoToAnnotation: (fb) => {\n if (fb.annotations.length > 0) {\n const ann = fb.annotations[0];\n if (!ann) return;\n window.scrollTo({ left: ann.scrollX, top: ann.scrollY, behavior: \"smooth\" });\n this.markers.pinHighlight(fb);\n }\n },\n },\n this.t,\n locale,\n );\n\n // --- Keyboard Shortcuts ---\n this.shortcuts = new KeyboardShortcuts(\n colors,\n {\n onNavigate: (dir) => {\n const idx = getFocusedCardIndex(this.listContainer);\n focusCardByIndex(this.listContainer, dir === \"down\" ? idx + 1 : idx - 1);\n },\n onResolve: () => {\n const fb = this.getFocusedFeedback();\n if (fb && !this.pendingMutations.has(fb.id)) {\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${CSS.escape(fb.id)}\"]`);\n const btn = card?.querySelector<HTMLButtonElement>('[data-action=\"resolve\"]');\n if (btn) this.toggleResolve(fb, btn).catch(() => {});\n }\n },\n onDelete: () => {\n const fb = this.getFocusedFeedback();\n if (fb && !this.pendingMutations.has(fb.id)) {\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${CSS.escape(fb.id)}\"]`);\n const btn = card?.querySelector<HTMLButtonElement>('[data-action=\"delete\"]');\n if (btn) this.deleteFeedback(fb, btn).catch(() => {});\n }\n },\n onFocusSearch: () => this.searchInput.focus(),\n onToggleSelect: () => {\n const fb = this.getFocusedFeedback();\n if (fb) this.bulk.toggle(fb.id);\n },\n },\n this.t,\n );\n\n // --- Assemble DOM ---\n this.root.appendChild(header);\n this.root.appendChild(this.stats.element);\n this.root.appendChild(filters);\n this.root.appendChild(this.listContainer);\n this.root.appendChild(this.bulk.barElement);\n this.root.appendChild(this.detail.element);\n this.root.appendChild(this.shortcuts.helpOverlay);\n this.root.appendChild(this.shortcuts.hintButton);\n shadowRoot.appendChild(this.root);\n\n // --- Event delegation on listContainer ---\n\n this.onListClick = (e: Event) => {\n const target = e.target as Element;\n\n // Bulk checkbox clicks are handled by BulkActions, skip\n if (target.closest(\".sp-bulk-checkbox\")) return;\n\n // Action buttons (expand, resolve, delete)\n const actionEl = target.closest<HTMLElement>(\"[data-action]\");\n if (actionEl) {\n e.stopPropagation();\n const card = actionEl.closest<HTMLElement>(\".sp-card\");\n if (!card) return;\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (!feedback) return;\n\n const action = actionEl.dataset.action;\n if (action === \"expand\") {\n const message = card.querySelector<HTMLElement>(\".sp-card-message\");\n if (!message) return;\n const isExpanded = message.classList.toggle(\"sp-card-message--expanded\");\n setText(actionEl, isExpanded ? this.t(\"panel.showLess\") : this.t(\"panel.showMore\"));\n actionEl.setAttribute(\"aria-expanded\", String(isExpanded));\n } else if (action === \"resolve\") {\n if (this.pendingMutations.has(feedback.id)) return;\n const btn = actionEl as HTMLButtonElement;\n this.toggleResolve(feedback, btn).catch(() => {});\n } else if (action === \"delete\") {\n if (this.pendingMutations.has(feedback.id)) return;\n const btn = actionEl as HTMLButtonElement;\n this.deleteFeedback(feedback, btn).catch(() => {});\n }\n return;\n }\n\n // Card click → open detail view\n const card = target.closest<HTMLElement>(\".sp-card\");\n if (card) {\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (feedback) {\n const number = this.feedbacks.indexOf(feedback) + 1;\n this.detail.show(feedback, number);\n }\n }\n };\n this.listContainer.addEventListener(\"click\", this.onListClick);\n\n this.onListKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key !== \"Enter\" && ke.key !== \" \") return;\n const target = ke.target as Element;\n const card = target.closest<HTMLElement>(\".sp-card\");\n // Only activate if the card itself is focused, not a button inside it\n if (!card || target !== card) return;\n ke.preventDefault();\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (feedback) {\n const number = this.feedbacks.indexOf(feedback) + 1;\n this.detail.show(feedback, number);\n }\n };\n this.listContainer.addEventListener(\"keydown\", this.onListKeydown);\n\n // mouseover/mouseout bubble (unlike mouseenter/mouseleave), enabling delegation\n this.onListMouseover = (e: Event) => {\n const target = (e as MouseEvent).target as Element;\n const card = target.closest<HTMLElement>(\".sp-card\");\n if (!card) return;\n const feedbackId = card.dataset.feedbackId;\n if (feedbackId) this.markers.highlight(feedbackId);\n };\n this.listContainer.addEventListener(\"mouseover\", this.onListMouseover);\n\n this.onListMouseout = (e: Event) => {\n const target = (e as MouseEvent).relatedTarget as Element | null;\n // Only clear highlight when leaving all cards (relatedTarget is outside listContainer)\n if (target && this.listContainer.contains(target)) return;\n this.markers.highlight(\"\");\n };\n this.listContainer.addEventListener(\"mouseout\", this.onListMouseout);\n\n // Events\n this.bus.on(\"panel:toggle\", (open) => {\n open ? this.open() : this.close();\n });\n\n // Keyboard handling: Escape to close + focus trap\n shadowRoot.addEventListener(\"keydown\", (e) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\" && this.isOpen) {\n // If detail view is open, close it instead\n if (this.detail.isVisible) {\n this.detail.hide();\n return;\n }\n this.close();\n return;\n }\n if (ke.key === \"Tab\" && this.isOpen) {\n // Filter out non-tabbable elements: those hidden via `display: none`\n // (either on themselves or any ancestor up to this.root) and elements\n // explicitly disabled. Without this filter, the trap can jump to a\n // button inside a closed detail view and effectively swallow the Tab\n // key. We use a walk of style.display rather than `offsetParent`\n // because the latter is unreliable in jsdom (always null without\n // layout) and breaks unit tests.\n const isVisible = (el: HTMLElement): boolean => {\n let cur: HTMLElement | null = el;\n while (cur && cur !== this.root) {\n if (cur.style.display === \"none\") return false;\n cur = cur.parentElement;\n }\n return true;\n };\n const focusable = Array.from(\n this.root.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n ),\n ).filter((el) => isVisible(el) && !el.hasAttribute(\"disabled\"));\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (!first || !last) return;\n const active = (shadowRoot as ShadowRoot).activeElement;\n if (ke.shiftKey && active === first) {\n ke.preventDefault();\n last.focus();\n } else if (!ke.shiftKey && active === last) {\n ke.preventDefault();\n first.focus();\n }\n }\n });\n\n // Listen for marker clicks\n this.onMarkerClick = ((e: CustomEvent) => {\n this.scrollToFeedback(e.detail.feedbackId);\n }) as EventListener;\n document.addEventListener(\"sp-marker-click\", this.onMarkerClick);\n }\n\n private onMarkerClick: EventListener;\n private onListClick: (e: Event) => void;\n private onListKeydown: (e: Event) => void;\n private onListMouseover: (e: Event) => void;\n private onListMouseout: (e: Event) => void;\n\n async open(): Promise<void> {\n if (this.isOpen) return;\n this.isOpen = true;\n this.root.classList.add(\"sp-panel--open\");\n this.root.setAttribute(\"aria-hidden\", \"false\");\n this.bus.emit(\"open\");\n this.shortcuts.enable(this.shadowRoot);\n await this.loadFeedbacks();\n // Move focus into the panel (search input or close button)\n requestAnimationFrame(() => {\n if (this.searchInput) {\n this.searchInput.focus();\n } else {\n this.closeBtn.focus();\n }\n });\n }\n\n close(): void {\n if (!this.isOpen) return;\n this.isOpen = false;\n this.root.classList.remove(\"sp-panel--open\");\n this.root.setAttribute(\"aria-hidden\", \"true\");\n this.bus.emit(\"close\");\n this.shortcuts.disable();\n this.detail.hide();\n // Restore focus to the FAB\n const fab = (this.root.getRootNode() as ShadowRoot).querySelector<HTMLButtonElement>(\".sp-fab\");\n fab?.focus();\n }\n\n private showLoading(): void {\n this.listContainer.replaceChildren();\n const loading = el(\"div\", { class: \"sp-loading\" });\n loading.setAttribute(\"role\", \"status\");\n loading.setAttribute(\"aria-live\", \"polite\");\n loading.setAttribute(\"aria-label\", this.t(\"panel.loading\"));\n const spinner = el(\"div\", { class: \"sp-spinner\" });\n loading.appendChild(spinner);\n this.listContainer.appendChild(loading);\n }\n\n private showError(): void {\n this.listContainer.replaceChildren();\n const empty = el(\"div\", { class: \"sp-empty\" });\n empty.setAttribute(\"role\", \"status\");\n empty.setAttribute(\"aria-live\", \"polite\");\n const text = el(\"div\", { class: \"sp-empty-text\" });\n setText(text, this.t(\"panel.loadError\"));\n const retryBtn = document.createElement(\"button\");\n retryBtn.className = \"sp-btn-ghost\";\n retryBtn.style.marginTop = \"8px\";\n setText(retryBtn, this.t(\"panel.retry\"));\n retryBtn.addEventListener(\"click\", () => this.loadFeedbacks().catch(() => {}));\n empty.appendChild(text);\n empty.appendChild(retryBtn);\n this.listContainer.appendChild(empty);\n }\n\n private async loadFeedbacks(): Promise<void> {\n // Cancel any in-flight request to prevent stale responses from overwriting newer results\n this.loadController?.abort();\n this.loadController = new AbortController();\n const { signal } = this.loadController;\n\n // Reset to page 1 on fresh load (filter/search change)\n this.currentPage = 1;\n\n const search = this.searchInput.value.trim() || undefined;\n const typeFilter = this.activeFilters.has(\"all\") ? undefined : (Array.from(this.activeFilters)[0] as FeedbackType);\n const currentStatus = this.statusSegmented.value;\n const statusFilter = currentStatus === \"all\" ? undefined : currentStatus;\n\n const scope = this.getScope();\n // Refresh scope-filter button visibility based on current scope (SPA nav).\n this.syncScopeAvailability();\n const currentScope = this.scopeSegmented.value;\n const options: GetFeedbacksOptions & { page: number; limit: number } = {\n page: 1,\n limit: PAGE_SIZE,\n };\n if (typeFilter) options.type = typeFilter;\n if (statusFilter) options.status = statusFilter;\n if (search) options.search = search;\n if (currentScope === \"this\") {\n options.url = scope.url;\n } else if (currentScope === \"template\" && scope.urlPattern) {\n options.urlPattern = scope.urlPattern;\n }\n\n // Only show spinner on first load (empty list) — otherwise keep current content visible\n const hasContent = this.feedbacks.length > 0;\n if (!hasContent) this.showLoading();\n\n try {\n const { feedbacks, total } = await this.client.getFeedbacks(this.projectName, options);\n if (signal.aborted) return; // Stale response — a newer request superseded this one\n this.feedbacks = feedbacks;\n this.totalFeedbacks = total;\n this.stats.update(feedbacks, total);\n this.bulk.reset();\n this.renderList();\n // Markers always render only the current-URL slice — even when the panel\n // shows a wider scope (\"template\" or \"all\"), markers stay strictly local\n // so the user never sees out-of-context dots on the page.\n const markerFeedbacks = this.scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === scope.url) : feedbacks;\n this.markers.render(markerFeedbacks);\n } catch (error) {\n if (signal.aborted) return; // Expected abort, not a real error\n if (!hasContent) this.showError();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private async loadMoreFeedbacks(): Promise<void> {\n if (this.isLoadingMore) return;\n this.isLoadingMore = true;\n\n // Capture current controller — if loadFeedbacks() runs while we're in-flight,\n // it replaces the controller, signaling that our results are stale.\n const controller = this.loadController;\n\n const nextPage = this.currentPage + 1;\n const search = this.searchInput.value.trim() || undefined;\n const typeFilter = this.activeFilters.has(\"all\") ? undefined : (Array.from(this.activeFilters)[0] as FeedbackType);\n const currentStatus = this.statusSegmented.value;\n const statusFilter = currentStatus === \"all\" ? undefined : currentStatus;\n\n const scope = this.getScope();\n const currentScope = this.scopeSegmented.value;\n const options: GetFeedbacksOptions & { page: number; limit: number } = {\n page: nextPage,\n limit: PAGE_SIZE,\n };\n if (typeFilter) options.type = typeFilter;\n if (statusFilter) options.status = statusFilter;\n if (search) options.search = search;\n if (currentScope === \"this\") {\n options.url = scope.url;\n } else if (currentScope === \"template\" && scope.urlPattern) {\n options.urlPattern = scope.urlPattern;\n }\n\n // Show spinner on the \"Load more\" button\n const loadMoreBtn = this.listContainer.querySelector<HTMLButtonElement>(\".sp-btn-load-more\");\n let restoreBtn: (() => void) | undefined;\n if (loadMoreBtn) restoreBtn = setButtonLoading(loadMoreBtn);\n\n try {\n const { feedbacks, total } = await this.client.getFeedbacks(this.projectName, options);\n if (controller !== this.loadController) return; // Filter/search changed — discard stale page\n this.currentPage = nextPage;\n this.totalFeedbacks = total;\n this.feedbacks = [...this.feedbacks, ...feedbacks];\n this.stats.update(this.feedbacks, total);\n this.renderList();\n const markerFeedbacks = this.scopeAnnotationsByUrl\n ? this.feedbacks.filter((f) => f.url === scope.url)\n : this.feedbacks;\n this.markers.render(markerFeedbacks);\n } catch (error) {\n if (restoreBtn) restoreBtn();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.isLoadingMore = false;\n }\n }\n\n private renderList(): void {\n this.listContainer.replaceChildren();\n\n if (this.feedbacks.length === 0) {\n const empty = el(\"div\", { class: \"sp-empty\" });\n empty.setAttribute(\"role\", \"status\");\n empty.setAttribute(\"aria-live\", \"polite\");\n const emptyText = el(\"div\", { class: \"sp-empty-text\" });\n setText(emptyText, this.t(\"panel.empty\"));\n empty.appendChild(emptyText);\n this.listContainer.appendChild(empty);\n return;\n }\n\n // Apply sorting\n const sorted = sortFeedbacks(this.feedbacks, this.sortControls.sortMode);\n\n // Select all bar\n const feedbackIds = sorted.map((f) => f.id);\n const selectAllBar = this.bulk.createSelectAllBar(feedbackIds, this.t(\"bulk.selectAll\"));\n this.listContainer.appendChild(selectAllBar);\n\n if (this.sortControls.groupByPage) {\n // Group by page rendering\n const groups = groupFeedbacksByPage(sorted);\n let globalIndex = 0;\n for (const [pagePath, groupFeedbacks] of groups) {\n const groupHeader = createPageGroupHeader(pagePath, groupFeedbacks.length, this.colors);\n this.listContainer.appendChild(groupHeader);\n\n const groupContent = el(\"div\", { class: \"sp-group-content\" });\n for (const feedback of groupFeedbacks) {\n const card = this.createCard(feedback, globalIndex + 1);\n card.style.setProperty(\"--sp-card-i\", String(globalIndex));\n groupContent.appendChild(card);\n globalIndex++;\n }\n this.listContainer.appendChild(groupContent);\n }\n } else {\n // Flat list rendering\n sorted.forEach((feedback, index) => {\n const card = this.createCard(feedback, index + 1);\n card.style.setProperty(\"--sp-card-i\", String(index));\n this.listContainer.appendChild(card);\n });\n }\n\n // \"Load more\" button when there are remaining feedbacks\n const remaining = this.totalFeedbacks - this.feedbacks.length;\n if (remaining > 0) {\n const loadMoreWrap = el(\"div\", { class: \"sp-load-more-wrap\" });\n const loadMoreBtn = document.createElement(\"button\");\n loadMoreBtn.className = \"sp-btn-ghost sp-btn-load-more\";\n setText(loadMoreBtn, this.t(\"panel.loadMore\").replace(\"{remaining}\", String(remaining)));\n loadMoreBtn.addEventListener(\"click\", () => this.loadMoreFeedbacks().catch(() => {}));\n loadMoreWrap.appendChild(loadMoreBtn);\n this.listContainer.appendChild(loadMoreWrap);\n }\n }\n\n private createCard(feedback: FeedbackResponse, number: number): HTMLElement {\n const isResolved = feedback.status === \"resolved\";\n const typeColor = getTypeColor(feedback.type, this.colors);\n\n const card = el(\"div\", {\n class: `sp-card ${isResolved ? \"sp-card--resolved\" : \"\"}`,\n });\n card.setAttribute(\"role\", \"listitem\");\n card.setAttribute(\"tabindex\", \"0\");\n card.setAttribute(\n \"aria-label\",\n `Feedback #${number}: ${getTypeLabel(feedback.type, this.t)} — ${feedback.message.slice(0, 80)}`,\n );\n card.dataset.feedbackId = feedback.id;\n\n // Color bar\n const bar = el(\"div\", { class: \"sp-card-bar\" });\n bar.style.background = isResolved ? \"#9ca3af\" : typeColor;\n\n // Body\n const body = el(\"div\", { class: \"sp-card-body\" });\n\n // Header: checkbox + #number + badge + date\n const header = el(\"div\", { class: \"sp-card-header\" });\n\n // Bulk checkbox — inline in the header row\n const checkbox = this.bulk.createCheckbox(feedback.id);\n header.appendChild(checkbox);\n\n const num = el(\"span\", { class: \"sp-card-number\" });\n setText(num, `#${number}`);\n\n const badge = el(\"span\", { class: \"sp-badge\" });\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n badge.style.background = typeBg;\n badge.style.color = typeColor;\n setText(badge, getTypeLabel(feedback.type, this.t));\n\n const date = el(\"span\", { class: \"sp-card-date\" });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(num);\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message\n const message = el(\"div\", { class: \"sp-card-message\" });\n setText(message, feedback.message);\n\n // Expand button\n const expandBtn = document.createElement(\"button\");\n expandBtn.className = \"sp-card-expand\";\n expandBtn.dataset.action = \"expand\";\n setText(expandBtn, this.t(\"panel.showMore\"));\n expandBtn.style.display = \"none\";\n expandBtn.setAttribute(\"aria-expanded\", \"false\");\n\n // Check if text is clamped (after render)\n requestAnimationFrame(() => {\n if (message.scrollHeight > message.clientHeight) {\n expandBtn.style.display = \"block\";\n }\n });\n\n // Footer: resolve button\n const footer = el(\"div\", { class: \"sp-card-footer\" });\n\n const resolveBtn = document.createElement(\"button\");\n resolveBtn.className = \"sp-btn-resolve\";\n resolveBtn.dataset.action = \"resolve\";\n if (isResolved) {\n resolveBtn.appendChild(parseSvg(ICON_UNDO));\n const span = document.createElement(\"span\");\n setText(span, ` ${this.t(\"panel.reopen\")}`);\n resolveBtn.appendChild(span);\n } else {\n resolveBtn.appendChild(parseSvg(ICON_CHECK));\n const span = document.createElement(\"span\");\n setText(span, ` ${this.t(\"panel.resolve\")}`);\n resolveBtn.appendChild(span);\n }\n\n const deleteBtn = document.createElement(\"button\");\n deleteBtn.className = \"sp-btn-delete\";\n deleteBtn.dataset.action = \"delete\";\n deleteBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteBtnLabel = document.createElement(\"span\");\n setText(deleteBtnLabel, ` ${this.t(\"panel.delete\")}`);\n deleteBtn.appendChild(deleteBtnLabel);\n\n footer.appendChild(resolveBtn);\n footer.appendChild(deleteBtn);\n\n body.appendChild(header);\n body.appendChild(message);\n body.appendChild(expandBtn);\n body.appendChild(footer);\n\n card.appendChild(bar);\n card.appendChild(body);\n\n return card;\n }\n\n // ---------------------------------------------------------------------------\n // Bulk operations\n // ---------------------------------------------------------------------------\n\n private async bulkResolve(ids: string[]): Promise<void> {\n try {\n await Promise.all(ids.map((id) => this.client.resolveFeedback(id, true)));\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n\n private async bulkDelete(ids: string[]): Promise<void> {\n try {\n await Promise.all(ids.map((id) => this.client.deleteFeedback(id)));\n for (const id of ids) this.bus.emit(\"feedback:deleted\", id);\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Existing methods (preserved)\n // ---------------------------------------------------------------------------\n\n private async confirmDeleteAll(): Promise<void> {\n const confirmed = await this.showConfirmDialog(\n this.t(\"panel.deleteAllConfirmTitle\"),\n this.t(\"panel.deleteAllConfirmMessage\"),\n );\n if (!confirmed) return;\n\n this.deleteAllBtn.disabled = true;\n try {\n await this.client.deleteAllFeedbacks(this.projectName);\n this.bus.emit(\"feedback:all-deleted\");\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.deleteAllBtn.disabled = false;\n }\n }\n\n private showConfirmDialog(title: string, message: string): Promise<boolean> {\n return new Promise((resolve) => {\n const backdrop = el(\"div\", { class: \"sp-confirm-backdrop\" });\n\n const titleId = `sp-confirm-title-${Date.now()}`;\n const messageId = `sp-confirm-msg-${Date.now()}`;\n\n const dialog = el(\"div\", { class: \"sp-confirm-dialog\" });\n dialog.setAttribute(\"role\", \"alertdialog\");\n dialog.setAttribute(\"aria-modal\", \"true\");\n dialog.setAttribute(\"aria-labelledby\", titleId);\n dialog.setAttribute(\"aria-describedby\", messageId);\n\n const titleEl = el(\"div\", { class: \"sp-confirm-title\" });\n titleEl.id = titleId;\n setText(titleEl, title);\n\n const messageEl = el(\"div\", { class: \"sp-confirm-message\" });\n messageEl.id = messageId;\n setText(messageEl, message);\n\n const btnRow = el(\"div\", { class: \"sp-confirm-actions\" });\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.type = \"button\";\n cancelBtn.className = \"sp-btn-ghost\";\n setText(cancelBtn, this.t(\"panel.cancel\"));\n\n const confirmBtn = document.createElement(\"button\");\n confirmBtn.type = \"button\";\n confirmBtn.className = \"sp-btn-danger\";\n setText(confirmBtn, this.t(\"panel.confirmDelete\"));\n\n let closed = false;\n const close = (result: boolean) => {\n if (closed) return;\n closed = true;\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n dialog.style.transform = \"translateY(8px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n resolve(result);\n }, 200);\n };\n\n // Focus trap: Tab cycles between cancel and confirm\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n close(false);\n return;\n }\n if (ke.key === \"Tab\") {\n ke.preventDefault();\n const active = (backdrop.getRootNode() as ShadowRoot).activeElement;\n if (active === cancelBtn) {\n confirmBtn.focus();\n } else {\n cancelBtn.focus();\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n cancelBtn.addEventListener(\"click\", () => close(false));\n confirmBtn.addEventListener(\"click\", () => close(true));\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) close(false);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(confirmBtn);\n dialog.appendChild(titleEl);\n dialog.appendChild(messageEl);\n dialog.appendChild(btnRow);\n backdrop.appendChild(dialog);\n\n this.root.getRootNode() instanceof ShadowRoot\n ? (this.root.getRootNode() as ShadowRoot).appendChild(backdrop)\n : this.root.appendChild(backdrop);\n\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n dialog.style.transform = \"translateY(0) scale(1)\";\n cancelBtn.focus();\n });\n });\n }\n\n private async deleteFeedback(feedback: FeedbackResponse, btn: HTMLButtonElement): Promise<void> {\n this.pendingMutations.add(feedback.id);\n const restore = setButtonLoading(btn);\n try {\n await this.client.deleteFeedback(feedback.id);\n this.bus.emit(\"feedback:deleted\", feedback.id);\n await this.loadFeedbacks();\n } catch (error) {\n restore();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.pendingMutations.delete(feedback.id);\n }\n }\n\n private async toggleResolve(feedback: FeedbackResponse, btn: HTMLButtonElement): Promise<void> {\n this.pendingMutations.add(feedback.id);\n const restore = setButtonLoading(btn);\n try {\n const newResolved = feedback.status !== \"resolved\";\n await this.client.resolveFeedback(feedback.id, newResolved);\n await this.loadFeedbacks();\n } catch (error) {\n restore();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.pendingMutations.delete(feedback.id);\n }\n }\n\n private buildTypeDropdown(): HTMLElement {\n this.typeOptions = [\n {\n value: \"all\",\n label: this.t(\"panel.filterAll\"),\n icon: ICON_LAYERS,\n color: this.colors.accent,\n bg: this.colors.accentLight,\n },\n {\n value: \"question\",\n label: this.t(\"type.question\"),\n icon: ICON_QUESTION,\n color: this.colors.typeQuestion,\n bg: this.colors.typeQuestionBg,\n },\n {\n value: \"change\",\n label: this.t(\"type.change\"),\n icon: ICON_CHANGE,\n color: this.colors.typeChange,\n bg: this.colors.typeChangeBg,\n },\n {\n value: \"bug\",\n label: this.t(\"type.bug\"),\n icon: ICON_BUG,\n color: this.colors.typeBug,\n bg: this.colors.typeBugBg,\n },\n {\n value: \"other\",\n label: this.t(\"type.other\"),\n icon: ICON_OTHER,\n color: this.colors.typeOther,\n bg: this.colors.typeOtherBg,\n },\n ];\n\n this.typeDropdownContainer = el(\"div\", { class: \"sp-filter-dropdown\" });\n\n this.typeDropdownBtn = document.createElement(\"button\");\n this.typeDropdownBtn.type = \"button\";\n this.typeDropdownBtn.className = \"sp-filter-dropdown-btn\";\n this.typeDropdownBtn.setAttribute(\"aria-haspopup\", \"listbox\");\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"false\");\n this.renderTypeDropdownTrigger();\n\n this.typeDropdownBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n if (this.typeDropdownMenu) this.closeTypeDropdown();\n else this.openTypeDropdown();\n });\n\n this.typeDropdownContainer.appendChild(this.typeDropdownBtn);\n return this.typeDropdownContainer;\n }\n\n private renderTypeDropdownTrigger(): void {\n const active = this.typeOptions.find((o) => this.activeFilters.has(o.value)) ?? this.typeOptions[0];\n if (!active) return;\n\n this.typeDropdownBtn.replaceChildren();\n this.typeDropdownBtn.style.setProperty(\"--sp-chip-color\", active.color);\n this.typeDropdownBtn.style.setProperty(\"--sp-chip-bg\", active.bg);\n this.typeDropdownBtn.dataset.filter = active.value;\n this.typeDropdownBtn.classList.toggle(\"sp-filter-dropdown-btn--filtered\", active.value !== \"all\");\n this.typeDropdownBtn.setAttribute(\"aria-label\", `${this.t(\"type.label\")}: ${active.label}`);\n\n const iconWrap = el(\"span\", { class: \"sp-filter-dropdown-btn__icon\" });\n iconWrap.appendChild(parseSvg(active.icon));\n this.typeDropdownBtn.appendChild(iconWrap);\n\n const labelWrap = el(\"span\", { class: \"sp-filter-dropdown-btn__label\" });\n const prefix = el(\"span\", { class: \"sp-filter-dropdown-btn__prefix\" });\n setText(prefix, this.t(\"type.label\"));\n const value = el(\"span\", { class: \"sp-filter-dropdown-btn__value\" });\n setText(value, active.label);\n labelWrap.appendChild(prefix);\n labelWrap.appendChild(value);\n this.typeDropdownBtn.appendChild(labelWrap);\n\n const chevron = el(\"span\", { class: \"sp-filter-dropdown-btn__chevron\" });\n chevron.appendChild(parseSvg(ICON_CHEVRON_DOWN));\n this.typeDropdownBtn.appendChild(chevron);\n }\n\n private openTypeDropdown(): void {\n this.typeDropdownMenu = el(\"div\", { class: \"sp-filter-dropdown-menu\" });\n this.typeDropdownMenu.setAttribute(\"role\", \"listbox\");\n this.typeDropdownMenu.setAttribute(\"aria-label\", this.t(\"type.label\"));\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"true\");\n\n for (const option of this.typeOptions) {\n const item = document.createElement(\"button\");\n item.type = \"button\";\n const isActive = this.activeFilters.has(option.value);\n item.className = `sp-filter-dropdown-option${isActive ? \" sp-filter-dropdown-option--active\" : \"\"}`;\n item.style.setProperty(\"--sp-chip-color\", option.color);\n item.style.setProperty(\"--sp-chip-bg\", option.bg);\n item.dataset.filter = option.value;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"aria-selected\", String(isActive));\n\n const iconWrap = el(\"span\", { class: \"sp-filter-dropdown-option__icon\" });\n iconWrap.appendChild(parseSvg(option.icon));\n item.appendChild(iconWrap);\n\n const labelEl = el(\"span\", { class: \"sp-filter-dropdown-option__label\" });\n setText(labelEl, option.label);\n item.appendChild(labelEl);\n\n if (isActive) {\n const checkWrap = el(\"span\", { class: \"sp-filter-dropdown-option__check\" });\n checkWrap.appendChild(parseSvg(ICON_CHECK));\n item.appendChild(checkWrap);\n }\n\n item.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.selectTypeFilter(option.value);\n });\n\n this.typeDropdownMenu.appendChild(item);\n }\n\n this.typeDropdownContainer.appendChild(this.typeDropdownMenu);\n\n requestAnimationFrame(() => {\n this.typeDropdownOutsideHandler = (e: MouseEvent) => {\n if (this.typeDropdownMenu && !this.typeDropdownContainer.contains(e.target as Node)) {\n this.closeTypeDropdown();\n }\n };\n document.addEventListener(\"click\", this.typeDropdownOutsideHandler, true);\n });\n\n this.typeDropdownMenu.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\") {\n this.closeTypeDropdown();\n this.typeDropdownBtn.focus();\n }\n });\n }\n\n private closeTypeDropdown(): void {\n if (this.typeDropdownMenu) {\n this.typeDropdownMenu.remove();\n this.typeDropdownMenu = null;\n }\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"false\");\n if (this.typeDropdownOutsideHandler) {\n document.removeEventListener(\"click\", this.typeDropdownOutsideHandler, true);\n this.typeDropdownOutsideHandler = null;\n }\n }\n\n private selectTypeFilter(value: string): void {\n this.activeFilters.clear();\n this.activeFilters.add(value);\n this.renderTypeDropdownTrigger();\n this.closeTypeDropdown();\n this.loadFeedbacks().catch(() => {});\n }\n\n private buildStatusSegmented(): HTMLElement {\n this.statusSegmented = new SegmentedControl<\"all\" | FeedbackStatus>({\n options: [\n {\n value: \"all\",\n label: this.t(\"panel.statusAll\"),\n icon: ICON_LAYERS,\n color: this.colors.accent,\n bg: this.colors.accentLight,\n },\n {\n value: \"open\",\n label: this.t(\"panel.statusOpen\"),\n icon: ICON_DOT_OPEN,\n color: this.colors.statusOpen,\n bg: this.colors.statusOpenBg,\n },\n {\n value: \"resolved\",\n label: this.t(\"panel.statusResolved\"),\n icon: ICON_CHECK,\n color: this.colors.statusResolved,\n bg: this.colors.statusResolvedBg,\n },\n ],\n value: \"all\",\n onChange: () => {\n this.loadFeedbacks().catch(() => {});\n },\n ariaLabel: this.t(\"status.label\"),\n datasetKey: \"statusFilter\",\n modifierPrefix: \"sp-segmented__btn--\",\n });\n\n return this.statusSegmented.element;\n }\n\n /**\n * Build the page-scope segmented control: \"this page / this type / all\".\n * The \"this type\" button is hidden when the current scope has no urlPattern\n * (host did not provide one for this route). Visibility is refreshed on\n * every `loadFeedbacks` so SPA navigation stays consistent.\n */\n private buildScopeSegmented(): HTMLElement {\n this.scopeSegmented = new SegmentedControl<\"this\" | \"template\" | \"all\">({\n options: [\n { value: \"this\", label: this.t(\"scope.thisPage\") },\n { value: \"template\", label: this.t(\"scope.thisType\") },\n { value: \"all\", label: this.t(\"scope.all\") },\n ],\n value: this.initialScopeFilter,\n onChange: () => {\n this.loadFeedbacks().catch(() => {});\n },\n ariaLabel: this.t(\"scope.label\"),\n datasetKey: \"scopeFilter\",\n modifierPrefix: \"sp-segmented__btn--scope-\",\n extraClass: \"sp-segmented--scope\",\n });\n\n // Initial visibility — \"this type\" only meaningful when scope has urlPattern\n this.syncScopeAvailability();\n return this.scopeSegmented.element;\n }\n\n /**\n * Hide the \"this type\" button when the current scope has no urlPattern, and\n * fall back to \"this page\" if it was the active selection. Called on every\n * `loadFeedbacks` so SPA navigation stays consistent.\n */\n private syncScopeAvailability(): void {\n if (!this.scopeSegmented) return;\n const scope = this.getScope();\n const showTemplate = !!scope.urlPattern;\n this.scopeSegmented.setOptionVisible(\"template\", showTemplate);\n if (!showTemplate && this.scopeSegmented.value === \"template\") {\n this.scopeSegmented.select(\"this\");\n }\n }\n\n /** Get the focused feedback (for keyboard shortcuts) */\n private getFocusedFeedback(): FeedbackResponse | undefined {\n const idx = getFocusedCardIndex(this.listContainer);\n if (idx < 0) return undefined;\n const card = this.listContainer.querySelectorAll<HTMLElement>(\".sp-card\")[idx];\n if (!card) return undefined;\n return this.feedbacks.find((f) => f.id === card.dataset.feedbackId);\n }\n\n scrollToFeedback(feedbackId: string): void {\n const escapedId = CSS.escape(feedbackId);\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${escapedId}\"]`);\n if (card) {\n card.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n card.classList.add(\"sp-anim-flash\");\n card.addEventListener(\n \"animationend\",\n () => {\n card.classList.remove(\"sp-anim-flash\");\n },\n { once: true },\n );\n }\n }\n\n /** Refresh the panel after a new feedback is submitted */\n async refresh(): Promise<void> {\n if (this.isOpen) {\n await this.loadFeedbacks();\n }\n }\n\n /** Whether the panel is currently open — used by the launcher to coordinate marker refreshes. */\n get isCurrentlyOpen(): boolean {\n return this.isOpen;\n }\n\n destroy(): void {\n this.loadController?.abort();\n if (this.searchTimeout) clearTimeout(this.searchTimeout);\n this.listContainer.removeEventListener(\"click\", this.onListClick);\n this.listContainer.removeEventListener(\"keydown\", this.onListKeydown);\n this.listContainer.removeEventListener(\"mouseover\", this.onListMouseover);\n this.listContainer.removeEventListener(\"mouseout\", this.onListMouseout);\n document.removeEventListener(\"sp-marker-click\", this.onMarkerClick);\n this.closeTypeDropdown();\n this.sortControls.destroy();\n this.bulk.destroy();\n this.exportBtn.destroy();\n this.shortcuts.destroy();\n this.detail.destroy();\n this.root.remove();\n }\n}\n"]}
|