@evotecit/canopyx 0.3.20 → 0.3.22

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.
Files changed (36) hide show
  1. package/CanopyX.Html/Assets/canopyx-calendar-screen.css +71 -0
  2. package/CanopyX.Html/Assets/canopyx-calendar-screen.js +38 -0
  3. package/CanopyX.Html/Assets/canopyx-calendar.css +15 -3
  4. package/CanopyX.Html/Assets/canopyx-calendar.js +16 -14
  5. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +5 -6
  6. package/CanopyX.Html/Assets/canopyx-grid.js +4 -5
  7. package/CanopyX.Html/Assets/canopyx-interactive.js +3 -4
  8. package/CanopyX.Html/Assets/canopyx-labels-de.js +7 -0
  9. package/CanopyX.Html/Assets/canopyx-labels-es.js +7 -0
  10. package/CanopyX.Html/Assets/canopyx-labels-fr.js +7 -0
  11. package/CanopyX.Html/Assets/canopyx-labels-it.js +7 -0
  12. package/CanopyX.Html/Assets/canopyx-labels-pl.js +7 -0
  13. package/CanopyX.Html/Assets/canopyx-module.mjs +4 -5
  14. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +5 -6
  15. package/CanopyX.Html/Assets/canopyx-reporting.js +4 -5
  16. package/CanopyX.Html/Assets/canopyx-ui-accordion.css +119 -0
  17. package/CanopyX.Html/Assets/canopyx-ui-accordion.js +33 -0
  18. package/CanopyX.Html/Assets/canopyx-ui-module.mjs +39 -0
  19. package/CanopyX.Html/Assets/canopyx-ui-navigation.css +4 -4
  20. package/CanopyX.Html/Assets/canopyx-ui-navigation.js +5 -5
  21. package/CanopyX.Html/Assets/canopyx-ui-overlays.js +1 -1
  22. package/CanopyX.Html/Assets/canopyx-ui-stepper.js +1 -1
  23. package/CanopyX.Html/Assets/canopyx-ui-tabs.css +1 -0
  24. package/CanopyX.Html/Assets/canopyx-ui-tabs.js +7 -4
  25. package/CanopyX.Html/Assets/canopyx-ui.css +119 -0
  26. package/CanopyX.Html/Assets/canopyx-ui.js +37 -0
  27. package/CanopyX.Html/Assets/canopyx.js +3 -4
  28. package/JavaScript/calendar.d.ts +39 -0
  29. package/JavaScript/locales/de.mjs +7 -0
  30. package/JavaScript/locales/es.mjs +7 -0
  31. package/JavaScript/locales/fr.mjs +7 -0
  32. package/JavaScript/locales/it.mjs +7 -0
  33. package/JavaScript/locales/pl.mjs +7 -0
  34. package/JavaScript/protocol.d.ts +1 -0
  35. package/JavaScript/ui.d.ts +70 -2
  36. package/package.json +18 -1
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"8dc12c5deb018c2c",install(context){if(installed.has(context.UI_IMPL))return;const{UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml}=context;const UI_LABELS={tabsMore:"More",tabsMoreSelected:"More: {label}",tabsScrollPrevious:"Previous tabs",tabsScrollNext:"Next tabs",tabsSection:"Section",tabsPosition:"{current} of {total}",tabsPause:"Pause",tabsPlay:"Play",tabsMotionDisabled:"Automatic tabs are disabled by reduced motion",stepperStepOf:"Step {current} of {total}",stepperBack:"Back",stepperNext:"Next",stepperFinish:"Finish",stepperSkip:"Skip",stepperSaveDraft:"Save draft",stepperAllSteps:"All steps",stepperOptional:"Optional",stepperCompleted:"Completed",stepperSkipped:"Skipped",stepperIssues:"{count} issues to fix",stepperIssue:"1 issue to fix",dialogClose:"Close",drawerClose:"Close",drawerPrevious:"Previous record",drawerNext:"Next record",stateLoading:"Loading…",stateRetry:"Retry",stateDetails:"Details"};const uiFocusSelector='button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';Object.assign(UI_TOOLS,{labels:values=>Object.assign({},UI_LABELS,values),content:(element,value)=>{if(value?.nodeType)element.replaceChildren(value);else hostHtml(element,value,null,"detail")},emit:(root,prefix,name,detail,cancelable=false)=>root.dispatchEvent(new CustomEvent("cx-"+prefix+":"+name,{detail,bubbles:true,cancelable})),focusables:root=>[...root.querySelectorAll(uiFocusSelector)].filter(element=>element.checkVisibility()&&!element.closest("[inert]")),observe(root,changed,signal){let width=-1,frame=0;const read=()=>{const next=root.getBoundingClientRect().width;if(next!==width){width=next;changed(width)}};const observer=new ResizeObserver(()=>{frame||=requestAnimationFrame(()=>{frame=0;read()})});observer.observe(root);read();const dispose=()=>{observer.disconnect();cancelAnimationFrame(frame)};signal?.addEventListener("abort",dispose,{once:true});return dispose},theme(host,element){const previous=new Map([...element.style].map(name=>[name,element.style.getPropertyValue(name)]));overlayTheme(host,element);for(const[name,value]of previous)if(name.startsWith("--hfx-")||name.startsWith("--cx-"))element.style.setProperty(name,value);const written=new Map([...element.style].map(name=>[name,element.style.getPropertyValue(name)]));return()=>{for(const[name,value]of written)if(element.style.getPropertyValue(name)===value){if(previous.has(name))element.style.setProperty(name,previous.get(name));else element.style.removeProperty(name)}}},position(element,anchor,placement="bottom-start",point){const viewport=global.visualViewport,width=viewport?.width||document.documentElement.clientWidth,height=viewport?.height||global.innerHeight;const offsetX=viewport?.offsetLeft||0,offsetY=viewport?.offsetTop||0;const style=getComputedStyle(element),gap=parseFloat(style.marginTop)||0,marginX=parseFloat(style.marginLeft)||0;const edge=Math.max(8,gap);const box=element.getBoundingClientRect(),target=point?{left:point.x,right:point.x,top:point.y,bottom:point.y}:anchor.getBoundingClientRect();const rtl=getComputedStyle(anchor).direction==="rtl",side=placement.split("-")[0],align=placement.split("-")[1]||"center";let x=(target.left+target.right-box.width)/ 2, y = target.bottom + gap, actual = side;
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"24afaa117ebf3fb5",install(context){if(installed.has(context.UI_IMPL))return;const{UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml}=context;const UI_LABELS={tabsMore:"More",tabsMoreSelected:"More: {label}",tabsScrollPrevious:"Previous tabs",tabsScrollNext:"Next tabs",tabsSection:"Section",tabsPosition:"{current} of {total}",tabsPause:"Pause",tabsPlay:"Play",tabsMotionDisabled:"Automatic tabs are disabled by reduced motion",accordionSearch:"Filter sections",accordionNoMatches:"No matching sections",accordionCopyTitle:"Copy title",accordionCopied:"Copied",stepperStepOf:"Step {current} of {total}",stepperBack:"Back",stepperNext:"Next",stepperFinish:"Finish",stepperSkip:"Skip",stepperSaveDraft:"Save draft",stepperAllSteps:"All steps",stepperOptional:"Optional",stepperCompleted:"Completed",stepperSkipped:"Skipped",stepperIssues:"{count} issues to fix",stepperIssue:"1 issue to fix",dialogClose:"Close",drawerClose:"Close",drawerPrevious:"Previous record",drawerNext:"Next record",stateLoading:"Loading…",stateRetry:"Retry",stateDetails:"Details"};const uiFocusSelector='button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';Object.assign(UI_TOOLS,{labels:values=>Object.assign({},UI_LABELS,values),content:(element,value)=>{if(value?.nodeType)element.replaceChildren(value);else hostHtml(element,value,null,"detail")},emit:(root,prefix,name,detail,cancelable=false)=>root.dispatchEvent(new CustomEvent("cx-"+prefix+":"+name,{detail,bubbles:true,cancelable})),focusables:root=>[...root.querySelectorAll(uiFocusSelector)].filter(element=>element.checkVisibility()&&!element.closest("[inert]")),observe(root,changed,signal){let width=-1,frame=0;const read=()=>{const next=root.getBoundingClientRect().width;if(next!==width){width=next;changed(width)}};const observer=new ResizeObserver(()=>{frame||=requestAnimationFrame(()=>{frame=0;read()})});observer.observe(root);read();const dispose=()=>{observer.disconnect();cancelAnimationFrame(frame)};signal?.addEventListener("abort",dispose,{once:true});return dispose},theme(host,element){const previous=new Map([...element.style].map(name=>[name,element.style.getPropertyValue(name)]));overlayTheme(host,element);for(const[name,value]of previous)if(name.startsWith("--hfx-")||name.startsWith("--cx-"))element.style.setProperty(name,value);const written=new Map([...element.style].map(name=>[name,element.style.getPropertyValue(name)]));return()=>{for(const[name,value]of written)if(element.style.getPropertyValue(name)===value){if(previous.has(name))element.style.setProperty(name,previous.get(name));else element.style.removeProperty(name)}}},position(element,anchor,placement="bottom-start",point){const viewport=global.visualViewport,width=viewport?.width||document.documentElement.clientWidth,height=viewport?.height||global.innerHeight;const offsetX=viewport?.offsetLeft||0,offsetY=viewport?.offsetTop||0;const style=getComputedStyle(element),gap=parseFloat(style.marginTop)||0,marginX=parseFloat(style.marginLeft)||0;const edge=Math.max(8,gap);const box=element.getBoundingClientRect(),target=point?{left:point.x,right:point.x,top:point.y,bottom:point.y}:anchor.getBoundingClientRect();const rtl=getComputedStyle(anchor).direction==="rtl",side=placement.split("-")[0],align=placement.split("-")[1]||"center";let x=(target.left+target.right-box.width)/ 2, y = target.bottom + gap, actual = side;
2
2
  if(side==="top")y=target.top-box.height-gap;if(side==="left"||side==="right"){x=side==="left"?target.left-box.width-gap:target.right+gap;y=target.top}
3
3
  else if(align!=="center")x=(align==="start")!==rtl?target.left:target.right-box.width;if(side==="top"&&y<offsetY){y=target.bottom+gap;actual="bottom"}
4
4
  else if(side==="bottom"&&y+box.height>height+offsetY){y=target.top-box.height-gap;actual="top"}
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"a31fd5d0b314cdef",requires:["ui-navigation"],install(context){if(installed.has(context.UI_IMPL))return;const{UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml}=context;UI_IMPL.stepper=(root,options={},signal)=>{const n=UI_TOOLS.navigation,life=n.scope(signal),labels=UI_TOOLS.labels(options.labels);const mode=options.mode||root.dataset.mode||'interactive';const linear=options.linear??root.dataset.linear!=='false';let items=n.records(root,'stepper',options);let current=n.resolve(items,options.selectedIndex??options.selected)||items.find(item=>item.element.hasAttribute('aria-current'))||items.find(item=>!item.disabled);if(current?.disabled)current=items.find(item=>!item.disabled);let destroyed=false,completed=false,view,finishSelection;root.dataset.mode=mode;const states=new Map(items.map(item=>[item.id,item.state==='current'?'upcoming':item.state]));const visited=new Set(items.filter(item=>item.visited||item.index<(current?.index??0)||['done','error','skipped'].includes(item.state)).map(item=>item.id));if(current)visited.add(current.id);function syncRecords(){items.forEach(item=>{item.state=item===current&&!completed&&states.get(item.id)!=='error'?'current':states.get(item.id);item.visited=visited.has(item.id)});return current}
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"5682c49db1b85314",requires:["ui-picker","ui-navigation"],install(context){if(installed.has(context.UI_IMPL))return;const{UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml}=context;UI_IMPL.stepper=(root,options={},signal)=>{const n=UI_TOOLS.navigation,life=n.scope(signal),labels=UI_TOOLS.labels(options.labels);const mode=options.mode||root.dataset.mode||'interactive';const linear=options.linear??root.dataset.linear!=='false';let items=n.records(root,'stepper',options);let current=n.resolve(items,options.selectedIndex??options.selected)||items.find(item=>item.element.hasAttribute('aria-current'))||items.find(item=>!item.disabled);if(current?.disabled)current=items.find(item=>!item.disabled);let destroyed=false,completed=false,view,finishSelection;root.dataset.mode=mode;const states=new Map(items.map(item=>[item.id,item.state==='current'?'upcoming':item.state]));const visited=new Set(items.filter(item=>item.visited||item.index<(current?.index??0)||['done','error','skipped'].includes(item.state)).map(item=>item.id));if(current)visited.add(current.id);function syncRecords(){items.forEach(item=>{item.state=item===current&&!completed&&states.get(item.id)!=='error'?'current':states.get(item.id);item.visited=visited.has(item.id)});return current}
2
2
  function getState(){syncRecords();return{selected:current?.id??null,finished:completed,steps:items.map(item=>({id:item.id,state:item.state,current:item===current,visited:item.visited,optional:item.optional}))}}
3
3
  function allowed(item){return!!item&&!item.disabled&&(!linear||item===current||visited.has(item.id)||['done','error','skipped'].includes(states.get(item.id)))}
4
4
  if(mode!=='interactive')return{select:async()=>false,getSelected:()=>current?.id??null,refresh(){},destroy(){life.abort()},preparePrint:async()=>{},next:async()=>false,back:async()=>false,skip:async()=>false,finish:async()=>false,setStepState(){return false},getState,ready:Promise.resolve()};const errors=UI_TOOLS.stepperErrors(root,labels);const deferred=n.deferred(root,'stepper',options,life,id=>select(id,'retry'));function render(focus=false){syncRecords();root.dataset.finished=String(completed);view?.update(items,current,states,visited,allowed,focus)}
@@ -106,6 +106,7 @@ inset-block:var(--hfx-space-2,0.5rem);
106
106
  inline-size:var(--hfx-indicator-width,2px);
107
107
  background:var(--hfx-color-accent-indicator,light-dark(#11776f,#37c9b8));
108
108
  }
109
+ .cx-tabs[data-justified="true"]:not(.cx-tabs--vertical) > .cx-tablist > .cx-tab{flex:1 1 0;}
109
110
  .cx-tabs[data-overflow="wrap"] > .cx-tablist{flex-wrap:wrap;overflow:visible;}
110
111
  .cx-tabs[data-overflow="menu"] > .cx-tablist{overflow:hidden;}
111
112
  .cx-tabs-tools{display:flex;gap:var(--hfx-space-1,0.25rem);grid-column:2;grid-row:1;}
@@ -1,16 +1,19 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"96b84956100933e7",requires:["ui-navigation"],install(context){if(installed.has(context.UI_IMPL))return;const{UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml}=context;UI_IMPL.tabs=(root,options={},signal)=>{const n=UI_TOOLS.navigation,life=n.scope(signal),labels=UI_TOOLS.labels(options.labels);const list=n.owned(root,'[role="tablist"]')[0];let items=[],current,layout,auto,destroyed=false;const style=options.style||['vertical','segmented','pills'].find(s=>root.classList.contains('cx-tabs--'+s))||'underline';for(const variant of['underline','pills','segmented','vertical'])root.classList.toggle('cx-tabs--'+variant,variant===style);root.classList.add('cx-tabs');const effectiveStyle=style==='segmented'&&n.owned(root,'[role="tab"]').length>5?'pills':style;if(effectiveStyle!==style){root.classList.replace('cx-tabs--segmented','cx-tabs--pills');if(options.debug===true)console.warn('[CanopyX] tabs: segmented supports 2–5 options; rendering as pills')}
2
- root.dataset.overflow=options.overflow||root.dataset.overflow||'scroll';if(root.dataset.overflow==='wrap'&&effectiveStyle!=='pills')root.dataset.overflow='scroll';root.dataset.collapse=options.collapse||root.dataset.collapse||(effectiveStyle==='segmented'?'none':'picker');root.dataset.print=options.print||root.dataset.print||'all';root.dataset.transition=options.transition||'none';list?.setAttribute('aria-orientation',effectiveStyle==='vertical'?'vertical':'horizontal');const deferred=n.deferred(root,'tabs',options,life,id=>select(id));function render(){for(const item of items){const selected=item===current;item.element.setAttribute('aria-selected',String(selected));item.element.tabIndex=selected?0:-1;item.element.dataset.state=item.disabled?'disabled':selected?'selected':'';if(item.panel){item.panel.hidden=!selected;item.panel.dataset.state=selected?'selected':'';n.panelTabStop(item.panel)}}
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"19ece8184f3daf4a",requires:["ui-picker","ui-navigation"],install(context){if(installed.has(context.UI_IMPL))return;const{UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml}=context;UI_IMPL.tabs=(root,options={},signal)=>{const n=UI_TOOLS.navigation,life=n.scope(signal),labels=UI_TOOLS.labels(options.labels);const list=n.owned(root,'[role="tablist"]')[0];let items=[],current,layout,auto,destroyed=false;const style=options.style||['vertical','segmented','pills'].find(s=>root.classList.contains('cx-tabs--'+s))||'underline';for(const variant of['underline','pills','segmented','vertical'])root.classList.toggle('cx-tabs--'+variant,variant===style);root.classList.add('cx-tabs');const effectiveStyle=style==='segmented'&&n.owned(root,'[role="tab"]').length>5?'pills':style;if(effectiveStyle!==style){root.classList.replace('cx-tabs--segmented','cx-tabs--pills');if(options.debug===true)console.warn('[CanopyX] tabs: segmented supports 2–5 options; rendering as pills')}
2
+ root.dataset.overflow=options.overflow||root.dataset.overflow||'scroll';if(root.dataset.overflow==='wrap'&&effectiveStyle!=='pills')root.dataset.overflow='scroll';root.dataset.collapse=options.collapse||root.dataset.collapse||(effectiveStyle==='segmented'?'none':'picker');root.dataset.print=options.print||root.dataset.print||'all';root.dataset.transition=options.transition||'none';root.dataset.justified=String(options.justified??root.dataset.justified==='true');const remember=options.remember??root.dataset.remember;const storageKey=remember?'canopyx:tabs:' +(remember===true?root.id:remember):null;list?.setAttribute('aria-orientation',effectiveStyle==='vertical'?'vertical':'horizontal');const deferred=n.deferred(root,'tabs',options,life,id=>select(id));function render(){for(const item of items){const selected=item===current;item.element.setAttribute('aria-selected',String(selected));item.element.tabIndex=selected?0:-1;item.element.dataset.state=item.disabled?'disabled':selected?'selected':'';if(item.panel){item.panel.hidden=!selected;item.panel.dataset.state=selected?'selected':'';n.panelTabStop(item.panel)}}
3
3
  layout?.update(items,current)}
4
- const selection=n.selection(root,'tabs',options,life,()=>current,async(from,to,loadSignal,live)=>{if(from!==to)deferred.leave(from);current=to;render();if(options.hash&&root.id)writeHash(to.id);if(from!==to)UI_TOOLS.emit(root,'tabs','change',{from,to});const loaded=await deferred.load(to,loadSignal,live);if(live()&&loaded)animate(to,from);if(live())layout?.update(items,current)});function select(value,source='api'){if(destroyed)return Promise.resolve(false);if(source!=='auto'&&source!=='initial')auto?.stop();const target=n.resolve(items,value);if(!target||target.disabled){selection.cancel();return Promise.resolve(false)}
4
+ const selection=n.selection(root,'tabs',options,life,()=>current,async(from,to,loadSignal,live,source)=>{if(from!==to)deferred.leave(from);current=to;render();if(options.hash&&root.id)writeHash(to.id);if(storageKey&&source!=='auto')try{localStorage.setItem(storageKey,to.id)}catch{}
5
+ if(from!==to)UI_TOOLS.emit(root,'tabs','change',{from,to});const loaded=await deferred.load(to,loadSignal,live);if(live()&&loaded)animate(to,from);if(live())layout?.update(items,current)});function select(value,source='api'){if(destroyed)return Promise.resolve(false);if(source!=='auto'&&source!=='initial')auto?.stop();const target=n.resolve(items,value);if(!target||target.disabled){selection.cancel();return Promise.resolve(false)}
5
6
  if(target===current&&!deferred.isDeferred(target)){selection.cancel();return Promise.resolve(true)}
6
7
  return selection.request(target,undefined,source)}
8
+ function step(direction){const enabled=items.filter(item=>!item.disabled);return select(enabled[enabled.indexOf(current)+ direction]?.id)}
9
+ function remembered(){try{return n.resolve(items,localStorage.getItem(storageKey))}catch{return undefined}}
7
10
  function animate(to,from){if(!to.panel||root.dataset.transition==='none'||matchMedia('(prefers-reduced-motion: reduce)').matches)return;to.panel.getAnimations().forEach(animation=>animation.cancel());const css=getComputedStyle(root),slide=root.dataset.transition==='slide';const duration=css.getPropertyValue('--cx-tabs-motion-duration-' +(slide?'base':'fast')).trim();const ms=parseFloat(duration)*(duration.endsWith('ms')?1:1000);const distance=css.getPropertyValue('--cx-tabs-motion-distance').trim();const easing=css.getPropertyValue('--cx-tabs-motion-easing').trim();const sign=(to.index>=(from?.index??0)?1:-1)*(css.direction==='rtl'?-1:1);to.panel.animate([{opacity:0,transform:slide?'translateX(calc('+distance+' * '+sign+'))':'none'},{opacity:1,transform:'none'}],{duration:ms||0,easing})}
8
11
  function hashId(){try{return new URLSearchParams(location.hash.slice(1)).get(root.id)}catch{return null}}
9
12
  function writeHash(id){const params=new URLSearchParams(location.hash.slice(1));params.set(root.id,id);const hash='#'+params.toString();if(hash!==location.hash)history[options.hashHistory==='push'?'pushState':'replaceState'](null,'',hash)}
10
13
  function refresh(){if(destroyed)return;selection.cancel();const id=current?.id;items=n.records(root,'tabs',options);current=items.find(item=>item.id===id&&!item.disabled)||items.find(item=>!item.disabled&&item.element.getAttribute('aria-selected')==='true')||items.find(item=>!item.disabled);render();auto?.reset()}
11
14
  root.addEventListener('click',event=>{const tab=event.target.closest('[role="tab"]');if(tab&&items.some(item=>item.element===tab))select(tab.dataset.tabId,'user')},{signal:life.signal});list?.addEventListener('keydown',event=>{const index=items.findIndex(item=>item.element===event.target);if(index<0)return;const visible=items.filter(item=>!item.element.hidden),position=visible.indexOf(items[index]);const vertical=list.getAttribute('aria-orientation')==='vertical';const rtl=getComputedStyle(root).direction==='rtl';const forward=vertical?'ArrowDown':rtl?'ArrowLeft':'ArrowRight';const back=vertical?'ArrowUp':rtl?'ArrowRight':'ArrowLeft';let target;if(event.key===forward||event.key===back)target=visible[(position +(event.key===forward?1:-1)+ visible.length)%visible.length];if(event.key==='Home')target=visible[0];if(event.key==='End')target=visible[visible.length-1];if(target){event.preventDefault();items.forEach(item=>{item.element.tabIndex=item===target?0:-1});target.element.focus();target.element.scrollIntoView({block:'nearest',inline:'nearest'});const activation=options.activation||root.dataset.activation;const manual=activation==='manual'||activation!=='automatic'&&(options.beforeChange||items.some(deferred.isDeferred));if(!manual&&!target.disabled)select(target.id,'user')}else if(event.key==='Enter'||event.key===' '){event.preventDefault();select(items[index].id,'user')}},{signal:life.signal});list?.addEventListener('focusout',event=>{if(!list.contains(event.relatedTarget))items.forEach(item=>{item.element.tabIndex=item===current?0:-1})},{signal:life.signal});let touch;root.addEventListener('pointerdown',event=>{if(event.pointerType==='touch'&&root.dataset.phone==='true'&&event.target.closest('.cx-tabpanel')&&
12
15
  !event.target.closest('a[href],button,input,select,textarea,[contenteditable="true"]')&&!getSelection()?.toString())touch={x:event.clientX,y:event.clientY,id:event.pointerId}},{signal:life.signal});root.addEventListener('pointerup',event=>{const start=touch;touch=null;if(!start||start.id!==event.pointerId)return;const dx=event.clientX-start.x,dy=event.clientY-start.y;if(Math.abs(dx)<48||Math.abs(dx)<=Math.abs(dy))return;const direction=(dx<0?1:-1)*(getComputedStyle(root).direction==='rtl'?-1:1);const target=items.slice().filter(item=>!item.disabled);const next=target[target.indexOf(current)+ direction];if(next)select(next.id,'user')},{signal:life.signal});root.addEventListener('pointercancel',()=>{touch=null},{signal:life.signal});if(options.hash)window.addEventListener('hashchange',()=>{const target=n.resolve(items,hashId());if(target&&target!==current)select(target.id,'hash')},{signal:life.signal});function destroy(){if(destroyed)return;destroyed=true;life.abort();auto?.destroy();layout?.destroy();deferred.destroy();root.removeAttribute('data-cx-ready');items.forEach(item=>{item.element.hidden=false;item.element.removeAttribute('aria-busy');if(item.panel){item.panel.hidden=false;item.panel.removeAttribute('aria-busy');item.panel.getAnimations().forEach(a=>a.cancel())}})}
13
- refresh();layout=UI_TOOLS.tabsLayout(root,list,options,labels,life,id=>select(id,'user'));root.dataset.cxReady='true';render();const requested=options.hash&&n.resolve(items,hashId())||n.resolve(items,options.selectedIndex??options.selected);const initial=requested&&!requested.disabled?requested:current;if(options.hash&&root.id&&initial===current&&current)writeHash(current.id);const ready=select(initial?.id,'initial');auto=UI_TOOLS.tabsAuto(root,list,options,labels,life,()=>({items,current}),id=>select(id,'auto'),()=>selection.cancel(),ready);signal?.addEventListener('abort',destroy,{once:true});return{select,getSelected:()=>current?.id??null,refresh,preparePrint:()=>deferred.preparePrint(),destroy,ready}};UI_TOOLS.tabsLayout=(root,list,options,labels,life,select)=>{const n=UI_TOOLS.navigation;const phone=UI_TOOLS.picker(root,{lead:labels.tabsSection,items:[],selected:null,onSelect:select});phone.element.classList.add('cx-tabs-phone-picker');const position=h('div','cx-tabs-position');position.setAttribute('aria-live','polite');const tools=h('div','cx-tabs-tools');const previous=n.button(labels.tabsScrollPrevious,'cx-tabs-scroll cx-tabs-scroll--previous');const next=n.button(labels.tabsScrollNext,'cx-tabs-scroll cx-tabs-scroll--next');for(const el of[previous,next]){el.setAttribute('aria-label',el.textContent);el.setAttribute('aria-hidden','true');el.tabIndex=-1}
16
+ refresh();layout=UI_TOOLS.tabsLayout(root,list,options,labels,life,id=>select(id,'user'));root.dataset.cxReady='true';render();const requested=options.hash&&n.resolve(items,hashId())||storageKey&&remembered()||n.resolve(items,options.selectedIndex??options.selected);const initial=requested&&!requested.disabled?requested:current;if(options.hash&&root.id&&initial===current&&current)writeHash(current.id);const ready=select(initial?.id,'initial');auto=UI_TOOLS.tabsAuto(root,list,options,labels,life,()=>({items,current}),id=>select(id,'auto'),()=>selection.cancel(),ready);signal?.addEventListener('abort',destroy,{once:true});return{select,next:()=>step(1),back:()=>step(-1),getSelected:()=>current?.id??null,refresh,preparePrint:()=>deferred.preparePrint(),destroy,ready}};UI_TOOLS.tabsLayout=(root,list,options,labels,life,select)=>{const n=UI_TOOLS.navigation;const phone=UI_TOOLS.picker(root,{lead:labels.tabsSection,items:[],selected:null,onSelect:select});phone.element.classList.add('cx-tabs-phone-picker');const position=h('div','cx-tabs-position');position.setAttribute('aria-live','polite');const tools=h('div','cx-tabs-tools');const previous=n.button(labels.tabsScrollPrevious,'cx-tabs-scroll cx-tabs-scroll--previous');const next=n.button(labels.tabsScrollNext,'cx-tabs-scroll cx-tabs-scroll--next');for(const el of[previous,next]){el.setAttribute('aria-label',el.textContent);el.setAttribute('aria-hidden','true');el.tabIndex=-1}
14
17
  setText(previous,'‹');setText(next,'›');const more=UI_TOOLS.picker(root,{lead:'',items:[],selected:null,onSelect:select});more.element.classList.add('cx-tabs-more');tools.append(previous,next,more.element);list?.before(phone.element,position);list?.after(tools);const indicator=h('span','cx-tabs-indicator');indicator.setAttribute('aria-hidden','true');list?.append(indicator);let items=[],current,narrow=false,updating=false,frame;function scroll(direction){const rtl=getComputedStyle(root).direction==='rtl'?-1:1;list?.scrollBy({left:direction*list.clientWidth*rtl,behavior:matchMedia('(prefers-reduced-motion: reduce)').matches?'instant':'smooth'})}
15
18
  previous.addEventListener('click',()=>scroll(-1),{signal:life.signal});next.addEventListener('click',()=>scroll(1),{signal:life.signal});function edges(){if(!list)return;const scrollable=root.dataset.overflow==='scroll'&&!narrow;const tabs=items.filter(item=>!item.element.hidden);const bounds=list.getBoundingClientRect(),rtl=getComputedStyle(root).direction==='rtl';const first=tabs[0]?.element.getBoundingClientRect(),last=tabs.at(-1)?.element.getBoundingClientRect();const before=!!first&&(rtl?first.right>bounds.right+1:first.left<bounds.left-1);const after=!!last&&(rtl?last.left<bounds.left-1:last.right>bounds.right+1);previous.hidden=!scrollable||!before;next.hidden=!scrollable||!after;root.dataset.scrollStart=String(scrollable&&before);root.dataset.scrollEnd=String(scrollable&&after)}
16
19
  function update(nextItems=items,selected=current,reveal=false){if(updating||life.signal.aborted||!list)return;updating=true;items=nextItems;current=selected;const focus=document.activeElement,fromMore=UI_TOOLS.owns(more.element,focus);const fromList=list.contains(focus)||fromMore,fromPicker=UI_TOOLS.owns(phone.element,focus);const choiceId=fromMore||fromPicker?focus.closest('[data-item-id]')?.dataset.itemId:null;const focusedItem=items.find(item=>item.element.contains(focus)||item.id===choiceId);const model=n.pickerItems(items,current?.id);const measure=list.cloneNode(true);measure.hidden=false;measure.inert=true;measure.removeAttribute('id');measure.setAttribute('aria-hidden','true');measure.style.cssText='position:absolute;visibility:hidden;display:flex;flex-flow:row nowrap;inline-size:max-content;max-inline-size:none;';const measuredTabs=[...measure.querySelectorAll('[role="tab"]')];measuredTabs.forEach(tab=>{tab.hidden=false;tab.removeAttribute('id')});root.append(measure);const gap=parseFloat(getComputedStyle(list).gap)||0;const widths=measuredTabs.map(tab=>tab.getBoundingClientRect().width+gap);measure.remove();const total=Math.max(0,widths.reduce((sum,value)=>sum+value,0)- gap);const play=tools.querySelector('.cx-tabs-play');const available=Math.max(0,root.clientWidth -(play?play.getBoundingClientRect().width+gap:0));function measureMore(selected){more.update({lead:selected?fill(labels.tabsMoreSelected,{label:''}).trim():labels.tabsMore,items:model,selected:selected?.id??null});const clone=more.element.cloneNode(true);clone.hidden=false;clone.inert=true;clone.style.cssText='position:absolute;visibility:hidden;inline-size:max-content;';root.append(clone);const width=clone.getBoundingClientRect().width;clone.remove();return width}
@@ -0,0 +1,119 @@
1
+ /* Shared semantic tokens are bundled by Sync-Assets.ps1. Only component geometry lives here. */
2
+ .cx-host,.cx-static{
3
+ --cx-compact:0;
4
+ --cx-row-h:var(--hfx-row-height,calc(40px - var(--cx-compact,0) * 8px));
5
+ --cx-size-d04em:.04em;
6
+ --cx-size-46ch:46ch;
7
+ --cx-size-440px:440px;
8
+ --cx-size-140px:140px;
9
+ --cx-size-d06em:.06em;
10
+ --cx-size-210px:210px;
11
+ --cx-size-neg-4px:-4px;
12
+ --cx-size-56px:56px;
13
+ --cx-size-64px:64px;
14
+ --cx-size-160px:160px;
15
+ --cx-size-12d5px:12.5px;
16
+ --cx-size-640px:640px;
17
+ --cx-size-17px:17px;
18
+ --cx-size-60vh:60vh;
19
+ --cx-size-11d5px:11.5px;
20
+ --cx-size-13d5px:13.5px;
21
+ --cx-size-38px:38px;
22
+ --cx-size-26px:26px;
23
+ --cx-size-52px:52px;
24
+ --cx-size-30px:30px;
25
+ --cx-size-72px:72px;
26
+ --cx-size-244px:244px;
27
+ --cx-size-44px:44px;
28
+ --cx-size-85vh:85vh;
29
+ --cx-size-480px:480px;
30
+ --cx-size-14px:14px;
31
+ --cx-size-1px:1px;
32
+ --cx-size-neg-1px:-1px;
33
+ --cx-size-8px:8px;
34
+ --cx-size-12px:12px;
35
+ --cx-size-4px:4px;
36
+ --cx-size-10px:10px;
37
+ --cx-size-11px:11px;
38
+ --cx-size-1d5px:1.5px;
39
+ --cx-size-5px:5px;
40
+ --cx-size-280px:280px;
41
+ --cx-size-34px:34px;
42
+ --cx-size-6px:6px;
43
+ --cx-size-32px:32px;
44
+ --cx-size-7px:7px;
45
+ --cx-size-420px:420px;
46
+ --cx-size-100vw:100vw;
47
+ --cx-size-16px:16px;
48
+ --cx-size-320px:320px;
49
+ --cx-size-2px:2px;
50
+ --cx-size-neg-2px:-2px;
51
+ --cx-size-180px:180px;
52
+ --cx-size-9px:9px;
53
+ --cx-size-neg-3px:-3px;
54
+ --cx-size-18px:18px;
55
+ --cx-size-1d6px:1.6px;
56
+ --cx-size-999px:999px;
57
+ --cx-size-100vh:100vh;
58
+ --cx-size-340px:340px;
59
+ --cx-size-20px:20px;
60
+ --cx-size-36px:36px;
61
+ --cx-size-3px:3px;
62
+ --cx-size-13px:13px;
63
+ --cx-size-360px:360px;
64
+ --cx-size-22px:22px;
65
+ --cx-size-24px:24px;
66
+ --cx-size-80vh:80vh;
67
+ --cx-size-240px:240px;
68
+ --cx-size-d875em:.875em;
69
+ --cx-size-92px:92px;
70
+ --cx-size-28px:28px;
71
+ --cx-scrollbar-thumb:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 28%,transparent);
72
+ --cx-scrollbar-thumb-hover:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 46%,transparent);
73
+ --cx-scrollbar-track:transparent;
74
+ --cx-scrollbar-size:10px;
75
+ }
76
+ .cx-host{
77
+ box-sizing:border-box;
78
+ display:flex;
79
+ flex-direction:column;
80
+ min-height:0;
81
+ color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));
82
+ background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));
83
+ font-family:var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);
84
+ font-size:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem));
85
+ line-height:var(--hfx-type-small-line,1.4);
86
+ }
87
+ .cx-host:where(:not(.cx-drawer,.cx-dialog,.cx-popover,.cx-menu,.cx-tooltip)){
88
+ height:480px;
89
+ }
90
+ .cx-host[data-cx-chrome="embedded"]{background:transparent;border:0;border-radius:0;}
91
+ .cx-host[data-cx-chrome="embedded"] > .cx-grid{border-inline:0;border-bottom:0;border-radius:0;background:transparent;}
92
+ .cx-host[data-cx-chrome="embedded"] > :is(.cx-grid-notice,.cx-grid-status,.cx-grid-pager){background:transparent;}
93
+ .cx-host[data-cx-chrome="embedded"] :is(.cx-toolbar,.cx-grid-query-summary,.cx-grid-status,.cx-grid-pager){padding-inline:var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));}
94
+ .cx-host[data-cx-chrome="embedded"] :is(.cx-hrow,.cx-row) > :first-child{padding-inline-start:var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));}
95
+ .cx-host[data-cx-chrome="embedded"] :is(.cx-hrow,.cx-row) > :last-child{padding-inline-end:var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));}
96
+ .cx-host *,.cx-host *::before,.cx-host *::after{box-sizing:border-box;}
97
+ .cx-host .cx-button.cx-filter-chip{display:inline-flex;align-items:center;justify-content:flex-start;gap:var(--hfx-space-1-5,6px);min-width:0;}
98
+ .cx-filter-chip > .cx-chip-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:var(--hfx-type-small-line,1.4);}
99
+ .cx-filter-chip > .cx-chip-remove{flex:none;}
100
+ @media print{.cx-filter-chip > .cx-chip-label{white-space:normal;overflow:visible;text-overflow:clip;}}
101
+ @media not (forced-colors:active){
102
+ :where(.cx-host,.cx-host *){scrollbar-color:var(--cx-scrollbar-thumb) var(--cx-scrollbar-track);scrollbar-width:thin;}
103
+ .cx-host::-webkit-scrollbar,.cx-host ::-webkit-scrollbar{width:var(--cx-scrollbar-size);height:var(--cx-scrollbar-size);}
104
+ .cx-host::-webkit-scrollbar-track,.cx-host ::-webkit-scrollbar-track,.cx-host ::-webkit-scrollbar-corner{background:var(--cx-scrollbar-track);}
105
+ .cx-host::-webkit-scrollbar-thumb,.cx-host ::-webkit-scrollbar-thumb{background:var(--cx-scrollbar-thumb) padding-box;border:calc(var(--hfx-border-width,1px)*2) solid transparent;border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));}
106
+ .cx-host ::-webkit-scrollbar-thumb:hover{background-color:var(--cx-scrollbar-thumb-hover);}
107
+ }
108
+ .cx-sr-only{
109
+ position:absolute !important;
110
+ width:1px;height:1px;padding:0;
111
+ margin:calc(var(--hfx-border-width,1px)*-1);
112
+ overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
113
+ }
114
+ .cx-host[data-cx-density="compact"]{--cx-compact:1;}
115
+ @layer hfx.fallbacks{
116
+ :where([data-cx-fallback-mode="auto"],.cx-static[data-theme="auto"],.cx-static[data-cx-theme="auto"]){color-scheme:light dark;}
117
+ :where([data-cx-fallback-mode="light"],.cx-static[data-theme="light"],.cx-static[data-cx-theme="light"]){color-scheme:light;}
118
+ :where([data-cx-fallback-mode="dark"],.cx-static[data-theme="dark"],.cx-static[data-cx-theme="dark"]){color-scheme:dark;}
119
+ }
@@ -0,0 +1,37 @@
1
+ /* CanopyX UI entry: standalone UI primitives. */
2
+ (function(global){"use strict";if(global.CanopyX){return}
3
+ function h(tag,className){const element=document.createElement(tag);if(className)element.className=className;return element}
4
+ function setText(element,value){element.textContent=value==null?"":String(value)}
5
+ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, name) => (values && Object.hasOwn(values, name) ? String(values[name]) : match));
6
+ }
7
+ const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
8
+ let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
9
+ return forms[rules.select(Number(count))]??forms.other??template}
10
+ let pageNonce=typeof document!=="undefined"&&document.currentScript?.nonce||"",trustPolicy;function setNonce(nonce){if(typeof nonce!=="string"||!nonce)throw new Error("CanopyX: invalid nonce.");pageNonce=nonce}
11
+ function withNonce(element){const nonce=pageNonce||document.querySelector("script[nonce]")?.nonce;if(nonce)element.nonce=nonce;return element}
12
+ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.trustedTypes?.createPolicy("canopyx",{createHTML:text=>text,createScript:text=>text,createScriptURL:text=>text})||null}
13
+ catch(_){trustPolicy=null}}
14
+ return trustPolicy?trustPolicy["create"+kind](value):value}
15
+ function hostHtml(element,html,sanitize,kind){const text=String(html??""),value=sanitize?sanitize(text,{kind}):text;if(value?.nodeType)element.replaceChildren(value);else if(typeof value==="string")element.innerHTML=trusted("HTML",value);else if(global.trustedTypes?.isHTML?.(value))element.innerHTML=value;else throw new Error("CanopyX: invalid sanitizeHtml result.")}
16
+ const STATUS_FALLBACKS={"--hfx-color-status-bad-bg":"light-dark(#f9e4e4,#3c272a)","--hfx-color-status-bad-fg":"light-dark(#b8292a,#f47171)","--hfx-color-status-good-bg":"light-dark(#e2f0e9,#1f362f)","--hfx-color-status-good-fg":"light-dark(#177345,#4cc78a)","--hfx-color-status-info-bg":"light-dark(#e4ecfa,#262f41)","--hfx-color-status-info-fg":"light-dark(#2b5fc0,#74a2f7)","--hfx-color-status-neutral-bg":"light-dark(#eeeff0,#2a2c31)","--hfx-color-status-neutral-fg":"light-dark(#5b6069,#a0a5ae)","--hfx-color-status-warn-bg":"light-dark(#f8efde,#3b3322)","--hfx-color-status-warn-fg":"light-dark(#8c5c05,#eeb640)"};const MODE_ATTRIBUTES=["data-theme","data-cx-theme","data-hfx-mode","data-bs-theme","data-hfx-theme","data-hfx-tokens"];const THEME_ATTRIBUTES=[...MODE_ATTRIBUTES,"data-hfx-style","data-hfx-density","data-cx-fallback-mode","style","class"];function watchTheme(host,signal){const attributes=THEME_ATTRIBUTES;const previous=host.getAttribute("data-cx-fallback-mode");const refresh=()=>{const parent=host.parentElement&&getComputedStyle(host.parentElement);const inherited=parent?.colorScheme;const surface=parent&&["--hfx-color-surface-card","--hfx-color-surface"].some(name=>parent.getPropertyValue(name).trim());let mode=null;if(!surface){outer:for(let owner=host;owner;owner=owner.parentElement)for(const attribute of MODE_ATTRIBUTES){const value=owner.getAttribute(attribute);if(value==="light"||value==="dark"){mode=value;break outer}}}
17
+ if(surface||!mode&&inherited&&inherited!=="normal"){if(host.hasAttribute("data-cx-fallback-mode"))host.removeAttribute("data-cx-fallback-mode")}else if(host.getAttribute("data-cx-fallback-mode")!==(mode||"auto"))host.setAttribute("data-cx-fallback-mode",mode||"auto")};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:attributes});refresh();const dispose=()=>{observer.disconnect();if(previous===null)host.removeAttribute("data-cx-fallback-mode");else host.setAttribute("data-cx-fallback-mode",previous)};signal?.addEventListener("abort",dispose,{once:true});return dispose}
18
+ function overlayTheme(host,element,inherit=false){for(const name of["data-hfx-style","data-hfx-mode","data-hfx-density"]){const owner=host.closest("["+name+"]");if(owner&&!inherit)element.setAttribute(name,owner.getAttribute(name));else element.removeAttribute(name)}
19
+ const theme=getComputedStyle(host),parent=inherit&&host.parentElement&&getComputedStyle(host.parentElement);element.style.colorScheme=theme.colorScheme;const copied=[];for(const name of theme)if((name.startsWith("--cx-")||name.startsWith("--hfx-"))&&(!parent||theme.getPropertyValue(name)!==parent.getPropertyValue(name))){element.style.setProperty(name,theme.getPropertyValue(name));copied.push(name)}
20
+ return copied}
21
+ function watchOverlayTheme(host,element,signal){if(signal?.aborted)return()=>{};let copied=[];const refresh=()=>{for(const name of copied)element.style.removeProperty(name);copied=overlayTheme(host,element,element.parentElement===host.parentElement)};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:THEME_ATTRIBUTES});const media=["(prefers-color-scheme:dark)","(prefers-contrast:more)","(forced-colors:active)"].map(query=>matchMedia(query));for(const query of media)query.addEventListener("change",refresh);const dispose=()=>{observer.disconnect();for(const query of media)query.removeEventListener("change",refresh);signal?.removeEventListener("abort",dispose)};signal?.addEventListener("abort",dispose,{once:true});dispose.refresh=refresh;refresh();return dispose}
22
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"ui-overlays":["24afaa117ebf3fb5","canopyx-ui-overlays.dedc42d3a501a387.js","canopyx-ui-overlays.3668a9a74004ea8e.css"],"ui-menu":["352b1ee391133ff0","canopyx-ui-menu.f9abee36db8f6ad2.js","canopyx-ui-menu.2f3478cc5f5c272f.css"],"ui-picker":["d415103478faf52a","canopyx-ui-picker.13e544bd68aca998.js","canopyx-ui-picker.59c85a1988a287a9.css"],"ui-navigation":["2553d01c5276d56a","canopyx-ui-navigation.c4ebc214197f140d.js","canopyx-ui-navigation.0afd07bbdc5aecb5.css"],"ui-tabs":["19ece8184f3daf4a","canopyx-ui-tabs.6cd35b2afd89f530.js","canopyx-ui-tabs.7bb6c6f1341e87e9.css"],"ui-stepper":["5682c49db1b85314","canopyx-ui-stepper.96973189b0f6e0c4.js","canopyx-ui-stepper.1d4a9db373b8d2f2.css"],"ui-accordion":["1424f075b78d0ccd","canopyx-ui-accordion.d0d5daa7f73d0859.js","canopyx-ui-accordion.a3ef9c27cea5b7a4.css"]},PART_CODE=new Map(),SHARED_PARTS={},partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
23
+ function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
24
+ part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
25
+ function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
26
+ function loadPart(part){return part.ready||=Promise.resolve().then(async()=>{const[version,scriptFile,styleFile]=Object.hasOwn(PARTS,part.name)?PARTS[part.name]:[];part.version=version;if(!version)throw new Error("CanopyX: no "+part.label+".");if(PART_CODE.get(part.name)?.version!==part.version||part.styleReady===null){const find=type=>[...document.querySelectorAll('script[type="application/x-canopyx-'+type+'"][data-cx-version="'+part.version+'"]')].find(item=>!pageNonce||item.nonce===pageNonce);const payload=find(part.name),script=h("script"),embeddedStyle=styleFile&&find(part.name+"-style");if(payload){if(embeddedStyle){const style=h("style");style.nonce=payload.nonce;setText(style,embeddedStyle.textContent);document.head.appendChild(style)}
27
+ script.textContent=trusted("Script",payload.textContent);script.nonce=payload.nonce;document.head.appendChild(script);script.remove()}else{const base=global.CanopyXFilterEditorBase,runtime=PART_URL||typeof base==="string"&&base||document.baseURI,hashed=PART_URL&&/\.[a-f\d]{16}\.js(?:[?#]|$)/.test(PART_URL);
28
+ const load=(element,attribute,file,kind)=>new Promise((resolve,reject)=>{const url=new URL(file,runtime).href;element[attribute]=attribute==="src"?trusted("ScriptURL",url):url;element.onload=resolve;element.onerror=()=>{element.remove();reject(new Error("CanopyX: "+part.label+" "+kind+" unavailable."))};document.head.appendChild(withNonce(element))});const link=h("link");link.rel="stylesheet";const style=styleFile&&(part.styleReady||=load(link,"href",hashed?styleFile:"canopyx-"+part.name+".css","stylesheet")
29
+ .catch(error=>{part.styleReady=null;throw error}));const code=PART_CODE.get(part.name)?.version===part.version||(part.scriptReady||=load(script,"src",hashed?scriptFile:"canopyx-"+part.name+".js","script")
30
+ .finally(()=>script.remove()).catch(error=>{part.scriptReady=null;throw error}));await Promise.all([style,code])}}
31
+ const code=PART_CODE.get(part.name);if(code?.version!==part.version)throw new Error("CanopyX: "+part.label+" and runtime must come from the same build.");for(const name of code.requires||[])await loadPart(part.parts[name]||SHARED_PARTS[name]);code.install(part.context())}).catch(error=>{part.ready=null;throw error})}
32
+ const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};function UiHost(){}
33
+ const UI_IMPL={},UI_TOOLS={},uiInstances=new WeakMap();const UI_KINDS={tabs:"ui-tabs",stepper:"ui-stepper",accordion:"ui-accordion",menu:"ui-menu",dialog:"ui-overlays",drawer:"ui-overlays",popover:"ui-overlays",tooltip:"ui-overlays"};const uiContext=()=>({UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml});for(const name of Object.keys(PARTS).filter(part=>part.startsWith("ui-")))SHARED_PARTS[name]=definePart(UiHost,name,name.replace("ui-","UI "),uiContext);function createUi(kind,target,options={}){const root=typeof target==="string"?document.querySelector(target):target;if(root?.nodeType!==1)throw new Error("CanopyX: "+kind+" needs an element.");let registrations=uiInstances.get(root);if(!registrations)uiInstances.set(root,registrations=new Map());if(registrations.has(kind))return registrations.get(kind);const lifetime=new AbortController();watchTheme(root,lifetime.signal);let instance=null;const ready=loadPart(SHARED_PARTS[UI_KINDS[kind]]).then(()=>{if(lifetime.signal.aborted)throw new DOMException("UI component destroyed.","AbortError");instance=UI_IMPL[kind](root,options,lifetime.signal);return instance.ready||instance});const api={element:root,ready:ready.then(()=>api),destroy(){if(lifetime.signal.aborted)return;lifetime.abort();instance?.destroy?.();registrations.delete(kind)}};for(const name of["select","getSelected","refresh","preparePrint","open","close","next","back","skip","finish","setStepState","getState","toggle","getOpen","filter"])api[name]=(...args)=>{if(lifetime.signal.aborted)throw new Error("CanopyX: UI component destroyed.");return instance?instance[name]?.(...args):ready.then(()=>instance[name]?.(...args))};api.ready.catch(error=>{if(error.name!=="AbortError")root.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});registrations.set(kind,Object.freeze(api));return api}
34
+ function bindContextMenu(target,items,options={}){if(typeof target!=="string"&&target?.nodeType!==1)throw new Error("CanopyX: contextMenu needs an element or selector.");if(typeof target==="string")document.documentElement.matches(target);let disposed=false,cleanup=null;const dispose=()=>{disposed=true;cleanup?.()};dispose.ready=loadPart(SHARED_PARTS["ui-menu"]).then(()=>{if(!disposed)cleanup=UI_IMPL.contextMenu(target,items,options)});dispose.open=(...args)=>disposed?false:cleanup?cleanup.open(...args):dispose.ready.then(()=>!disposed&&cleanup.open(...args));dispose.close=(...args)=>cleanup?.close(...args);return dispose}
35
+ function mountUi(root=document){const mounted=[];for(const kind of Object.keys(UI_KINDS)){const selector="[data-cx-"+kind+"]",nodes=[...root.querySelectorAll(selector)];if(root.matches?.(selector))nodes.unshift(root);for(const element of nodes){if(kind==="menu"&&element.parentElement?.closest(selector))continue;if(kind==="stepper"&&["report","static"].includes(element.dataset.mode))continue;mounted.push(createUi(kind,element))}}
36
+ return mounted}
37
+ const UI_API={mountUi,contextMenu:bindContextMenu};for(const kind of Object.keys(UI_KINDS))UI_API[kind]=(target,options)=>createUi(kind,target,options);global.CanopyX=Object.freeze(Object.assign({registerPart,setNonce},UI_API));const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mountUi(document))}else{mountUi(document)}})(typeof window!=="undefined"?window:this);
@@ -75,8 +75,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
75
75
  const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
