@adia-ai/web-modules 0.8.19 → 0.8.20

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog — @adia-ai/web-modules
2
2
 
3
+ ## [0.8.20] — 2026-07-28
4
+
5
+ ### Fixed
6
+ - **The npm tarball no longer ships `*.test.js`** (gh#462) — the `files` roster excluded examples/html but never unit tests, so 13 test file(s) rode the 0.8.19 tarball. `!**/*.test.js` appended as the roster's LAST entry (npm's files globbing is order-sensitive — a leading exclude is overridden by later directory includes). Proof: `npm pack --dry-run` → 0 test files, runtime files intact.
7
+ - **The `form/` cluster is importable by subpath** (gh#457) — 0.8.19 shipped the files (gh#448) but the `exports` map was never extended, so `@adia-ai/web-modules/form/...` threw `ERR_PACKAGE_PATH_NOT_EXPORTED` and only the whole-package barrel reached `<form-popover-ui>`. Added the `./form`, `./form/*`, and `./form/*.css` stanzas mirroring every sibling cluster. Known residue, not fixed here: the module ships no `.d.ts`, so the `types` conditions point ahead of reality until types land.
8
+
9
+ ### Maintenance
10
+ - **`dist/` bundles rebuilt** in this cut's window (1 file(s)) — regenerated from the source changes described above, not independent edits.
11
+
3
12
  ## [0.8.19] — 2026-07-27
4
13
 
5
14
  ### Fixed
@@ -246,12 +246,12 @@ Correct shape for <chart-ui x="label" y="value">:
246
246
  <button-ui data-tour-next variant="primary" size="sm" text="${i?"Done":"Next \u2192"}"></button-ui>
247
247
  </div>
248
248
  </div>
249
- `;try{this.#e.showPopover()}catch{}this.#i?.(),l?this.#i=ut(l,this.#e,{placement:o,gap:12}):(this.#e.style.position="fixed",this.#e.style.top="50%",this.#e.style.left="50%",this.#e.style.transform="translate(-50%, -50%)"),queueMicrotask(()=>this.#e?.focus?.())}#d=null;#f(){if(!this.#t)return;let t=this.#d;if(!t){this.#t.setAttribute("data-tour-no-target","");return}this.#t.removeAttribute("data-tour-no-target");let e=t.getBoundingClientRect(),i=getComputedStyle(this),r=parseFloat(i.getPropertyValue("--tour-spotlight-padding"))||8,n=Math.max(0,e.top-r),o=Math.max(0,e.left-r),a=e.width+r*2,l=e.height+r*2;this.#t.style.top=`${n}px`,this.#t.style.left=`${o}px`,this.#t.style.width=`${a}px`,this.#t.style.height=`${l}px`}#p=t=>{let e=t.target;if(!(!e||!e.closest)){if(e.closest("[data-tour-skip]")){this.skip();return}if(e.closest("[data-tour-previous]")){this.previous();return}if(e.closest("[data-tour-next]")){this.next();return}}}},Co=class extends v{static properties={target:{type:String,default:"",reflect:!0},title:{type:String,default:"",reflect:!0},placement:{type:String,default:"bottom",reflect:!0}};static template=()=>null};function p5(s){return String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}S("tour-ui",Eo),S("tour-step-ui",Co);C();var y1="data-toolbar-spillover",m5="data-toolbar-spillover-menu",v1=8,ld="data-toolbar-spillover-label";function x1(s){return s?.tagName&&s.tagName.toLowerCase()==="divider-ui"}function g5(s){return s?s.split("-").filter(Boolean).map(t=>t[0].toUpperCase()+t.slice(1)).join(" "):""}function b5(s){let t=s.matches?.("button-ui")?[s]:Array.from(s.querySelectorAll?.("button-ui")||[]);for(let e of t){if(e.hasAttribute(ld)||e.getAttribute("text"))continue;let i=e.getAttribute("aria-label")||g5(e.getAttribute("icon"));i&&(e.setAttribute(ld,""),e.setAttribute("text",i))}}function O5(s){let t=s.matches?.("button-ui")?[s]:Array.from(s.querySelectorAll?.("button-ui")||[]);for(let e of t)e.hasAttribute(ld)&&(e.removeAttribute(ld),e.removeAttribute("text"))}function S1(s){let t=s.getBoundingClientRect(),e=getComputedStyle(s),i=parseFloat(e.marginLeft)||0,r=parseFloat(e.marginRight)||0;return t.width+i+r}var $o=class extends v{static properties={gap:{type:String,default:"sm",reflect:!0},align:{type:String,default:"start",reflect:!0},overflow:{type:String,default:"menu",reflect:!0},bordered:{type:Boolean,default:!1,reflect:!0}};static template=()=>null;#t=null;#e=null;#i=null;#s=null;#r=null;#n=!1;#a=!1;#o=null;#l=null;connected(){this.setAttribute("role","toolbar"),this.#h(),typeof ResizeObserver<"u"&&(this.#t=new ResizeObserver(()=>this.#O()),this.#t.observe(this)),typeof MutationObserver<"u"&&(this.#e=new MutationObserver(()=>{this.#n||this.#O()})),this.#y(),this.#O()}disconnected(){this.#o!=null&&(cancelAnimationFrame(this.#o),this.#o=null),this.#a=!1,this.#t?.disconnect(),this.#e?.disconnect(),this.#u(),this.#t=null,this.#e=null,this.#i=null,this.#s=null}#h(){if(this.#i)return;let t=document.createElement("button-ui");t.setAttribute("icon","dots-three"),t.setAttribute("variant","ghost"),t.setAttribute("size","sm"),t.setAttribute(y1,""),t.setAttribute("aria-label","More actions"),t.setAttribute("aria-haspopup","menu"),t.hidden=!0;let e=document.createElement("div");e.setAttribute(m5,""),e.setAttribute("popover","manual"),e.setAttribute("role","menu"),t.addEventListener("click",this.#d),e.addEventListener("click",this.#f),e.addEventListener("toggle",this.#g),this.appendChild(t),this.appendChild(e),this.#i=t,this.#s=e}#c(){let t=this.#s;!t||t.matches(":popover-open")||(t.showPopover?.(),this.#r?.(),this.#r=ut(this.#i,t,{placement:"bottom-end",gap:4}),this.#l=requestAnimationFrame(()=>{this.#l=null,document.addEventListener("pointerdown",this.#p,!0),document.addEventListener("keydown",this.#m,!0)}))}#u(){this.#r?.(),this.#r=null,this.#s?.matches(":popover-open")&&this.#s.hidePopover?.(),this.#l!=null&&(cancelAnimationFrame(this.#l),this.#l=null),document.removeEventListener("pointerdown",this.#p,!0),document.removeEventListener("keydown",this.#m,!0)}#d=t=>{t.stopPropagation(),this.#s?.matches(":popover-open")?this.#u():this.#c()};#f=t=>{let e=t.target.closest("button-ui");e&&(e.matches(`[${y1}]`)||queueMicrotask(()=>this.#u()))};#p=t=>{if(this.#i?.contains(t.target)||this.#s?.contains(t.target))return;let e=t.composedPath?.()||[];for(let i of e){if(i===document)break;if(i?.nodeType===1&&i.hasAttribute?.("popover"))return}this.#u()};#m=t=>{t.key==="Escape"&&(t.stopPropagation(),this.#u(),this.#i?.focus?.({preventScroll:!0}))};#g=t=>{t.newState==="closed"&&(this.#r?.(),this.#r=null,this.#l!=null&&(cancelAnimationFrame(this.#l),this.#l=null),document.removeEventListener("pointerdown",this.#p,!0),document.removeEventListener("keydown",this.#m,!0))};#O(){this.#a||(this.#a=!0,this.#o=requestAnimationFrame(()=>{this.#o=null,this.#a=!1,this.isConnected&&this.#x()}))}#y(){this.#e?.observe(this,{childList:!0})}#b(){this.#e&&(this.#e.disconnect(),this.#e.takeRecords())}#x(){if(!this.isConnected)return;let t=this.#i,e=this.#s;if(!(!t||!e)){this.#n=!0,this.#b();try{for(;e.firstChild;)O5(e.firstChild),this.insertBefore(e.firstChild,t);let i=0;for(let y of this.children)y===t||y===e||(y.dataset.toolbarOrder==null&&(y.dataset.toolbarOrder=String(i)),i+=1);let r=Array.from(this.children).filter(y=>y!==t&&y!==e).sort((y,x)=>Number(y.dataset.toolbarOrder)-Number(x.dataset.toolbarOrder));for(let y of r)this.insertBefore(y,t);let n=r;for(let y of n)y.hidden=!1;t.hidden=!0;let o=getComputedStyle(this),a=parseFloat(o.paddingLeft)||0,l=parseFloat(o.paddingRight)||0,h=parseFloat(o.columnGap||o.gap)||0,c=this.clientWidth-a-l,u=n.map(y=>S1(y)),d=u.reduce((y,x)=>y+x,0)+Math.max(0,n.length-1)*h,f=d<=c-v1;if(this.overflow==="none"||f)return;t.hidden=!1;let p=S1(t),m=n.length,b=d;for(;m>0&&!(b+h+p<=c-v1);)m-=1,b-=u[m],m>0&&(b-=h);for(;m>0&&x1(n[m-1]);)m-=1;let g=n.slice(m);for(let y of g){if(x1(y)){y.hidden=!0;continue}b5(y),e.appendChild(y)}e.firstElementChild||(t.hidden=!0)}finally{this.#n=!1,queueMicrotask(()=>{this.#e?.takeRecords(),this.#y()})}}}},Po=class extends v{static template=()=>null;connected(){this.setAttribute("role","group")}};S("toolbar-ui",$o),S("toolbar-group-ui",Po);C();var Qo=class extends v{static properties={variant:{type:String,default:"primary",reflect:!0},collapsed:{type:Boolean,default:!1,reflect:!0},divider:{type:Boolean,default:!1,reflect:!0},heading:{type:String,default:"",reflect:!0}};static template=()=>null;#t=null;connected(){this.setAttribute("role","navigation"),this.heading&&this.setAttribute("aria-label",this.heading),this.addEventListener("click",this.#i),this.variant!=="section"&&typeof ResizeObserver<"u"&&(this.#t=new ResizeObserver(()=>this.#e()),this.#t.observe(this))}render(){this.heading?this.setAttribute("aria-label",this.heading):this.removeAttribute("aria-label"),this.variant!=="section"&&this.#e()}#e(){let t=this.collapsed||this.getBoundingClientRect().width<=96;for(let e of this.querySelectorAll(":scope > nav-group-ui")){let i=e.querySelector(':scope > [slot="header"]');i&&(i.title=t?e.text:"")}for(let e of this.querySelectorAll(":scope > nav-item-ui"))e.title=t?e.text:""}get selectedItem(){return this.querySelector("nav-item-ui[selected]")}select(t){let e=this.selectedItem;e&&e!==t&&e.removeAttribute("selected"),t&&(t.setAttribute("selected",""),this.dispatchEvent(new CustomEvent("nav-select",{bubbles:!0,detail:{item:t,text:t.text,value:t.value}})))}toggle(){this.variant!=="section"&&(this.collapsed=!this.collapsed)}#i=t=>{let e=t.target.closest("nav-item-ui");if(e&&this.contains(e)){if(e.disabled)return;this.select(e),this.#s();return}if(this.variant==="section")return;let i=t.target.closest("nav-group-ui");if(i&&this.contains(i))if(this.collapsed||this.getBoundingClientRect().width<=96){if(t.target.closest("[popover]"))return;i.showPopover?.()}else{let n=i.querySelector(':scope > [slot="header"]');n&&(t.target===n||n.contains(t.target))&&(i.open=!i.open)}};#s(){this.style.pointerEvents="none",requestAnimationFrame(()=>{this.style.pointerEvents=""})}disconnected(){this.removeEventListener("click",this.#i),this.#t?.disconnect(),this.#t=null}};S("nav-ui",Qo);C();var To=class extends v{static properties={text:{type:String,default:"",reflect:!0},icon:{type:String,default:"",reflect:!0},badge:{type:String,default:"",reflect:!0},open:{type:Boolean,default:!1,reflect:!0},collapsible:{type:Boolean,default:!0,reflect:!0},variant:{type:String,default:"",reflect:!0}};static template=()=>null;#t=null;#e=null;#i=null;#s=t=>{this.collapsible&&(t.key==="Enter"||t.key===" ")&&(t.preventDefault(),this.open=!this.open,this.dispatchEvent(new CustomEvent("group-toggle",{bubbles:!0,detail:{text:this.text,open:this.open}})))};connected(){this.setAttribute("role","group"),nt(this,"header").length?this.#i=nt(this,"header")[0]:(this.#i=document.createElement("div"),this.#i.setAttribute("slot","header"),this.#i.setAttribute("tabindex","0"),this.#i.innerHTML=`
249
+ `;try{this.#e.showPopover()}catch{}this.#i?.(),l?this.#i=ut(l,this.#e,{placement:o,gap:12}):(this.#e.style.position="fixed",this.#e.style.top="50%",this.#e.style.left="50%",this.#e.style.transform="translate(-50%, -50%)"),queueMicrotask(()=>this.#e?.focus?.())}#d=null;#f(){if(!this.#t)return;let t=this.#d;if(!t){this.#t.setAttribute("data-tour-no-target","");return}this.#t.removeAttribute("data-tour-no-target");let e=t.getBoundingClientRect(),i=getComputedStyle(this),r=parseFloat(i.getPropertyValue("--tour-spotlight-padding"))||8,n=Math.max(0,e.top-r),o=Math.max(0,e.left-r),a=e.width+r*2,l=e.height+r*2;this.#t.style.top=`${n}px`,this.#t.style.left=`${o}px`,this.#t.style.width=`${a}px`,this.#t.style.height=`${l}px`}#p=t=>{let e=t.target;if(!(!e||!e.closest)){if(e.closest("[data-tour-skip]")){this.skip();return}if(e.closest("[data-tour-previous]")){this.previous();return}if(e.closest("[data-tour-next]")){this.next();return}}}},Co=class extends v{static properties={target:{type:String,default:"",reflect:!0},title:{type:String,default:"",reflect:!0},placement:{type:String,default:"bottom",reflect:!0}};static template=()=>null};function p5(s){return String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}S("tour-ui",Eo),S("tour-step-ui",Co);C();var y1="data-toolbar-spillover",m5="data-toolbar-spillover-menu",v1=8,ld="data-toolbar-spillover-label";function x1(s){return s?.tagName&&s.tagName.toLowerCase()==="divider-ui"}function g5(s){return s?s.split("-").filter(Boolean).map(t=>t[0].toUpperCase()+t.slice(1)).join(" "):""}function b5(s){let t=s.matches?.("button-ui")?[s]:Array.from(s.querySelectorAll?.("button-ui")||[]);for(let e of t){if(e.hasAttribute(ld)||e.getAttribute("text"))continue;let i=e.getAttribute("aria-label")||g5(e.getAttribute("icon"));i&&(e.setAttribute(ld,""),e.setAttribute("text",i))}}function O5(s){let t=s.matches?.("button-ui")?[s]:Array.from(s.querySelectorAll?.("button-ui")||[]);for(let e of t)e.hasAttribute(ld)&&(e.removeAttribute(ld),e.removeAttribute("text"))}function S1(s){let t=s.getBoundingClientRect(),e=getComputedStyle(s),i=parseFloat(e.marginLeft)||0,r=parseFloat(e.marginRight)||0;return t.width+i+r}var $o=class extends v{static properties={gap:{type:String,default:"sm",reflect:!0},align:{type:String,default:"start",reflect:!0},overflow:{type:String,default:"menu",reflect:!0},bordered:{type:Boolean,default:!1,reflect:!0}};static template=()=>null;#t=null;#e=null;#i=null;#s=null;#r=null;#n=!1;#a=!1;#o=null;#l=null;connected(){this.setAttribute("role","toolbar"),this.#h(),typeof ResizeObserver<"u"&&(this.#t=new ResizeObserver(()=>this.#O()),this.#t.observe(this)),typeof MutationObserver<"u"&&(this.#e=new MutationObserver(()=>{this.#n||this.#O()})),this.#y(),this.#O()}disconnected(){this.#o!=null&&(cancelAnimationFrame(this.#o),this.#o=null),this.#a=!1,this.#t?.disconnect(),this.#e?.disconnect(),this.#u(),this.#t=null,this.#e=null,this.#i=null,this.#s=null}#h(){if(this.#i)return;let t=document.createElement("button-ui");t.setAttribute("icon","dots-three"),t.setAttribute("variant","ghost"),t.setAttribute("size","sm"),t.setAttribute(y1,""),t.setAttribute("aria-label","More actions"),t.setAttribute("aria-haspopup","menu"),t.hidden=!0;let e=document.createElement("div");e.setAttribute(m5,""),e.setAttribute("popover","manual"),e.setAttribute("role","menu"),t.addEventListener("click",this.#d),e.addEventListener("click",this.#f),e.addEventListener("toggle",this.#g),this.appendChild(t),this.appendChild(e),this.#i=t,this.#s=e}#c(){let t=this.#s;!t||t.matches(":popover-open")||(t.showPopover?.(),this.#r?.(),this.#r=ut(this.#i,t,{placement:"bottom-end",gap:4}),this.#l=requestAnimationFrame(()=>{this.#l=null,document.addEventListener("pointerdown",this.#p,!0),document.addEventListener("keydown",this.#m,!0)}))}#u(){this.#r?.(),this.#r=null,this.#s?.matches(":popover-open")&&this.#s.hidePopover?.(),this.#l!=null&&(cancelAnimationFrame(this.#l),this.#l=null),document.removeEventListener("pointerdown",this.#p,!0),document.removeEventListener("keydown",this.#m,!0)}#d=t=>{t.stopPropagation(),this.#s?.matches(":popover-open")?this.#u():this.#c()};#f=t=>{let e=t.target.closest("button-ui");e&&(e.matches(`[${y1}]`)||queueMicrotask(()=>this.#u()))};#p=t=>{if(this.#i?.contains(t.target)||this.#s?.contains(t.target))return;let e=t.composedPath?.()||[];for(let i of e){if(i===document)break;if(i?.nodeType===1&&i.hasAttribute?.("popover"))return}this.#u()};#m=t=>{t.key==="Escape"&&(t.stopPropagation(),this.#u(),this.#i?.focus?.({preventScroll:!0}))};#g=t=>{t.newState==="closed"&&(this.#r?.(),this.#r=null,this.#l!=null&&(cancelAnimationFrame(this.#l),this.#l=null),document.removeEventListener("pointerdown",this.#p,!0),document.removeEventListener("keydown",this.#m,!0))};#O(){this.#a||(this.#a=!0,this.#o=requestAnimationFrame(()=>{this.#o=null,this.#a=!1,this.isConnected&&this.#x()}))}#y(){this.#e?.observe(this,{childList:!0})}#b(){this.#e&&(this.#e.disconnect(),this.#e.takeRecords())}#x(){if(!this.isConnected)return;let t=this.#i,e=this.#s;if(!(!t||!e)){this.#n=!0,this.#b();try{for(;e.firstChild;)O5(e.firstChild),this.insertBefore(e.firstChild,t);let i=0;for(let y of this.children)y===t||y===e||(y.dataset.toolbarOrder==null&&(y.dataset.toolbarOrder=String(i)),i+=1);let r=Array.from(this.children).filter(y=>y!==t&&y!==e).sort((y,x)=>Number(y.dataset.toolbarOrder)-Number(x.dataset.toolbarOrder));for(let y of r)this.insertBefore(y,t);let n=r;for(let y of n)y.hidden=!1;t.hidden=!0;let o=getComputedStyle(this),a=parseFloat(o.paddingLeft)||0,l=parseFloat(o.paddingRight)||0,h=parseFloat(o.columnGap||o.gap)||0,c=this.clientWidth-a-l,u=n.map(y=>S1(y)),d=u.reduce((y,x)=>y+x,0)+Math.max(0,n.length-1)*h,f=d<=c-v1;if(this.overflow==="none"||f)return;t.hidden=!1;let p=S1(t),m=n.length,b=d;for(;m>0&&!(b+h+p<=c-v1);)m-=1,b-=u[m],m>0&&(b-=h);for(;m>0&&x1(n[m-1]);)m-=1;let g=n.slice(m);for(let y of g){if(x1(y)){y.hidden=!0;continue}b5(y),e.appendChild(y)}e.firstElementChild||(t.hidden=!0)}finally{this.#n=!1,queueMicrotask(()=>{this.#e?.takeRecords(),this.#y()})}}}},Po=class extends v{static template=()=>null;connected(){this.setAttribute("role","group")}};S("toolbar-ui",$o),S("toolbar-group-ui",Po);C();var Qo=class extends v{static properties={variant:{type:String,default:"primary",reflect:!0},collapsed:{type:Boolean,default:!1,reflect:!0},divider:{type:Boolean,default:!1,reflect:!0},heading:{type:String,default:"",reflect:!0}};static template=()=>null;#t=null;connected(){this.setAttribute("role","navigation"),this.heading&&this.setAttribute("aria-label",this.heading),this.addEventListener("click",this.#i),this.variant!=="section"&&typeof ResizeObserver<"u"&&(this.#t=new ResizeObserver(()=>this.#e()),this.#t.observe(this))}render(){this.heading?this.setAttribute("aria-label",this.heading):this.removeAttribute("aria-label"),this.variant!=="section"&&this.#e()}#e(){let t=this.collapsed||this.getBoundingClientRect().width<=96;for(let e of this.querySelectorAll(":scope > nav-group-ui")){let i=e.querySelector(':scope > [slot="header"]');i&&(i.title=t?e.text:"")}for(let e of this.querySelectorAll(":scope > nav-item-ui"))e.title=t?e.text:""}get selectedItem(){return this.querySelector("nav-item-ui[selected]")}select(t){let e=this.selectedItem;e&&e!==t&&e.removeAttribute("selected"),t&&(t.setAttribute("selected",""),this.dispatchEvent(new CustomEvent("nav-select",{bubbles:!0,detail:{item:t,text:t.text,value:t.value}})))}toggle(){this.variant!=="section"&&(this.collapsed=!this.collapsed)}#i=t=>{let e=t.target.closest("nav-item-ui");if(e&&this.contains(e)){if(e.disabled)return;this.select(e),this.#s();return}if(this.variant==="section")return;let i=t.target.closest("nav-group-ui");if(i&&this.contains(i))if(this.collapsed||this.getBoundingClientRect().width<=96){if(t.target.closest("[popover]"))return;i.showPopover?.()}else{let n=i.querySelector(':scope > [slot="header"]');n&&(t.target===n||n.contains(t.target))&&(i.open=!i.open)}};#s(){this.style.pointerEvents="none",requestAnimationFrame(()=>{this.style.pointerEvents=""})}disconnected(){this.removeEventListener("click",this.#i),this.#t?.disconnect(),this.#t=null}};S("nav-ui",Qo);C();var To=class extends v{static properties={text:{type:String,default:"",reflect:!0},icon:{type:String,default:"",reflect:!0},badge:{type:String,default:"",reflect:!0},open:{type:Boolean,default:!1,reflect:!0},selected:{type:Boolean,default:!1,reflect:!0},collapsible:{type:Boolean,default:!0,reflect:!0},variant:{type:String,default:"",reflect:!0}};static template=()=>null;#t=null;#e=null;#i=null;#s=t=>{this.collapsible&&(t.key==="Enter"||t.key===" ")&&(t.preventDefault(),this.open=!this.open,this.dispatchEvent(new CustomEvent("group-toggle",{bubbles:!0,detail:{text:this.text,open:this.open}})))};connected(){this.setAttribute("role","group"),nt(this,"header").length?this.#i=nt(this,"header")[0]:(this.#i=document.createElement("div"),this.#i.setAttribute("slot","header"),this.#i.setAttribute("tabindex","0"),this.#i.innerHTML=`
250
250
  <span slot="icon">${this.icon?`<icon-ui name="${this.icon}"></icon-ui>`:""}</span>
251
251
  <span slot="text">${this.text}</span>
252
252
  ${this.badge?`<span slot="badge">${this.badge}</span>`:""}
253
253
  <icon-ui slot="caret" name="caret-right"></icon-ui>
254
- `,this.prepend(this.#i)),this.#i?.addEventListener("keydown",this.#s)}render(){let t=this.querySelector('[slot="header"] [slot="text"]');t&&(t.textContent=this.text);let e=this.querySelector('[slot="header"] [slot="badge"]');e&&(e.textContent=this.badge),this.setAttribute("aria-expanded",String(this.open));let i=this.querySelector('[slot="header"] [slot="icon"] icon-ui');i&&i.setAttribute("weight",this.open?"fill":"regular")}showPopover(){if(!this.#t){this.#t=document.createElement("div"),this.#t.setAttribute("slot","popover"),this.#t.setAttribute("popover","auto");let t=document.createElement("div");t.setAttribute("slot","popover-label"),t.textContent=this.text,this.#t.appendChild(t);for(let e of this.querySelectorAll(":scope > nav-item-ui")){let i=document.createElement("div");i.setAttribute("role","option"),i.dataset.sourceValue=e.getAttribute("value")||"",i.textContent=e.text,i.addEventListener("click",()=>{let r=this.closest("nav-ui");r&&r.select(e),this.#t.hidePopover()}),this.#t.appendChild(i)}this.appendChild(this.#t),this.#t.addEventListener("toggle",e=>{e.newState==="closed"&&(this.#e?.(),this.#e=null)})}for(let t of this.#t.querySelectorAll('[role="option"]')){let e=t.dataset.sourceValue;(e?this.querySelector(`:scope > nav-item-ui[value="${e}"]`):null)?.hasAttribute("selected")?(t.setAttribute("aria-current","page"),t.setAttribute("aria-selected","true")):(t.removeAttribute("aria-current"),t.removeAttribute("aria-selected"))}this.#t.showPopover(),this.#e?.(),this.#e=ut(this,this.#t,{placement:"right",gap:4})}disconnected(){this.#i?.removeEventListener("keydown",this.#s),this.#e?.(),this.#e=null,this.#t?.hidePopover?.()}};S("nav-group-ui",To);C();var Lo=class extends v{static properties={text:{type:String,default:"",reflect:!0},icon:{type:String,default:"",reflect:!0},value:{type:String,default:"",reflect:!0},badge:{type:String,default:"",reflect:!0},selected:{type:Boolean,default:!1,reflect:!0},disabled:{type:Boolean,default:!1,reflect:!0},variant:{type:String,default:"",reflect:!0}};static template=()=>null;#t=t=>{if(this.disabled){t.preventDefault();return}this.closest("nav-ui")?.select?.(this),this.dispatchEvent(new CustomEvent("nav-select",{bubbles:!0,detail:{item:this,text:this.text,value:this.value}}))};#e=t=>{this.disabled||(t.key==="Enter"||t.key===" ")&&(t.preventDefault(),this.#t(t))};connected(){this.setAttribute("role","link"),this.setAttribute("tabindex",this.disabled?"-1":"0"),this.querySelector('[slot="text"]')||(this.innerHTML=`
254
+ `,this.prepend(this.#i)),this.#i?.addEventListener("keydown",this.#s)}render(){let t=this.querySelector('[slot="header"] [slot="text"]');t&&(t.textContent=this.text);let e=this.querySelector('[slot="header"] [slot="badge"]');e&&(e.textContent=this.badge),this.setAttribute("aria-expanded",String(this.open));let i=this.querySelector('[slot="header"] [slot="icon"] icon-ui');i&&i.setAttribute("weight",this.hasAttribute("selected")?"fill":"regular")}showPopover(){if(!this.#t){this.#t=document.createElement("div"),this.#t.setAttribute("slot","popover"),this.#t.setAttribute("popover","auto");let t=document.createElement("div");t.setAttribute("slot","popover-label"),t.textContent=this.text,this.#t.appendChild(t);for(let e of this.querySelectorAll(":scope > nav-item-ui")){let i=document.createElement("div");i.setAttribute("role","option"),i.dataset.sourceValue=e.getAttribute("value")||"",i.textContent=e.text,i.addEventListener("click",()=>{let r=this.closest("nav-ui");r&&r.select(e),this.#t.hidePopover()}),this.#t.appendChild(i)}this.appendChild(this.#t),this.#t.addEventListener("toggle",e=>{e.newState==="closed"&&(this.#e?.(),this.#e=null)})}for(let t of this.#t.querySelectorAll('[role="option"]')){let e=t.dataset.sourceValue;(e?this.querySelector(`:scope > nav-item-ui[value="${e}"]`):null)?.hasAttribute("selected")?(t.setAttribute("aria-current","page"),t.setAttribute("aria-selected","true")):(t.removeAttribute("aria-current"),t.removeAttribute("aria-selected"))}this.#t.showPopover(),this.#e?.(),this.#e=ut(this,this.#t,{placement:"right",gap:4})}disconnected(){this.#i?.removeEventListener("keydown",this.#s),this.#e?.(),this.#e=null,this.#t?.hidePopover?.()}};S("nav-group-ui",To);C();var Lo=class extends v{static properties={text:{type:String,default:"",reflect:!0},icon:{type:String,default:"",reflect:!0},value:{type:String,default:"",reflect:!0},badge:{type:String,default:"",reflect:!0},selected:{type:Boolean,default:!1,reflect:!0},disabled:{type:Boolean,default:!1,reflect:!0},variant:{type:String,default:"",reflect:!0}};static template=()=>null;#t=t=>{if(this.disabled){t.preventDefault();return}this.closest("nav-ui")?.select?.(this),this.dispatchEvent(new CustomEvent("nav-select",{bubbles:!0,detail:{item:this,text:this.text,value:this.value}}))};#e=t=>{this.disabled||(t.key==="Enter"||t.key===" ")&&(t.preventDefault(),this.#t(t))};connected(){this.setAttribute("role","link"),this.setAttribute("tabindex",this.disabled?"-1":"0"),this.querySelector('[slot="text"]')||(this.innerHTML=`
255
255
  <span slot="icon">${this.icon?`<icon-ui name="${this.icon}"></icon-ui>`:""}</span>
256
256
  <span slot="text">${this.text}</span>
257
257
  ${this.badge?`<span slot="badge">${this.badge}</span>`:""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adia-ai/web-modules",
3
- "version": "0.8.19",
3
+ "version": "0.8.20",
4
4
  "description": "AdiaUI composite custom elements \u2014 shell, chat, editor, runtime clusters built from @adia-ai/web-components primitives. Subpath exports per cluster.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -203,6 +203,20 @@
203
203
  "import": "./generative/index.js",
204
204
  "default": "./generative/index.js"
205
205
  },
206
+ "./form": {
207
+ "types": "./form/index.d.ts",
208
+ "import": "./form/index.js",
209
+ "default": "./form/index.js"
210
+ },
211
+ "./form/*": {
212
+ "types": "./form/*/*.d.ts",
213
+ "import": "./form/*/*.js",
214
+ "default": "./form/*/*.js"
215
+ },
216
+ "./form/*.css": {
217
+ "types": "./css-module.d.ts",
218
+ "default": "./form/*/*.css"
219
+ },
206
220
  "./package.json": "./package.json"
207
221
  },
208
222
  "files": [
@@ -239,6 +253,7 @@
239
253
  "!form/**/*.examples.html",
240
254
  "!form/**/*.examples.js",
241
255
  "!form/**/*.html",
256
+ "!**/*.test.js",
242
257
  "index.js",
243
258
  "css-module.d.ts",
244
259
  "web-modules.sheet.d.ts",
@@ -1,112 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import '../../../web-components/core/element.js';
3
- import './chat-composer.js';
4
-
5
- const tick = () => new Promise((r) => queueMicrotask(r));
6
-
7
- function mount(html) {
8
- const wrap = document.createElement('div');
9
- wrap.innerHTML = html;
10
- document.body.appendChild(wrap);
11
- return wrap.firstElementChild;
12
- }
13
-
14
- beforeEach(() => {
15
- document.body.innerHTML = '';
16
- });
17
-
18
- describe('chat-composer', () => {
19
- it('registers chat-composer as a custom element', () => {
20
- expect(customElements.get('chat-composer')).toBeDefined();
21
- });
22
-
23
- it('defaults to disabled=false', () => {
24
- const c = mount('<chat-composer></chat-composer>');
25
- expect(c.disabled).toBe(false);
26
- });
27
-
28
- it('reflects [disabled] via property assignment', async () => {
29
- const c = mount('<chat-composer></chat-composer>');
30
- c.disabled = true;
31
- await tick();
32
- expect(c.hasAttribute('disabled')).toBe(true);
33
- });
34
-
35
- it('exposes .focus() / .clear() / .input getter', () => {
36
- const c = mount('<chat-composer></chat-composer>');
37
- expect(typeof c.focus).toBe('function');
38
- expect(typeof c.clear).toBe('function');
39
- expect('input' in c).toBe(true);
40
- });
41
-
42
- it('returns null .input when no inner input element', () => {
43
- const c = mount('<chat-composer></chat-composer>');
44
- expect(c.input).toBeNull();
45
- });
46
-
47
- it('forwards inner submit as composer-submit event', async () => {
48
- // Plain input-like element with submit dispatch
49
- const wrap = document.createElement('div');
50
- wrap.innerHTML = `<chat-composer>
51
- <chat-input-ui></chat-input-ui>
52
- </chat-composer>`;
53
- document.body.appendChild(wrap);
54
- const composer = wrap.firstElementChild;
55
- const innerInput = composer.querySelector('chat-input-ui');
56
-
57
- const onComposerSubmit = vi.fn();
58
- composer.addEventListener('composer-submit', onComposerSubmit);
59
-
60
- innerInput.dispatchEvent(new CustomEvent('submit', { detail: { text: 'hello' } }));
61
- await tick();
62
-
63
- expect(onComposerSubmit).toHaveBeenCalledTimes(1);
64
- expect(onComposerSubmit.mock.calls[0][0].detail).toEqual({ text: 'hello' });
65
- });
66
-
67
- it('propagates [disabled] to inner input via attribute', async () => {
68
- const wrap = document.createElement('div');
69
- wrap.innerHTML = `<chat-composer>
70
- <chat-input-ui></chat-input-ui>
71
- </chat-composer>`;
72
- document.body.appendChild(wrap);
73
- const composer = wrap.firstElementChild;
74
- const innerInput = composer.querySelector('chat-input-ui');
75
-
76
- composer.disabled = true;
77
- await tick();
78
-
79
- expect(innerInput.hasAttribute('disabled')).toBe(true);
80
-
81
- composer.disabled = false;
82
- await tick();
83
-
84
- expect(innerInput.hasAttribute('disabled')).toBe(false);
85
- });
86
-
87
- it('cleanup on disconnect — removes inner submit listener', () => {
88
- const wrap = document.createElement('div');
89
- wrap.innerHTML = `<chat-composer>
90
- <chat-input-ui></chat-input-ui>
91
- </chat-composer>`;
92
- document.body.appendChild(wrap);
93
- const composer = wrap.firstElementChild;
94
- const innerInput = composer.querySelector('chat-input-ui');
95
- const removeSpy = vi.spyOn(innerInput, 'removeEventListener');
96
-
97
- composer.remove();
98
-
99
- const removedTypes = removeSpy.mock.calls.map((args) => args[0]);
100
- expect(removedTypes).toContain('submit');
101
- });
102
-
103
- it('handles input-ui as inner input fallback', () => {
104
- const wrap = document.createElement('div');
105
- wrap.innerHTML = `<chat-composer>
106
- <input-ui></input-ui>
107
- </chat-composer>`;
108
- document.body.appendChild(wrap);
109
- const composer = wrap.firstElementChild;
110
- expect(composer.input?.tagName?.toLowerCase()).toBe('input-ui');
111
- });
112
- });
@@ -1,110 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import '../../../web-components/core/element.js';
3
- import './chat-sidebar.js';
4
-
5
- const tick = () => new Promise((r) => queueMicrotask(r));
6
-
7
- function mount(html) {
8
- const wrap = document.createElement('div');
9
- wrap.innerHTML = html;
10
- document.body.appendChild(wrap);
11
- return wrap.firstElementChild;
12
- }
13
-
14
- let originalRect;
15
- beforeEach(() => {
16
- document.body.innerHTML = '';
17
- try { localStorage.clear(); } catch {}
18
- globalThis.ResizeObserver = class {
19
- observe() {} unobserve() {} disconnect() {}
20
- };
21
- originalRect = HTMLElement.prototype.getBoundingClientRect;
22
- HTMLElement.prototype.getBoundingClientRect = function () {
23
- const inline = this.style?.width || '';
24
- const w = parseFloat(inline) || 240;
25
- return { width: w, height: 600, top: 0, left: 0, right: w, bottom: 600, x: 0, y: 0 };
26
- };
27
- });
28
-
29
- afterEach(() => {
30
- if (originalRect) HTMLElement.prototype.getBoundingClientRect = originalRect;
31
- });
32
-
33
- describe('chat-sidebar', () => {
34
- it('registers chat-sidebar as a custom element', () => {
35
- expect(customElements.get('chat-sidebar')).toBeDefined();
36
- });
37
-
38
- it('defaults to collapsed=false on connect', () => {
39
- const sb = mount('<chat-sidebar slot="leading"></chat-sidebar>');
40
- expect(sb.collapsed).toBe(false);
41
- });
42
-
43
- it('reflects [collapsed] via property assignment', async () => {
44
- const sb = mount('<chat-sidebar slot="leading"></chat-sidebar>');
45
- sb.collapsed = true;
46
- await tick();
47
- expect(sb.hasAttribute('collapsed')).toBe(true);
48
- });
49
-
50
- it('reflects [resizing] via property assignment', async () => {
51
- const sb = mount('<chat-sidebar slot="leading"></chat-sidebar>');
52
- sb.resizing = true;
53
- await tick();
54
- expect(sb.hasAttribute('resizing')).toBe(true);
55
- });
56
-
57
- it('exposes .toggle() / .collapse() / .expand() public methods', () => {
58
- const sb = mount('<chat-sidebar slot="leading" collapsible></chat-sidebar>');
59
- expect(typeof sb.toggle).toBe('function');
60
- expect(typeof sb.collapse).toBe('function');
61
- expect(typeof sb.expand).toBe('function');
62
- });
63
-
64
- it('persists width to chat-namespaced localStorage key (not collide with admin)', async () => {
65
- const sb = mount('<chat-sidebar slot="leading" collapsible></chat-sidebar>');
66
- sb.style.width = '240px';
67
- sb.collapse();
68
- expect(sb.collapsed).toBe(true);
69
- // localStorage key should be chat-namespaced
70
- expect(localStorage.getItem('adia-chat-sidebar-leading')).not.toBeNull();
71
- // Should NOT have written to the admin namespace
72
- expect(localStorage.getItem('adia-sidebar-leading')).toBeNull();
73
- });
74
-
75
- it('uses [name] override for the localStorage key', () => {
76
- const sb = mount('<chat-sidebar slot="leading" name="conversations" collapsible></chat-sidebar>');
77
- sb.style.width = '200px';
78
- sb.collapse();
79
- expect(localStorage.getItem('adia-chat-sidebar-conversations')).not.toBeNull();
80
- expect(localStorage.getItem('adia-chat-sidebar-leading')).toBeNull();
81
- });
82
-
83
- it('toggle() returns the new collapsed value', () => {
84
- const sb = mount('<chat-sidebar slot="leading" collapsible></chat-sidebar>');
85
- sb.style.width = '200px';
86
- const result = sb.toggle();
87
- expect(result).toBe(sb.collapsed);
88
- });
89
-
90
- it('dispatches sidebar-toggle event on toggle()', () => {
91
- const sb = mount('<chat-sidebar slot="leading" collapsible></chat-sidebar>');
92
- sb.style.width = '200px';
93
- const onToggle = vi.fn();
94
- sb.addEventListener('sidebar-toggle', onToggle);
95
- sb.toggle();
96
- expect(onToggle).toHaveBeenCalledTimes(1);
97
- expect(onToggle.mock.calls[0][0].detail).toEqual(
98
- expect.objectContaining({ name: expect.any(String), expanded: expect.any(Boolean) })
99
- );
100
- });
101
-
102
- it('cleans up resize handlers on disconnect', () => {
103
- const sb = mount('<chat-sidebar slot="leading" resizable><div data-resize></div></chat-sidebar>');
104
- const handle = sb.querySelector('[data-resize]');
105
- const removeSpy = vi.spyOn(handle, 'removeEventListener');
106
- sb.remove();
107
- const removedTypes = removeSpy.mock.calls.map((args) => args[0]);
108
- expect(removedTypes).toContain('pointerdown');
109
- });
110
- });
@@ -1,82 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import '../../../web-components/core/element.js';
3
- import './chat-thread.js';
4
-
5
- const tick = () => new Promise((r) => queueMicrotask(r));
6
-
7
- function mount(html) {
8
- const wrap = document.createElement('div');
9
- wrap.innerHTML = html;
10
- document.body.appendChild(wrap);
11
- return wrap.firstElementChild;
12
- }
13
-
14
- let originalRect;
15
- beforeEach(() => {
16
- document.body.innerHTML = '';
17
- globalThis.MutationObserver = class {
18
- observe() {} disconnect() {}
19
- };
20
- originalRect = HTMLElement.prototype.getBoundingClientRect;
21
- HTMLElement.prototype.getBoundingClientRect = function () {
22
- return { width: 480, height: 600, top: 0, left: 0, right: 480, bottom: 600, x: 0, y: 0 };
23
- };
24
- });
25
-
26
- afterEach(() => {
27
- if (originalRect) HTMLElement.prototype.getBoundingClientRect = originalRect;
28
- });
29
-
30
- describe('chat-thread', () => {
31
- it('registers chat-thread as a custom element', () => {
32
- expect(customElements.get('chat-thread')).toBeDefined();
33
- });
34
-
35
- it('defaults to streaming=false on connect', () => {
36
- const t = mount('<chat-thread></chat-thread>');
37
- expect(t.streaming).toBe(false);
38
- });
39
-
40
- it('defaults to empty=true when no children', async () => {
41
- const t = mount('<chat-thread></chat-thread>');
42
- await tick();
43
- expect(t.empty).toBe(true);
44
- });
45
-
46
- it('reflects [streaming] via property assignment', async () => {
47
- const t = mount('<chat-thread></chat-thread>');
48
- t.streaming = true;
49
- await tick();
50
- expect(t.hasAttribute('streaming')).toBe(true);
51
- });
52
-
53
- it('reflects [empty] via property assignment', async () => {
54
- const t = mount('<chat-thread></chat-thread>');
55
- t.empty = false;
56
- await tick();
57
- expect(t.hasAttribute('empty')).toBe(false);
58
- t.empty = true;
59
- await tick();
60
- expect(t.hasAttribute('empty')).toBe(true);
61
- });
62
-
63
- it('exposes .scrollToBottom() and .scrollToBottomInstant() methods', () => {
64
- const t = mount('<chat-thread></chat-thread>');
65
- expect(typeof t.scrollToBottom).toBe('function');
66
- expect(typeof t.scrollToBottomInstant).toBe('function');
67
- });
68
-
69
- it('does not count <chat-empty> stub as a message child for [empty] calc', () => {
70
- const t = mount('<chat-thread><chat-empty></chat-empty></chat-thread>');
71
- // chat-empty alone — empty should still be true
72
- expect(t.empty).toBe(true);
73
- });
74
-
75
- it('cleanup on disconnect — removes scroll listener', () => {
76
- const t = mount('<chat-thread></chat-thread>');
77
- const removeSpy = vi.spyOn(t, 'removeEventListener');
78
- t.remove();
79
- const removedTypes = removeSpy.mock.calls.map((args) => args[0]);
80
- expect(removedTypes).toContain('scroll');
81
- });
82
- });
@@ -1,100 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import '../../../web-components/core/element.js';
3
- import './editor-canvas.js';
4
-
5
- const tick = () => new Promise((r) => queueMicrotask(r));
6
-
7
- function mount(html) {
8
- const wrap = document.createElement('div');
9
- wrap.innerHTML = html;
10
- document.body.appendChild(wrap);
11
- return wrap.firstElementChild;
12
- }
13
-
14
- beforeEach(() => {
15
- document.body.innerHTML = '';
16
- globalThis.MutationObserver = class {
17
- observe() {} disconnect() {}
18
- };
19
- });
20
-
21
- describe('editor-canvas', () => {
22
- it('registers editor-canvas as a custom element', () => {
23
- expect(customElements.get('editor-canvas')).toBeDefined();
24
- });
25
-
26
- it('defaults to focused=false', () => {
27
- const c = mount('<editor-canvas></editor-canvas>');
28
- expect(c.focused).toBe(false);
29
- });
30
-
31
- it('defaults to empty=true with no children', async () => {
32
- const c = mount('<editor-canvas></editor-canvas>');
33
- await tick();
34
- expect(c.empty).toBe(true);
35
- });
36
-
37
- it('reflects [empty] via property assignment', async () => {
38
- const c = mount('<editor-canvas></editor-canvas>');
39
- c.empty = false;
40
- await tick();
41
- expect(c.hasAttribute('empty')).toBe(false);
42
- c.empty = true;
43
- await tick();
44
- expect(c.hasAttribute('empty')).toBe(true);
45
- });
46
-
47
- it('reflects [focused] via property assignment', async () => {
48
- const c = mount('<editor-canvas></editor-canvas>');
49
- c.focused = true;
50
- await tick();
51
- expect(c.hasAttribute('focused')).toBe(true);
52
- });
53
-
54
- it('does not count <editor-canvas-empty> stub as a content child', () => {
55
- const c = mount('<editor-canvas><editor-canvas-empty></editor-canvas-empty></editor-canvas>');
56
- expect(c.empty).toBe(true);
57
- });
58
-
59
- it('exposes .zoom getter/setter (default 1.0)', () => {
60
- const c = mount('<editor-canvas></editor-canvas>');
61
- expect(c.zoom).toBe(1.0);
62
- c.zoom = 2.0;
63
- expect(c.zoom).toBe(2.0);
64
- expect(c.style.getPropertyValue('--editor-canvas-zoom')).toBe('2');
65
- });
66
-
67
- it('rejects invalid zoom values', () => {
68
- const c = mount('<editor-canvas></editor-canvas>');
69
- c.zoom = 1.5;
70
- c.zoom = 'invalid'; // should not change
71
- expect(c.zoom).toBe(1.5);
72
- c.zoom = -1; // should not change
73
- expect(c.zoom).toBe(1.5);
74
- c.zoom = 0; // should not change
75
- expect(c.zoom).toBe(1.5);
76
- });
77
-
78
- it('.resetView() restores zoom to 1.0', () => {
79
- const c = mount('<editor-canvas></editor-canvas>');
80
- c.zoom = 2.5;
81
- c.resetView();
82
- expect(c.zoom).toBe(1.0);
83
- });
84
-
85
- it('.focus() sets [focused] reflected', async () => {
86
- const c = mount('<editor-canvas></editor-canvas>');
87
- c.focus();
88
- await tick();
89
- expect(c.focused).toBe(true);
90
- expect(c.hasAttribute('focused')).toBe(true);
91
- });
92
-
93
- it('.blur() clears [focused] reflected', async () => {
94
- const c = mount('<editor-canvas focused></editor-canvas>');
95
- c.blur();
96
- await tick();
97
- expect(c.focused).toBe(false);
98
- expect(c.hasAttribute('focused')).toBe(false);
99
- });
100
- });