76
76
  let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
77
77
  return forms[rules.select(Number(count))]??forms.other??template}
78
- let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{const uiLabel=/^(?:tabs(?:More(?:Selected)?|ScrollPrevious|ScrollNext|Section|Position|Pause|Play|MotionDisabled)|stepper(?:StepOf|Back|Next|Finish|Skip|SaveDraft|AllSteps|Optional|Completed|Skipped|Issues?)|dialogClose|drawer(?:Close|Previous|Next)|state(?:Loading|Retry|Details))$/.test(name);
79
- if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change|board|plan|path|stack|time|compare|viewIntent)[A-Z]\w{0,63}$/.test(name) && !uiLabel) throw new Error("CanopyX: there is no label '" + name + "'.");
78
+ let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change|board|plan|path|stack|time|compare|viewIntent|tabs|stepper|accordion|dialog|drawer|state)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
80
79
  if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
81
80
  if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
82
81
  return Object.freeze(labels)}
@@ -531,7 +530,7 @@ close()}else{return}
531
530
  e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const lifetime=new AbortController();let flyout=null,pending=null;const ready=()=>flyout?Promise.resolve(flyout):pending||=loadPart(SHARED_PARTS["ui-overlays"]).then(()=>{if(!lifetime.signal.aborted)flyout=UI_TOOLS.toolbarFlyout(anchorElement,panel,isOpen,lifetime.signal);return flyout}).catch(error=>{pending=null;throw error});const invoke=method=>{if(lifetime.signal.aborted||!isOpen())return;if(flyout){flyout[method]();return}
532
531
  ready().then(value=>{if(!lifetime.signal.aborted&&isOpen())value?.[method]()}).catch(error=>{if(!lifetime.signal.aborted)(anchorElement.closest(".cx-host")||anchorElement)
533
532
  .dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))})};return{position:()=>invoke("position"),open:()=>invoke("open"),close:()=>flyout?.close(),dispose:()=>lifetime.abort()}}
534
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"ui-overlays":["8dc12c5deb018c2c","canopyx-ui-overlays.1e39ccf6db0a3df6.js","canopyx-ui-overlays.3668a9a74004ea8e.css"],"ui-menu":["352b1ee391133ff0","canopyx-ui-menu.f9abee36db8f6ad2.js","canopyx-ui-menu.2f3478cc5f5c272f.css"],"ui-picker":["d415103478faf52a","canopyx-ui-picker.13e544bd68aca998.js","canopyx-ui-picker.59c85a1988a287a9.css"],"ui-navigation":["d14b60f4d16a1cf3","canopyx-ui-navigation.02e11de5f457cc64.js","canopyx-ui-navigation.fb8bdcd8dba604c8.css"],"ui-tabs":["96b84956100933e7","canopyx-ui-tabs.f83f7ebb96c86512.js","canopyx-ui-tabs.bb8c7c70a8b5be2c.css"],"ui-stepper":["a31fd5d0b314cdef","canopyx-ui-stepper.dfddf053fc163c73.js","canopyx-ui-stepper.1d4a9db373b8d2f2.css"],"tree-tools":["ef0d06c82135ae2e","canopyx-tree-tools.1c4b9e286dde6065.js","canopyx-tree-tools.350dd0ee46757029.css"],"export":["15abf3205094bda6","canopyx-export.68b90138463329fe.js"],"office-export":["4fb7a4d570390ee9","canopyx-office-export.7e62c385b884e75b.js"],"links":["c6579c9401f0971d","canopyx-links.b25760079f57e6e1.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["7485f5c9875e9f9b","canopyx-link.9066770aa822fe0f.js","canopyx-link.997fefec6b85f0c5.css"],"highlight":["5ebf0042011ba4fd","canopyx-highlight.ff11a0ca8e30102b.js","canopyx-highlight.9c26291cbcd0962b.css"],"layouts":["90267e35e7edf3a4","canopyx-layouts.058b8a396f909a79.js","canopyx-layouts.ca17f42babc4192a.css"],"record-panel":["cb6bcd1baf644a51","canopyx-record-panel.557c676822e8624f.js","canopyx-record-panel.174846a640de979f.css"]},PART_CODE=new Map(),SHARED_PARTS={},partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
533
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"ui-overlays":["24afaa117ebf3fb5","canopyx-ui-overlays.dedc42d3a501a387.js","canopyx-ui-overlays.3668a9a74004ea8e.css"],"ui-menu":["352b1ee391133ff0","canopyx-ui-menu.f9abee36db8f6ad2.js","canopyx-ui-menu.2f3478cc5f5c272f.css"],"ui-picker":["d415103478faf52a","canopyx-ui-picker.13e544bd68aca998.js","canopyx-ui-picker.59c85a1988a287a9.css"],"ui-navigation":["2553d01c5276d56a","canopyx-ui-navigation.c4ebc214197f140d.js","canopyx-ui-navigation.0afd07bbdc5aecb5.css"],"ui-tabs":["19ece8184f3daf4a","canopyx-ui-tabs.6cd35b2afd89f530.js","canopyx-ui-tabs.7bb6c6f1341e87e9.css"],"ui-stepper":["5682c49db1b85314","canopyx-ui-stepper.96973189b0f6e0c4.js","canopyx-ui-stepper.1d4a9db373b8d2f2.css"],"ui-accordion":["1424f075b78d0ccd","canopyx-ui-accordion.d0d5daa7f73d0859.js","canopyx-ui-accordion.a3ef9c27cea5b7a4.css"],"tree-tools":["ef0d06c82135ae2e","canopyx-tree-tools.1c4b9e286dde6065.js","canopyx-tree-tools.350dd0ee46757029.css"],"export":["15abf3205094bda6","canopyx-export.68b90138463329fe.js"],"office-export":["4fb7a4d570390ee9","canopyx-office-export.7e62c385b884e75b.js"],"links":["c6579c9401f0971d","canopyx-links.b25760079f57e6e1.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["7485f5c9875e9f9b","canopyx-link.9066770aa822fe0f.js","canopyx-link.997fefec6b85f0c5.css"],"highlight":["5ebf0042011ba4fd","canopyx-highlight.ff11a0ca8e30102b.js","canopyx-highlight.9c26291cbcd0962b.css"],"layouts":["90267e35e7edf3a4","canopyx-layouts.058b8a396f909a79.js","canopyx-layouts.ca17f42babc4192a.css"],"record-panel":["cb6bcd1baf644a51","canopyx-record-panel.557c676822e8624f.js","canopyx-record-panel.174846a640de979f.css"]},PART_CODE=new Map(),SHARED_PARTS={},partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
535
534
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
536
535
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
537
536
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -593,7 +592,7 @@ const wanted=Array.from(new Set(ids||this.rows.filter((w)=>!w.status).map((w)=>w
593
592
  const navigation=navigationScope(this,this.dataLifetime.signal);let doc;try{doc=await navigation.wait(this.source.counts(wanted,this.sourceRequest(this.dataLifetime.signal)))}
594
593
  finally{navigation.dispose()}
595
594
  if(navigation.cancelled())return null;if(this.queryAware)snapshotRevision(doc,this.datasetRevision);checkDocument(doc,"counts");this.applyCounts(Object.assign({},doc,{items:doc.items.filter(item=>{const captured=mine.get(item.id);return captured&&this.keyMap.get(item.id)===captured.w&&captured.w.countRevision===captured.revision})}),true);return doc}});function UiHost(){}
596
- const UI_IMPL={},UI_TOOLS={},uiInstances=new WeakMap();const UI_KINDS={tabs:"ui-tabs",stepper:"ui-stepper",menu:"ui-menu",dialog:"ui-overlays",drawer:"ui-overlays",popover:"ui-overlays",tooltip:"ui-overlays"};const uiContext=()=>({UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml});for(const name of["ui-overlays","ui-menu","ui-picker","ui-navigation","ui-tabs","ui-stepper"])SHARED_PARTS[name]=definePart(UiHost,name,name.replace("ui-","UI "),uiContext);function createUi(kind,target,options={}){const root=typeof target==="string"?document.querySelector(target):target;if(root?.nodeType!==1)throw new Error("CanopyX: "+kind+" needs an element.");let registrations=uiInstances.get(root);if(!registrations)uiInstances.set(root,registrations=new Map());if(registrations.has(kind))return registrations.get(kind);const lifetime=new AbortController();watchTheme(root,lifetime.signal);let instance=null;const ready=loadPart(SHARED_PARTS[UI_KINDS[kind]]).then(()=>{if(lifetime.signal.aborted)throw new DOMException("UI component destroyed.","AbortError");instance=UI_IMPL[kind](root,options,lifetime.signal);return instance.ready||instance});const api={element:root,ready:ready.then(()=>api),destroy(){if(lifetime.signal.aborted)return;lifetime.abort();instance?.destroy?.();registrations.delete(kind)}};for(const name of["select","getSelected","refresh","preparePrint","open","close","next","back","skip","finish","setStepState","getState"])api[name]=(...args)=>{if(lifetime.signal.aborted)throw new Error("CanopyX: UI component destroyed.");return instance?instance[name]?.(...args):ready.then(()=>instance[name]?.(...args))};api.ready.catch(error=>{if(error.name!=="AbortError")root.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});registrations.set(kind,Object.freeze(api));return api}
595
+ const UI_IMPL={},UI_TOOLS={},uiInstances=new WeakMap();const UI_KINDS={tabs:"ui-tabs",stepper:"ui-stepper",accordion:"ui-accordion",menu:"ui-menu",dialog:"ui-overlays",drawer:"ui-overlays",popover:"ui-overlays",tooltip:"ui-overlays"};const uiContext=()=>({UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml});for(const name of Object.keys(PARTS).filter(part=>part.startsWith("ui-")))SHARED_PARTS[name]=definePart(UiHost,name,name.replace("ui-","UI "),uiContext);function createUi(kind,target,options={}){const root=typeof target==="string"?document.querySelector(target):target;if(root?.nodeType!==1)throw new Error("CanopyX: "+kind+" needs an element.");let registrations=uiInstances.get(root);if(!registrations)uiInstances.set(root,registrations=new Map());if(registrations.has(kind))return registrations.get(kind);const lifetime=new AbortController();watchTheme(root,lifetime.signal);let instance=null;const ready=loadPart(SHARED_PARTS[UI_KINDS[kind]]).then(()=>{if(lifetime.signal.aborted)throw new DOMException("UI component destroyed.","AbortError");instance=UI_IMPL[kind](root,options,lifetime.signal);return instance.ready||instance});const api={element:root,ready:ready.then(()=>api),destroy(){if(lifetime.signal.aborted)return;lifetime.abort();instance?.destroy?.();registrations.delete(kind)}};for(const name of["select","getSelected","refresh","preparePrint","open","close","next","back","skip","finish","setStepState","getState","toggle","getOpen","filter"])api[name]=(...args)=>{if(lifetime.signal.aborted)throw new Error("CanopyX: UI component destroyed.");return instance?instance[name]?.(...args):ready.then(()=>instance[name]?.(...args))};api.ready.catch(error=>{if(error.name!=="AbortError")root.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});registrations.set(kind,Object.freeze(api));return api}
597
596
  function bindContextMenu(target,items,options={}){if(typeof target!=="string"&&target?.nodeType!==1)throw new Error("CanopyX: contextMenu needs an element or selector.");if(typeof target==="string")document.documentElement.matches(target);let disposed=false,cleanup=null;const dispose=()=>{disposed=true;cleanup?.()};dispose.ready=loadPart(SHARED_PARTS["ui-menu"]).then(()=>{if(!disposed)cleanup=UI_IMPL.contextMenu(target,items,options)});dispose.open=(...args)=>disposed?false:cleanup?cleanup.open(...args):dispose.ready.then(()=>!disposed&&cleanup.open(...args));dispose.close=(...args)=>cleanup?.close(...args);return dispose}
598
597
  function mountUi(root=document){const mounted=[];for(const kind of Object.keys(UI_KINDS)){const selector="[data-cx-"+kind+"]",nodes=[...root.querySelectorAll(selector)];if(root.matches?.(selector))nodes.unshift(root);for(const element of nodes){if(kind==="menu"&&element.parentElement?.closest(selector))continue;if(kind==="stepper"&&["report","static"].includes(element.dataset.mode))continue;mounted.push(createUi(kind,element))}}
599
598
  return mounted}
@@ -26,6 +26,19 @@ export interface GridCalendarSource {
26
26
  color?: string;
27
27
  /** Starts switched off. */
28
28
  hidden?: boolean;
29
+ /** A face drawn in front of the source's events and in its legend switch: a same-origin or base64 data:image URL. */
30
+ avatar?: string;
31
+ /** 1..3 characters, also shown when the avatar fails. */
32
+ initials?: string;
33
+ /** 1..4 characters such as an emoji, when there is neither an avatar nor initials. */
34
+ icon?: string;
35
+ }
36
+ /** The face of a resource, drawn in front of its events. */
37
+ export interface GridCalendarFace {
38
+ resource: string;
39
+ avatar?: string;
40
+ initials?: string;
41
+ icon?: string;
29
42
  }
30
43
  /** The resource timeline's zoom levels. */
31
44
  export type GridCalendarZoom = "hour" | "day" | "week" | "month" | "quarter";
@@ -182,6 +195,24 @@ export interface GridCalendarDefinition<Row extends GridRow = GridRow> {
182
195
  months?: number;
183
196
  /** A print button in the calendar bar. */
184
197
  print?: boolean;
198
+ /** A text column with each event's location (details; merged copies match on it). */
199
+ location?: GridColumnId<Row>;
200
+ /** Copies of one event in several sources (same title, start, end, all-day flag and location) draw once; tone colours them. */
201
+ merge?: boolean | { tone?: string };
202
+ /** How strongly finished events fade in week, day, N-day, list and agenda views, 0.1..0.9. */
203
+ fadePast?: number;
204
+ /** Short notes in day headers, at most 1000. */
205
+ dayNotes?: readonly { date: string; text: string; tone?: string }[];
206
+ /** Faces of resources, one per resource. */
207
+ faces?: readonly GridCalendarFace[];
208
+ /** Days the week list shows from its date, 2..14, instead of the calendar week. */
209
+ listDays?: number;
210
+ /** The narrowest day column, 60..400 pixels: narrower calendars show fewer days, keeping today. */
211
+ dayWidth?: number;
212
+ /** The week list stacks its days when fewer than this many columns (2..7) fit. */
213
+ listBelow?: number;
214
+ /** A Reset button that appears once the calendar differs from its defaults. */
215
+ reset?: boolean;
185
216
  }
186
217
 
187
218
  /** An occurrence as the calendar shows it. */
@@ -201,6 +232,8 @@ export interface GridCalendarEvent {
201
232
  readonly source?: string | null;
202
233
  /** An event of an iCalendar source: read-only, and its record id is not a record of the grid. */
203
234
  readonly external?: boolean;
235
+ /** The sources of a merged event, in source order (merge). */
236
+ readonly owners?: readonly string[];
204
237
  }
205
238
 
206
239
  /** The template hook: draws an event's content into a fresh element; return true to own it. Text is the host's to escape. */
@@ -237,6 +270,8 @@ export interface GridCalendarOptions {
237
270
  menu?: (context: GridCalendarMenuContext, defaults: readonly { readonly id: string; readonly label: string }[]) => readonly GridCalendarMenuItem[] | null | false | void;
238
271
  /** Decides how an occurrence change applies before the calendar asks: a mode, false to cancel, or nothing to keep the setting. */
239
272
  occurrence?: (change: GridOccurrenceChange) => "this" | "following" | "all" | false | void | PromiseLike<"this" | "following" | "all" | false | void>;
273
+ /** Content for a day's header: return text, or write into element with DOM methods and return true. Its text joins the day's name. */
274
+ dayHeader?: (context: { readonly day: string; readonly events: number; readonly view: GridCalendarView; readonly element: HTMLElement; readonly labels: Readonly<Record<string, string>> }) => string | boolean | void;
240
275
  }
241
276
 
242
277
  /** canopyx:eventCreate (cancelable; cancel it to open your own form): the proposed new event. */
@@ -268,6 +303,8 @@ export interface CalendarEventInput {
268
303
  recurrence?: string;
269
304
  exceptions?: string;
270
305
  source?: string;
306
+ /** Where it takes place (details); merged copies of one event match on it. */
307
+ location?: string;
271
308
  }
272
309
  /** The options of CanopyX.createCalendar: a preset's defaults, each overridden by its own option. */
273
310
  export interface CalendarOptions {
@@ -374,4 +411,6 @@ export interface GridCalendarApi {
374
411
  clearCalendarSelection(): void | Promise<void>;
375
412
  /** Shows (true) or hides a source's events; omitted switches it. Resolves with whether they show. */
376
413
  setCalendarSource(id: string, visible?: boolean): boolean | Promise<boolean>;
414
+ /** Puts back the configured view, date, zoom and sources (the Reset button of reset: true). */
415
+ resetCalendar(): Promise<GridCalendarState>;
377
416
  }
@@ -524,6 +524,9 @@ const labels = Object.freeze({
524
524
  calendarOutsideRange: "Außerhalb des Zeitraums dieses Kalenders",
525
525
  calendarClose: "Schließen",
526
526
  calendarDetailsOf: "Details zu {title}",
527
+ calendarReset: "Zurücksetzen",
528
+ calendarSharedBy: "Geteilt von {names}",
529
+ calendarSourcesShown: "{shown} von {total}",
527
530
  flowSteps: "Schritte",
528
531
  flowStepOf: "Schritt {current} von {count}",
529
532
  flowStepAnnounce: "Schritt {current} von {count}, {title}",
@@ -914,6 +917,10 @@ const labels = Object.freeze({
914
917
  timePosition: "Momentaufnahme {index} von {count}",
915
918
  timeFrame: "Momentaufnahme um {time}",
916
919
  timeReducedMotion: "Die zeitgesteuerte Wiedergabe ist wegen reduzierter Bewegung deaktiviert. Momentaufnahmen manuell durchgehen.",
920
+ accordionSearch: "Abschnitte filtern",
921
+ accordionNoMatches: "Keine passenden Abschnitte",
922
+ accordionCopyTitle: "Titel kopieren",
923
+ accordionCopied: "Kopiert",
917
924
  tabsMore: "Mehr",
918
925
  tabsMoreSelected: "Mehr: {label}",
919
926
  tabsScrollPrevious: "Vorherige Tabs",
@@ -524,6 +524,9 @@ const labels = Object.freeze({
524
524
  calendarOutsideRange: "Fuera de las fechas que muestra este calendario",
525
525
  calendarClose: "Cerrar",
526
526
  calendarDetailsOf: "Detalles de {title}",
527
+ calendarReset: "Restablecer",
528
+ calendarSharedBy: "Compartido por {names}",
529
+ calendarSourcesShown: "{shown} de {total}",
527
530
  flowSteps: "Pasos",
528
531
  flowStepOf: "Paso {current} de {count}",
529
532
  flowStepAnnounce: "Paso {current} de {count}, {title}",
@@ -914,6 +917,10 @@ const labels = Object.freeze({
914
917
  timePosition: "Instantánea {index} de {count}",
915
918
  timeFrame: "Instantánea de {time}",
916
919
  timeReducedMotion: "La reproducción automática está desactivada porque el movimiento reducido está activado. Recorre las instantáneas manualmente.",
920
+ accordionSearch: "Filtrar secciones",
921
+ accordionNoMatches: "No hay secciones coincidentes",
922
+ accordionCopyTitle: "Copiar título",
923
+ accordionCopied: "Copiado",
917
924
  tabsMore: "Más",
918
925
  tabsMoreSelected: "Más: {label}",
919
926
  tabsScrollPrevious: "Pestañas anteriores",
@@ -524,6 +524,9 @@ const labels = Object.freeze({
524
524
  calendarOutsideRange: "En dehors des dates de ce calendrier",
525
525
  calendarClose: "Fermer",
526
526
  calendarDetailsOf: "Détails de {title}",
527
+ calendarReset: "Réinitialiser",
528
+ calendarSharedBy: "Partagé par {names}",
529
+ calendarSourcesShown: "{shown} sur {total}",
527
530
  flowSteps: "Étapes",
528
531
  flowStepOf: "Étape {current} sur {count}",
529
532
  flowStepAnnounce: "Étape {current} sur {count}, {title}",
@@ -914,6 +917,10 @@ const labels = Object.freeze({
914
917
  timePosition: "Instantané {index} sur {count}",
915
918
  timeFrame: "Instantané du {time}",
916
919
  timeReducedMotion: "La lecture automatique est désactivée car les mouvements réduits sont activés. Parcourez les instantanés manuellement.",
920
+ accordionSearch: "Filtrer les sections",
921
+ accordionNoMatches: "Aucune section correspondante",
922
+ accordionCopyTitle: "Copier le titre",
923
+ accordionCopied: "Copié",
917
924
  tabsMore: "Plus",
918
925
  tabsMoreSelected: "Plus : {label}",
919
926
  tabsScrollPrevious: "Onglets précédents",
@@ -524,6 +524,9 @@ const labels = Object.freeze({
524
524
  calendarOutsideRange: "Al di fuori delle date di questo calendario",
525
525
  calendarClose: "Chiudi",
526
526
  calendarDetailsOf: "Dettagli di {title}",
527
+ calendarReset: "Ripristina",
528
+ calendarSharedBy: "Condiviso da {names}",
529
+ calendarSourcesShown: "{shown} di {total}",
527
530
  flowSteps: "Passaggi",
528
531
  flowStepOf: "Passaggio {current} di {count}",
529
532
  flowStepAnnounce: "Passaggio {current} di {count}, {title}",
@@ -914,6 +917,10 @@ const labels = Object.freeze({
914
917
  timePosition: "Istantanea {index} di {count}",
915
918
  timeFrame: "Istantanea del {time}",
916
919
  timeReducedMotion: "La riproduzione automatica è disattivata perché è attiva la riduzione del movimento. Scorri le istantanee manualmente.",
920
+ accordionSearch: "Filtra le sezioni",
921
+ accordionNoMatches: "Nessuna sezione corrispondente",
922
+ accordionCopyTitle: "Copia titolo",
923
+ accordionCopied: "Copiato",
917
924
  tabsMore: "Altro",
918
925
  tabsMoreSelected: "Altro: {label}",
919
926
  tabsScrollPrevious: "Schede precedenti",
@@ -524,6 +524,9 @@ const labels = Object.freeze({
524
524
  calendarOutsideRange: "Poza datami, które pokazuje ten kalendarz",
525
525
  calendarClose: "Zamknij",
526
526
  calendarDetailsOf: "Szczegóły: {title}",
527
+ calendarReset: "Resetuj",
528
+ calendarSharedBy: "Wspólne: {names}",
529
+ calendarSourcesShown: "{shown} z {total}",
527
530
  flowSteps: "Kroki",
528
531
  flowStepOf: "Krok {current} z {count}",
529
532
  flowStepAnnounce: "Krok {current} z {count}: {title}",
@@ -914,6 +917,10 @@ const labels = Object.freeze({
914
917
  timePosition: "Stan {index} z {count}",
915
918
  timeFrame: "Stan z {time}",
916
919
  timeReducedMotion: "Automatyczne odtwarzanie jest wyłączone z powodu ograniczenia ruchu. Przeglądaj stany ręcznie.",
920
+ accordionSearch: "Filtruj sekcje",
921
+ accordionNoMatches: "Brak pasujących sekcji",
922
+ accordionCopyTitle: "Kopiuj tytuł",
923
+ accordionCopied: "Skopiowano",
917
924
  tabsMore: "Więcej",
918
925
  tabsMoreSelected: "Więcej: {label}",
919
926
  tabsScrollPrevious: "Poprzednie karty",
@@ -275,6 +275,7 @@ export type LabelName =
275
275
  | "calendarResized" | "calendarSeriesMoved" | "calendarSeriesTime" | "calendarMoveHelp" | "calendarEdit" | "calendarSaveFailed" | "calendarExport" | "calendarTimeRange" | "calendarSelected"
276
276
  | "calendarLane" | "calendarHighlighted"
277
277
  /** Standalone UI primitives; their English defaults load with the optional UI parts. */
278
+ | "accordionSearch" | "accordionNoMatches" | "accordionCopyTitle" | "accordionCopied"
278
279
  | "tabsMore" | "tabsMoreSelected" | "tabsScrollPrevious" | "tabsScrollNext" | "tabsSection" | "tabsPosition" | "tabsPause" | "tabsPlay" | "tabsMotionDisabled"
279
280
  | "stepperStepOf" | "stepperBack" | "stepperNext" | "stepperFinish" | "stepperSkip" | "stepperSaveDraft"
280
281
  | "stepperAllSteps" | "stepperOptional" | "stepperCompleted" | "stepperSkipped" | "stepperIssues" | "stepperIssue"