@evotecit/canopyx 0.3.15 → 0.3.16

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.
@@ -525,7 +525,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
525
525
  active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
526
526
  close()}else{return}
527
527
  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 position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
528
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"record-panel":["94adeb844689e329","canopyx-record-panel.d0d71d38743e3476.js","canopyx-record-panel.66edd824ab6111c1.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
528
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"record-panel":["82aa828bc880087b","canopyx-record-panel.e0736e2285995701.js","canopyx-record-panel.4b9f1a99c5b76321.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
529
529
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
530
530
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
531
531
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"42ad4b814f47bd00",install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,fill,gridButton,gridIcon,gridQuery,gridResultShape,gridQueryRows,gridCompare,gridOrder,gridIdOrder,validateGridRows,validateGridPage,validateGridCursorPage,gridFreeze,requireIdentifier,checkDocument,cellValue,PROTOCOL,GRID_REPORTING,VIEW_MODES,inlineGridSource}=context;const LIVE_KEYS=new Set(["stableOrder","flash","batchMs","pollMs","load","announce","pauseWhenHidden"]);const LIVE_MAX_ROWS=100000;function liveOptions(view,options){const read=value=>{if(value===undefined||value===true||value===false)return{};if(!value||typeof value!=="object"||Array.isArray(value)||Object.keys(value).some(key=>!LIVE_KEYS.has(key)))
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"3b3c9833ff68a72b",install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,fill,gridButton,gridIcon,gridQuery,gridResultShape,gridQueryRows,gridCompare,gridOrder,gridIdOrder,validateGridRows,validateGridPage,validateGridCursorPage,gridFreeze,requireIdentifier,checkDocument,cellValue,PROTOCOL,GRID_REPORTING,VIEW_MODES,inlineGridSource}=context;const LIVE_KEYS=new Set(["stableOrder","flash","batchMs","pollMs","load","announce","pauseWhenHidden"]);const LIVE_MAX_ROWS=100000;function liveOptions(view,options){const read=value=>{if(value===undefined||value===true||value===false)return{};if(!value||typeof value!=="object"||Array.isArray(value)||Object.keys(value).some(key=>!LIVE_KEYS.has(key)))
2
2
  throw new Error("CanopyX: live takes stableOrder, flash, batchMs, pollMs, load, announce and pauseWhenHidden.");return value};const merged=options.live===false?{}:{...read(view.live),...read(options.live)},flash=merged.flash;const integer=(value,min,max)=>value===undefined||Number.isInteger(value)&&value>=min&&value<=max;if(["stableOrder","announce","pauseWhenHidden"].some(key=>merged[key]!==undefined&&typeof merged[key]!=="boolean")||
3
3
  !(flash===undefined||typeof flash==="boolean"||flash&&typeof flash==="object"&&Object.keys(flash).every(key=>key==="durationMs")&&integer(flash.durationMs,100,10000))||
4
4
  !integer(merged.batchMs,0,60000)||!(merged.pollMs===undefined||merged.pollMs===0||integer(merged.pollMs,250,86400000))||
@@ -43,17 +43,17 @@ snapshot.matched?this.rowItem(Math.max(this.rowBounds().first,Math.min(focusInde
43
43
  this.syncQuerySummary();this.syncPager();this.syncGridChrome();this.liveAfterChange(changed,removed,positionOf,shifted)},liveAfterChange(changed,removed,positionOf,shifted){const gone=new Set(removed);if(this.querySelection){let touched=false;for(const id of gone)touched=this.selectionExcluded.delete(id)||touched;if(this.querySelection.matched!==this.snapshot.matched||this.querySelection.revision!==this.snapshot.revision){this.querySelection=gridFreeze({...this.querySelection,matched:this.snapshot.matched,revision:this.snapshot.revision});touched=true}
44
44
  if(touched)this.publishQuerySelection?.()}else if(gone.size&&[...this.selected].some(id=>gone.has(id)))this.setSelection([...this.selected].filter(id=>!gone.has(id)));if(this.formatStatsKey!==undefined)this.formatStatsKey=null;VIEW_MODES.refresh?.(this);const dialog=this.recordDrawer,id=dialog?.isConnected?dialog.getAttribute("data-cx-record"):null;if(id&&typeof dialog._cxPaint==="function"&&(changed.has(id)||gone.has(id)||shifted)){const index=gone.has(id)?-1:positionOf(id),row=index>=0?this.rowCache.get(index):null;const record=row?row.h:index<0||!this.liveInline()?null:this.liveRows().get(id);if(record)dialog._cxPaint(row?record:liveCopy(record),index);else if(gone.has(id)){dialog._cxPaint(dialog._cxRecord,null);this.liveNote(this.labels.gridLiveRecordRemoved)}
45
45
  else if(shifted&&!changed.has(id))dialog._cxPaint(dialog._cxRecord,index>=0?index:null)}
46
- this.liveFlash(changed)},async liveRequery(changed,removed){const anchor=this.liveAnchor(),active=document.activeElement,hadFocus=this.canvas.contains(active);const focusedId=this.focused&&!this.focused.status?this.focused.key:null,keep=this.dataLifetime;this.dataLifetime=new AbortController();this.summaryCandidate=null;try{await this.setQuery({...this.acceptedQuery,offset:this.paged?this.pageOffset:0,revision:undefined})}
47
- finally{const current=this.dataLifetime;if(current.signal.aborted||this.destroyed)keep.abort();else current.signal.addEventListener("abort",()=>keep.abort(),{once:true})}
46
+ this.liveFlash(changed)},async liveRequery(changed,removed,ownerSignal){const anchor=this.liveAnchor(),active=document.activeElement,hadFocus=this.canvas.contains(active);const focusedId=this.focused&&!this.focused.status?this.focused.key:null,keep=this.dataLifetime;this.dataLifetime=new AbortController();this.summaryCandidate=null;let queryLifetime,queryEpoch;const cancel=()=>queryLifetime?.abort();try{const query=this.setQuery({...this.acceptedQuery,offset:this.paged?this.pageOffset:0,revision:undefined});queryLifetime=this.dataLifetime;queryEpoch=this.queryEpoch;ownerSignal?.addEventListener("abort",cancel,{once:true});if(ownerSignal?.aborted)cancel();await query}
47
+ finally{ownerSignal?.removeEventListener("abort",cancel);const current=this.dataLifetime;if(this.queryEpoch!==queryEpoch||current.signal.aborted||this.destroyed)keep.abort();else current.signal.addEventListener("abort",()=>keep.abort(),{once:true})}
48
48
  this.setLogicalTop(Math.min(anchor.top,this.total));this.render();for(let wait=0;wait<8&&this.pendingPages.size&&!this.destroyed;wait++)await Promise.race([...this.pendingPages.values()].map(token=>token.promise));const focus=focusedId&&[...this.rowCache.values()].find(row=>row.key===focusedId);if(focus)this.focused=focus;if(hadFocus&&!this.canvas.contains(document.activeElement))(focus&&this.rendered.get(focus)||this.grid).focus({preventScroll:true});const dialog=this.recordDrawer,id=dialog?.isConnected?dialog.getAttribute("data-cx-record"):null,row=id&&[...this.rowCache.values()].find(item=>item.key===id);if(row&&changed.has(id))dialog._cxPaint(row.h,row._ri);else if(id&&new Set(removed).has(id)){dialog._cxPaint(dialog._cxRecord,null);this.liveNote(this.labels.gridLiveRecordRemoved)}
49
49
  if(dialog?.contains(active)&&!dialog.contains(document.activeElement))active.focus?.({preventScroll:true});this.liveAfterChange(changed,removed,()=>-1,false)}});Object.assign(DataGrid.prototype,{liveHeldOffsets(){const offsets=new Set([0]),bounds=this.rowBounds(),size=this.pageSize;if(this.focused&&this.focused._ri>=0)offsets.add(Math.floor(this.focused._ri / size) * size);
50
50
  if(this.paged)offsets.add(Math.floor(this.pageOffset / size) * size);
51
51
  for(const range of this.window?this.window.ranges||[this.window]:[])
52
52
  for(let page=Math.floor(Math.max(bounds.first,range.first)/ size) * size; page <= Math.min(bounds.last, range.last); page += size) offsets.add(page);
53
- return[...offsets].slice(0,4).sort((a,b)=>a-b)},async liveRefreshHost(force){if(this.cursor)return this.liveRefreshCursor();const offsets=this.liveHeldOffsets(),lifetime=this.dataLifetime,epoch=this.queryEpoch,accepted=this.acceptedQuery;const ask=async(offset,snapshot)=>{const query=gridQuery(this.view,{...accepted,offset,limit:this.pageSize,revision:snapshot?snapshot.revision:undefined});const page=validateGridPage(await this.requestPage(query,lifetime.signal),this.view,query,snapshot);if(this.destroyed||epoch!==this.queryEpoch||this.acceptedQuery!==accepted)throw new DOMException("The refresh was superseded.","AbortError");return page};const first=await ask(0,null);if(!force&&(first.revision===this.snapshot.revision||first.revision===this.livePending?.snapshot?.revision))return null;const snapshot={revision:first.revision,total:first.total,matched:first.matched};if(this.liveProjected()){this.livePending=null;this.liveMoved=false;await this.liveRequery(new Map(),[]);return{changed:new Map(),removed:[],orderChanged:false,revision:this.snapshot.revision}}
53
+ return[...offsets].slice(0,4).sort((a,b)=>a-b)},async liveRefreshHost(force,signal=this.dataLifetime.signal){if(this.cursor)return this.liveRefreshCursor(signal);const offsets=this.liveHeldOffsets(),lifetime=this.dataLifetime,epoch=this.queryEpoch,accepted=this.acceptedQuery;const ask=async(offset,snapshot)=>{const query=gridQuery(this.view,{...accepted,offset,limit:this.pageSize,revision:snapshot?snapshot.revision:undefined});const page=validateGridPage(await this.requestPage(query,signal),this.view,query,snapshot);if(signal.aborted||this.destroyed||epoch!==this.queryEpoch||this.acceptedQuery!==accepted)throw new DOMException("The refresh was superseded.","AbortError");return page};const first=await ask(0,null);if(!force&&(first.revision===this.snapshot.revision||first.revision===this.livePending?.snapshot?.revision))return null;const snapshot={revision:first.revision,total:first.total,matched:first.matched};if(this.liveProjected()){this.livePending=null;this.liveMoved=false;await this.liveRequery(new Map(),[],signal);return{changed:new Map(),removed:[],orderChanged:false,revision:this.snapshot.revision}}
54
54
  const pages=new Map([[0,first.items]]);for(const offset of offsets)if(offset&&offset<snapshot.matched)pages.set(offset,(await ask(offset,snapshot)).items);const position=new Map(),fresh=new Map();for(const[offset,items]of pages)items.forEach((item,index)=>{position.set(item.id,offset+index);fresh.set(item.id,item)});const changed=new Map(),held=new Map();for(const row of this.rowCache.values())if(!row.status)held.set(row.key,row);for(const[id,item]of fresh){const row=held.get(id),columns=row?liveChangedColumns(row.h,item):"*";if(columns==="*"||columns.size)changed.set(id,columns)}
55
55
  const seen=[...this.rendered.keys()].filter(row=>!row.status&&row.key).sort((a,b)=>a._ri-b._ri).map(row=>row.key);const before=seen.filter(id=>position.has(id)),after=[...before].sort((a,b)=>position.get(a)- position.get(b));const moved=before.some((id,index)=>id!==after[index]);if(moved&&this.liveOpts.stableOrder&&!force){this.liveSetHeld(fresh,false);this.livePending={snapshot,pages};this.liveSyncPrompt();return{changed,removed:[],orderChanged:true,revision:snapshot.revision}}
56
- this.livePending=null;this.liveMoved=false;this.liveSwap(snapshot,()=>pages,id=>position.get(id)??-1,changed,[]);this.liveSyncPrompt();return{changed,removed:[],orderChanged:false,revision:snapshot.revision}},async liveRefreshCursor(){const query=gridQuery(this.view,{...this.acceptedQuery,cursor:undefined,revision:undefined,limit:this.pageLength});const page=validateGridCursorPage(await this.requestPage(query,this.dataLifetime.signal),this.view,query,null);if(this.destroyed||page.revision===this.snapshot.revision||page.revision===this.livePending?.revision)return null;this.livePending={cursor:true,revision:page.revision};this.liveSyncPrompt();return{changed:new Map(),removed:[],orderChanged:false,newData:true,revision:page.revision}},liveSetHeld(changes,merge){const changed=new Map(),loaded=new Set(),pages=new Set(),query=this.acceptedQuery,used=new Set(query.sort.map(sort=>sort.column));const walk=group=>{if(!group)return;for(const filter of group.filters)used.add(filter.column);group.groups.forEach(walk)};for(const filter of query.filters)used.add(filter.column);walk(query.filterGroup);const searched=!!query.search;let moved=false;for(const row of this.rowCache.values()){const change=!row.status&&changes.get(row.key);if(!change)continue;loaded.add(row.key);const after=merge?liveMerged(row.h,change):liveCopy(change),columns=liveChangedColumns(row.h,after);if(!columns.size&&liveSameRow(row.h,after))continue;row.h=after;changed.set(row.key,columns);pages.add(Math.floor(row._ri / this.pageSize) * this.pageSize);
56
+ this.livePending=null;this.liveMoved=false;this.liveSwap(snapshot,()=>pages,id=>position.get(id)??-1,changed,[]);this.liveSyncPrompt();return{changed,removed:[],orderChanged:false,revision:snapshot.revision}},async liveRefreshCursor(signal=this.dataLifetime.signal){const query=gridQuery(this.view,{...this.acceptedQuery,cursor:undefined,revision:undefined,limit:this.pageLength});const page=validateGridCursorPage(await this.requestPage(query,signal),this.view,query,null);if(signal.aborted)throw new DOMException("The refresh was superseded.","AbortError");if(this.destroyed||page.revision===this.snapshot.revision||page.revision===this.livePending?.revision)return null;this.livePending={cursor:true,revision:page.revision};this.liveSyncPrompt();return{changed:new Map(),removed:[],orderChanged:false,newData:true,revision:page.revision}},liveSetHeld(changes,merge){const changed=new Map(),loaded=new Set(),pages=new Set(),query=this.acceptedQuery,used=new Set(query.sort.map(sort=>sort.column));const walk=group=>{if(!group)return;for(const filter of group.filters)used.add(filter.column);group.groups.forEach(walk)};for(const filter of query.filters)used.add(filter.column);walk(query.filterGroup);const searched=!!query.search;let moved=false;for(const row of this.rowCache.values()){const change=!row.status&&changes.get(row.key);if(!change)continue;loaded.add(row.key);const after=merge?liveMerged(row.h,change):liveCopy(change),columns=liveChangedColumns(row.h,after);if(!columns.size&&liveSameRow(row.h,after))continue;row.h=after;changed.set(row.key,columns);pages.add(Math.floor(row._ri / this.pageSize) * this.pageSize);
57
57
  if(searched||[...columns].some(id=>used.has(id)))moved=true}
58
58
  if(merge&&this.livePending?.pages){for(const items of this.livePending.pages.values())for(let index=0;index<items.length;index++){const item=items[index],change=loaded.has(item.id)&&changes.get(item.id);if(!change)continue;const after=liveMerged(item,change),columns=liveChangedColumns(item,after);items[index]=after;if(!liveSameRow(item,after)&&(searched||[...columns].some(id=>used.has(id))))moved=true}
59
59
  if(moved)this.livePending={refresh:true}}
@@ -68,22 +68,27 @@ this.lifetime.signal.addEventListener("abort",()=>{bar.remove();this.host.classL
68
68
  const wasHidden=this.liveBar.hidden||this.liveBarCursor!==cursor;setText(this.liveBarText,cursor?this.labels.gridLiveNewData:this.labels.gridLiveOrderChanged);setText(this.liveBarButton,cursor?this.labels.gridLiveRefresh:this.labels.gridLiveResort);this.liveBarButton.title=cursor?"":this.labels.gridLiveOrderHint;this.liveBarCursor=cursor;if(this.liveBar.classList.contains("cx-live-float"))this.liveBar.style.top=this.grid.offsetTop+this.head.offsetHeight+6+"px";this.liveBar.hidden=false;if(wasHidden)this.liveNote(cursor?this.labels.gridLiveNewData:this.labels.gridLiveOrderChanged+". "+this.labels.gridLiveOrderHint)},liveFlash(changed){const duration=this.liveOpts?.flashMs;if(!duration||!changed.size)return;const now=performance.now(),flashes=this.liveFlashes||=new Map();for(const[id,columns]of changed){const existing=flashes.get(id),merged=columns==="*"||existing?.columns==="*"?"*":new Set([...(existing?.columns||[]),...columns]);if(merged!=="*"&&!merged.size)continue;flashes.set(id,{columns:merged,start:now,until:now+duration})}
69
69
  clearTimeout(this.liveFlashTimer);this.liveFlashTimer=setTimeout(()=>this.liveFlashExpire(),duration+20);this.version++;this.scheduleRender()},liveFlashExpire(){if(this.destroyed||!this.liveFlashes)return;const now=performance.now();for(const[id,flash]of this.liveFlashes)if(flash.until<=now)this.liveFlashes.delete(id);if(this.liveFlashes.size)this.liveFlashTimer=setTimeout(()=>this.liveFlashExpire(),Math.max(20,Math.min(...[...this.liveFlashes.values()].map(flash=>flash.until))- now+20));this.version++;this.scheduleRender()},liveAnnounce(result){if(!this.liveOpts?.announce||!result.added.length&&!result.removed.length)return;const counts=this.liveCounts||={added:0,updated:0,removed:0};counts.added +=result.added.length;counts.updated +=result.updated.length;counts.removed +=result.removed.length;if(this.liveAnnounceTimer)return;if(!this.liveSpoke||performance.now()- this.liveSpoke>=LIVE_ANNOUNCE_MS){this.liveNote(this.liveCountText());this.liveCoolDown()}
70
70
  else this.liveAnnounceTimer=setTimeout(()=>{this.liveAnnounceTimer=0;this.liveSay(this.liveCountText());this.liveCoolDown()},LIVE_ANNOUNCE_MS -(performance.now()- this.liveSpoke))},liveCountText(){const numbers=new Intl.NumberFormat(this.lang),counts=this.liveCounts;this.liveCounts=null;return counts?fill(this.labels.gridLiveChanged,{added:numbers.format(counts.added),updated:numbers.format(counts.updated),removed:numbers.format(counts.removed)}):""},liveCoolDown(){this.liveSpoke=performance.now();this.liveAnnounceTimer=setTimeout(()=>{this.liveAnnounceTimer=0;if(this.liveCounts&&!this.destroyed){this.liveSay(this.liveCountText());this.liveCoolDown()}},LIVE_ANNOUNCE_MS)}});const LIVE_FILL=DataGrid.prototype.fillRow;DataGrid.prototype.fillRow=function(element,row){LIVE_FILL.call(this,element,row);const flash=this.liveFlashes?.size&&!row.status&&row.key?this.liveFlashes.get(row.key):null,mark=flash?row.key+"@"+flash.start:null;if(element._cxFlash&&element._cxFlashMark===mark&&element._cxFlashLayout===element._layout)return;if(element._cxFlash){for(const cell of element._cxFlash){cell.classList.remove("cx-live-flash");cell.style.removeProperty("animation-delay")}element._cxFlash=null;element._cxFlashMark=null}
71
- if(!flash||!element._cells)return;const now=performance.now();if(flash.until<=now)return;const marked=[];element._cells.forEach((slot,index)=>{const column=this.cols[index];if(!slot||!column||flash.columns!=="*"&&!flash.columns.has(column.id))return;slot.cell.classList.add("cx-live-flash");slot.cell.style.animationDelay=Math.round(flash.start-now)+ "ms";marked.push(slot.cell)});if(marked.length){element._cxFlash=marked;element._cxFlashMark=mark;element._cxFlashLayout=element._layout}};Object.assign(DataGrid.prototype,{startLive(){if(this.view.rowIdentity==="ordinal")throw new Error("CanopyX: ordinal row identity is snapshot-local; keyed live updates require stable row keys.");if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");if(this.liveOpts)return;this.liveOpts=liveOptions(this.view,this.opts);this.liveQueue=new Map();this.liveWaiters=[];this.liveScheduled=new Set();if(this.liveOpts.flashMs)this.host.style.setProperty("--cx-live-flash-ms",this.liveOpts.flashMs+"ms");this.host.addEventListener("canopyx:query",()=>{if(this.liveOrder&&this.liveOrder.shape!==gridResultShape(this.acceptedQuery))this.liveOrder=null;this.livePending=null;this.liveMoved=false;this.liveSyncPrompt()},{signal:this.lifetime.signal});this.lifetime.signal.addEventListener("abort",()=>{clearTimeout(this.liveTimer);clearTimeout(this.liveFlashTimer);clearTimeout(this.liveAnnounceTimer);this.host.style.removeProperty("--cx-live-flash-ms");for(const waiter of this.liveWaiters.splice(0))waiter.reject(new DOMException("Grid was destroyed.","AbortError"))},{once:true});if(this.liveOpts.pollMs)this.livePoll({intervalMs:this.liveOpts.pollMs})},liveStatus(){const queued=new Set(this.liveQueue?.keys());for(const{change}of this.liveScheduled||[])if(change){for(const row of[...change.add,...change.update])queued.add(row.id);change.remove.forEach(id=>queued.add(id))}
71
+ if(!flash||!element._cells)return;const now=performance.now();if(flash.until<=now)return;const marked=[];element._cells.forEach((slot,index)=>{const column=this.cols[index];if(!slot||!column||flash.columns!=="*"&&!flash.columns.has(column.id))return;slot.cell.classList.add("cx-live-flash");slot.cell.style.animationDelay=Math.round(flash.start-now)+ "ms";marked.push(slot.cell)});if(marked.length){element._cxFlash=marked;element._cxFlashMark=mark;element._cxFlashLayout=element._layout}};Object.assign(DataGrid.prototype,{startLive(){if(this.view.rowIdentity==="ordinal")throw new Error("CanopyX: ordinal row identity is snapshot-local; keyed live updates require stable row keys.");if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");if(this.liveOpts)return;this.liveOpts=liveOptions(this.view,this.opts);this.liveQueue=new Map();this.liveWaiters=[];this.liveScheduled=new Set();this.liveProjection=null;if(this.liveOpts.flashMs)this.host.style.setProperty("--cx-live-flash-ms",this.liveOpts.flashMs+"ms");this.host.addEventListener("canopyx:query",()=>{if(this.liveOrder&&this.liveOrder.shape!==gridResultShape(this.acceptedQuery))this.liveOrder=null;this.livePending=null;this.liveMoved=false;this.liveProjection=null;this.liveSyncPrompt()},{signal:this.lifetime.signal});this.lifetime.signal.addEventListener("abort",()=>{clearTimeout(this.liveTimer);clearTimeout(this.liveFlashTimer);clearTimeout(this.liveAnnounceTimer);this.liveProjection=null;this.host.style.removeProperty("--cx-live-flash-ms");for(const waiter of this.liveWaiters.splice(0))waiter.reject(new DOMException("Grid was destroyed.","AbortError"))},{once:true});if(this.liveOpts.pollMs)this.livePoll({intervalMs:this.liveOpts.pollMs})},liveStatus(){const queued=new Set(this.liveQueue?.keys());for(const id of this.liveProjection?.ids||[])queued.add(id);for(const{change}of this.liveScheduled||[])if(change){for(const row of[...change.add,...change.update])queued.add(row.id);change.remove.forEach(id=>queued.add(id))}
72
72
  return gridFreeze({orderChanged:!!(this.liveOrder?.dirty||this.livePending?.pages||this.livePending?.refresh||this.liveMoved),newData:!!this.livePending?.cursor,pending:queued.size,polling:!!this.livePoller?.active,revision:this.snapshot?.revision??null})},liveRun(task){return this.liveChain=(this.liveChain||Promise.resolve()).catch(()=>{}).then(async()=>{this.startLive();await this.liveSettle();return task()})},applyTransaction(input){return this.liveQueueChange(liveTransaction(this,input),"api")},addRows(rows){return this.applyTransaction({add:rows})},updateRows(rows){return this.applyTransaction({update:rows})},removeRows(ids){return this.applyTransaction({remove:ids})},async setRows(rows){if(!this.liveInline())throw new Error("CanopyX: setRows replaces inline rows; a hosted grid's rows change at its source, then refreshRows().");validateGridRows(rows,this.view.columns);const owned=liveCopy(rows);return this.liveQueueChange(null,"api",owned)},liveQueueChange(change,source,replacement){if(this.destroyed)return Promise.reject(new DOMException("Grid was destroyed.","AbortError"));try{this.startLive()}catch(error){return Promise.reject(error)}
73
73
  if(this.view.source.kind==="inline"&&this.opts.source)
74
74
  return Promise.reject(new Error("CanopyX: this grid's rows belong to its own source; change them through it (an enhanced grid's setData, addRows and removeRows)."));if(!this.liveInline()&&(change.add.length||change.remove.length))
75
75
  return Promise.reject(new Error("CanopyX: rows of a hosted grid are added and removed at its source; call refreshRows() after."));const scheduled={change};this.liveScheduled.add(scheduled);let waiter;const promise=new Promise((resolve,reject)=>{waiter={resolve,reject}});this.liveRun(async()=>{if(replacement){await this.liveFlush().catch(()=>{});change=liveTransaction(this,liveDiff(replacement,this.liveRows()))}
76
- this.liveScheduled.delete(scheduled);this.liveEnqueueChange(change,source,waiter)}).catch(error=>{this.liveScheduled.delete(scheduled);waiter.reject(error)});return promise},liveEnqueueChange(change,source,waiter){liveEnqueue(this.liveQueue,change);this.liveWaiters.push(waiter);this.liveSource=this.liveSource&&this.liveSource!==source?"api":source;if(!this.liveOpts.batchMs)this.flushTransactions().catch(()=>{});else if(!this.liveTimer)this.liveTimer=setTimeout(()=>this.flushTransactions().catch(()=>{}),this.liveOpts.batchMs)},flushTransactions(){clearTimeout(this.liveTimer);this.liveTimer=0;return this.liveRun(()=>this.liveFlush())},async liveFlush(){clearTimeout(this.liveTimer);this.liveTimer=0;const queue=this.liveQueue,waiters=this.liveWaiters.splice(0),source=this.liveSource||"api";this.liveQueue=new Map();this.liveSource=null;try{const result=queue.size?await this.liveApply(queue,source):liveResult();waiters.forEach(waiter=>waiter.resolve(result));return result}catch(error){waiters.forEach(waiter=>waiter.reject(error));throw error}},async liveSettle(){if(!this.acceptedQuery&&!this.pendingQuery)await this.ready.catch(()=>{});while(!this.destroyed&&this.pendingQuery)await new Promise(resolve=>setTimeout(resolve,16));if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");if(!this.acceptedQuery)throw new Error("CanopyX: live changes need an accepted query.");if(this.view.rowData&&this.liveInline()){await this.source.decoded;delete this.view.rowData;this.source=inlineGridSource(this.view)}},liveInlinePages(order){const rows=this.liveRows(),size=this.pageSize;return(anchor,focus)=>{const span=Math.ceil((this.grid.clientHeight||600)/ this.rowH) + 30, offsets = new Set();
76
+ this.liveScheduled.delete(scheduled);this.liveEnqueueChange(change,source,waiter)}).catch(error=>{this.liveScheduled.delete(scheduled);waiter.reject(error)});return promise},liveEnqueueChange(change,source,waiter){liveEnqueue(this.liveQueue,change);this.liveWaiters.push(waiter);this.liveSource=this.liveSource&&this.liveSource!==source?"api":source;if(!this.liveOpts.batchMs)this.flushTransactions().catch(()=>{});else if(!this.liveTimer)this.liveTimer=setTimeout(()=>this.flushTransactions().catch(()=>{}),this.liveOpts.batchMs)},flushTransactions(){clearTimeout(this.liveTimer);this.liveTimer=0;return this.liveRun(()=>this.liveFlush())},async liveFlush(){clearTimeout(this.liveTimer);this.liveTimer=0;const queue=this.liveQueue,waiters=this.liveWaiters.splice(0),source=this.liveSource||this.liveProjection?.source||"api";this.liveQueue=new Map();this.liveSource=null;try{const result=queue.size||this.liveProjection?await this.liveApply(queue,source):liveResult();waiters.forEach(waiter=>waiter.resolve(result));return result}catch(error){waiters.forEach(waiter=>waiter.reject(error));throw error}},async liveSettle(){if(!this.acceptedQuery&&!this.pendingQuery)await this.ready.catch(()=>{});while(!this.destroyed&&this.pendingQuery)await new Promise(resolve=>setTimeout(resolve,16));if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");if(!this.acceptedQuery)throw new Error("CanopyX: live changes need an accepted query.");if(this.view.rowData&&this.liveInline()){await this.source.decoded;delete this.view.rowData;this.source=inlineGridSource(this.view)}},liveInlinePages(order){const rows=this.liveRows(),size=this.pageSize;return(anchor,focus)=>{const span=Math.ceil((this.grid.clientHeight||600)/ this.rowH) + 30, offsets = new Set();
77
77
  const[first,last]=this.paged?[this.pageOffset,this.pageOffset+this.pageLength-1]:[Math.max(0,anchor-span),anchor+2*span];for(let page=Math.floor(first / size) * size; page <= Math.min(last, order.ids.length - 1); page += size) offsets.add(page);
78
78
  if(focus>=0)offsets.add(Math.floor(focus / size) * size);
79
- return new Map([...offsets].map(offset=>[offset,order.ids.slice(offset,offset+size).map(id=>liveCopy(rows.get(id)))]))}},liveSwapInline(changed,removed,shifted){const order=this.liveOrder;this.liveSwap({revision:this.snapshot.revision,total:this.liveRows().size,matched:order.ids.length},this.liveInlinePages(order),id=>order.at.get(id)??-1,changed,removed,shifted)},async liveApply(queue,source){let outcome;if(this.liveInline()){const projected=this.liveProjected(),{result,changed}=this.liveApplyRows(queue,!projected);if(changed.size||result.removed.length){if(!this.opts.source)this.source=inlineGridSource(this.view);this.liveOrderSource=this.source;if(projected)await this.liveRequery(changed,result.removed);else this.liveSwapInline(changed,result.removed,result.added.length>0||result.removed.length>0||!this.liveOpts.stableOrder)}
79
+ return new Map([...offsets].map(offset=>[offset,order.ids.slice(offset,offset+size).map(id=>liveCopy(rows.get(id)))]))}},liveSwapInline(changed,removed,shifted){const order=this.liveOrder;this.liveSwap({revision:this.snapshot.revision,total:this.liveRows().size,matched:order.ids.length},this.liveInlinePages(order),id=>order.at.get(id)??-1,changed,removed,shifted)},async liveApply(queue,source,ownerSignal){let outcome;if(this.liveInline()){const projected=this.liveProjected(),before=this.view.rows;let{result,changed}=this.liveApplyRows(queue,!projected);if(changed.size||result.removed.length){if(!this.opts.source)this.source=inlineGridSource(this.view);this.liveOrderSource=this.source;if(projected){this.liveProjection||={rows:new Map(before.map(row=>[row.id,row])),source};if(this.liveProjection.source!==source)this.liveProjection.source="api"}
80
+ else this.liveSwapInline(changed,result.removed,result.added.length>0||result.removed.length>0||!this.liveOpts.stableOrder)}
81
+ if(projected&&this.liveProjection){const pending=this.liveProjection,delta=liveDiff(this.view.rows,pending.rows);source=pending.source;changed=new Map(delta.add.map(row=>[row.id,"*"]));result={...result,added:delta.add.filter(row=>!pending.rows.has(row.id)).map(row=>row.id),updated:delta.add.filter(row=>pending.rows.has(row.id)).map(row=>row.id),removed:delta.remove};pending.ids=new Set([...result.added,...result.updated,...result.removed]);await this.liveRequery(changed,result.removed,ownerSignal);if(this.liveProjection===pending)this.liveProjection=null}
80
82
  outcome={...result,orderChanged:!!this.liveOrder?.dirty}}else{const updates=new Map([...queue.values()].map(change=>[change.id,change.row]));const{changed,moved,loaded}=this.liveSetHeld(updates,true);if(moved)this.liveMoved=true;outcome={added:[],updated:[...changed.keys()],removed:[],missing:[...updates.keys()].filter(id=>!loaded.has(id)),orderChanged:this.liveMoved}}
81
- const recordNote=!!this.liveNotes?.length;this.liveSyncPrompt();if(!recordNote)this.liveAnnounce(outcome);this.liveSpeak();return this.liveReport(outcome,source)},liveReport(outcome,source){const detail=gridFreeze({added:outcome.added||[],updated:outcome.updated||[],removed:outcome.removed||[],missing:outcome.missing||[],orderChanged:!!outcome.orderChanged,newData:!!outcome.newData,revision:outcome.revision??this.snapshot?.revision??null,source});if(detail.added.length||detail.updated.length||detail.removed.length||detail.newData||detail.orderChanged||outcome.refreshed)this.emit("rowsChanged",detail);return detail},refreshRows(){return this.liveRefresh("refresh")},liveRefresh(source){return this.liveRun(async()=>{if(this.liveInline()){if(!this.liveOpts.load)return liveResult();await this.liveFlush().catch(()=>{});let answer=await this.runGridHook(signal=>this.liveOpts.load({signal,query:this.acceptedQuery,rows:this.view.rows.length}),this.dataLifetime.signal);if(answer==null)return liveResult();if(Array.isArray(answer)){validateGridRows(answer,this.view.columns);answer=liveCopy(answer)}
82
- const change=liveTransaction(this,Array.isArray(answer)?liveDiff(answer,this.liveRows()):answer),queue=new Map();liveEnqueue(queue,change);return this.liveApply(queue,source)}
83
- if(this.view.source.kind==="inline")return liveResult();const outcome=await this.liveRefreshHost(false);if(!outcome)return liveResult();const changed=[...outcome.changed].filter(([,columns])=>columns!=="*").map(([id])=>id);this.liveSpeak();return this.liveReport({updated:changed,orderChanged:outcome.orderChanged,newData:outcome.newData,revision:outcome.revision,refreshed:true},source)})},resort(){return this.liveRun(async()=>{const pending=this.livePending,revision=this.snapshot?.revision;if(pending?.cursor){this.livePending=null;this.liveSyncPrompt();await this.setQuery({...this.acceptedQuery,cursor:undefined,revision:undefined},{pageLength:this.pageLength});return}
83
+ const recordNote=!!this.liveNotes?.length;this.liveSyncPrompt();if(!recordNote)this.liveAnnounce(outcome);this.liveSpeak();return this.liveReport(outcome,source)},liveReport(outcome,source){const detail=gridFreeze({added:outcome.added||[],updated:outcome.updated||[],removed:outcome.removed||[],missing:outcome.missing||[],orderChanged:!!outcome.orderChanged,newData:!!outcome.newData,revision:outcome.revision??this.snapshot?.revision??null,source});if(detail.added.length||detail.updated.length||detail.removed.length||detail.newData||detail.orderChanged||outcome.refreshed)this.emit("rowsChanged",detail);return detail},refreshRows(){return this.liveRefresh("refresh")},liveRefresh(source,pollSignal){return this.liveRun(async()=>{if(this.liveInline()){if(!this.liveOpts.load)return this.liveProjection?this.liveFlush():liveResult();await this.liveFlush().catch(()=>{})}
84
+ const dataSignal=this.dataLifetime.signal,controller=new AbortController();const signals=[dataSignal,pollSignal].filter(Boolean),abort=()=>controller.abort();for(const signal of signals){signal.addEventListener("abort",abort,{once:true});if(signal.aborted)abort()}
85
+ try{if(this.liveInline()){let answer=await this.runGridHook(signal=>this.liveOpts.load({signal,query:this.acceptedQuery,rows:this.view.rows.length}),controller.signal);if(controller.signal.aborted)throw new DOMException("Grid poll cancelled.","AbortError");if(answer==null)return liveResult();if(Array.isArray(answer)){validateGridRows(answer,this.view.columns);answer=liveCopy(answer)}
86
+ const change=liveTransaction(this,Array.isArray(answer)?liveDiff(answer,this.liveRows()):answer),queue=new Map();liveEnqueue(queue,change);return await this.liveApply(queue,source,controller.signal)}
87
+ if(this.view.source.kind==="inline")return liveResult();const outcome=await this.liveRefreshHost(false,controller.signal);if(!outcome)return liveResult();const changed=[...outcome.changed].filter(([,columns])=>columns!=="*").map(([id])=>id);this.liveSpeak();return this.liveReport({updated:changed,orderChanged:outcome.orderChanged,newData:outcome.newData,revision:outcome.revision,refreshed:true},source)}catch(error){if(source==="poll"&&error?.name==="AbortError"&&!controller.signal.aborted)throw new Error(error.message,{cause:error});throw error}finally{for(const signal of signals)signal.removeEventListener("abort",abort)}})},resort(){return this.liveRun(async()=>{const pending=this.livePending,revision=this.snapshot?.revision;if(pending?.cursor){this.livePending=null;this.liveSyncPrompt();await this.setQuery({...this.acceptedQuery,cursor:undefined,revision:undefined},{pageLength:this.pageLength});return}
84
88
  if(this.liveInline()){this.liveOrder=null;this.liveMoved=false;if(this.liveProjected())await this.liveRequery(new Map(),[]);else{this.liveOrderOf();this.liveSwapInline(new Map(),[],true)}}else if(pending?.pages){this.livePending=null;this.liveMoved=false;const position=new Map();for(const[offset,items]of pending.pages)items.forEach((item,index)=>position.set(item.id,offset+index));this.liveSwap(pending.snapshot,()=>pending.pages,id=>position.get(id)??-1,new Map(),[])}else{this.liveMoved=false;await this.liveRefreshHost(true)}
85
89
  this.liveSyncPrompt();if(!this.liveInline()&&this.snapshot?.revision!==revision)this.liveReport({refreshed:true,revision:this.snapshot.revision},"refresh");this.liveNote(this.labels.gridLiveSorted);this.liveSpeak()})},async poll(options={}){return this.livePoll(options)},livePoll(options){this.startLive();if(!options||typeof options!=="object"||Array.isArray(options))throw new Error("CanopyX: poll takes options.");const interval=options.intervalMs??this.liveOpts.pollMs,hidden=options.pauseWhenHidden??this.liveOpts.pauseWhenHidden;if(!Number.isInteger(interval)||interval<250||interval>86400000||typeof hidden!=="boolean"||options.load!==undefined&&typeof options.load!=="function")
86
- throw new Error("CanopyX: poll needs intervalMs from 250 to 86400000.");if(options.load)this.liveOpts.load=options.load;if(this.liveInline()&&!this.liveOpts.load)throw new Error("CanopyX: an inline grid polls a load function (live.load or poll({ load })).");this.livePoller?.stop();const lifetime=new AbortController();let timer=0,running=null,paused=false,due=false;const schedule=()=>{clearTimeout(timer);timer=paused||lifetime.signal.aborted?0:setTimeout(tick,interval)};const tick=now=>{clearTimeout(timer);timer=0;if(lifetime.signal.aborted||paused&&!now)return Promise.resolve();if(hidden&&document.hidden&&!now){due=true;return Promise.resolve()}
87
- if(running)return running;return running=this.liveRefresh("poll").then(()=>undefined,error=>{if(error?.name!=="AbortError")this.emit("error",{error})})
88
- .finally(()=>{running=null;schedule()})};const stop=()=>{lifetime.abort();clearTimeout(timer);if(this.livePoller===poller)this.livePoller=null};document.addEventListener("visibilitychange",()=>{if(!document.hidden&&due&&!paused){due=false;tick()}},{signal:lifetime.signal});this.lifetime.signal.addEventListener("abort",stop,{once:true,signal:lifetime.signal});const poller=Object.freeze({pause(){paused=true;clearTimeout(timer);timer=0},resume(){if(!paused||lifetime.signal.aborted)return;paused=false;due=false;tick()},stop,refresh:()=>tick(true),get paused(){return paused},get active(){return!lifetime.signal.aborted&&!paused}});this.livePoller=poller;if(options.immediate)tick();else schedule();return poller}});function liveResult(){return gridFreeze({added:[],updated:[],removed:[],missing:[],orderChanged:false,newData:false,revision:null,source:"api"})}
90
+ throw new Error("CanopyX: poll needs intervalMs from 250 to 86400000.");if(options.onRefresh!==undefined&&typeof options.onRefresh!=="function")throw new Error("CanopyX: poll onRefresh must be a function.");if(options.load)this.liveOpts.load=options.load;if(this.liveInline()&&!this.liveOpts.load)throw new Error("CanopyX: an inline grid polls a load function (live.load or poll({ load })).");this.livePoller?.stop();const lifetime=new AbortController();let timer=0,running=null,cycle=null,paused=false,due=false;const schedule=()=>{clearTimeout(timer);timer=paused||lifetime.signal.aborted||hidden&&document.hidden?0:setTimeout(tick,interval)};const tick=now=>{clearTimeout(timer);timer=0;if(lifetime.signal.aborted||paused&&!now)return Promise.resolve();if(hidden&&document.hidden&&!now){due=true;return Promise.resolve()}
91
+ if(running)return running;due=false;cycle=new AbortController();return running=this.liveRefresh("poll",cycle.signal).then(result=>{if(!lifetime.signal.aborted&&!cycle.signal.aborted&&options.onRefresh){try{options.onRefresh(result)}catch(error){this.emit("error",{error})}}},error=>{if(error?.name!=="AbortError")this.emit("error",{error})})
92
+ .finally(()=>{running=null;cycle=null;if(due&&!paused&&!lifetime.signal.aborted&&!(hidden&&document.hidden))tick();else schedule()})};const stop=()=>{lifetime.abort();cycle?.abort();clearTimeout(timer);if(this.livePoller===poller)this.livePoller=null};document.addEventListener("visibilitychange",()=>{if(!hidden)return;due=true;if(document.hidden){clearTimeout(timer);cycle?.abort()}
93
+ else if(!paused)tick()},{signal:lifetime.signal});this.lifetime.signal.addEventListener("abort",stop,{once:true,signal:lifetime.signal});const poller=Object.freeze({pause(){paused=true;cycle?.abort();clearTimeout(timer);timer=0},resume(){if(!paused||lifetime.signal.aborted)return;paused=false;due=true;tick()},stop,refresh:()=>tick(true),get paused(){return paused},get active(){return!lifetime.signal.aborted&&!paused}});this.livePoller=poller;if(options.immediate)tick();else schedule();return poller}});function liveResult(){return gridFreeze({added:[],updated:[],removed:[],missing:[],orderChanged:false,newData:false,revision:null,source:"api"})}
89
94
  installed.add(context.DataGrid.prototype)}};(global.CanopyXParts||=[]).push(["live",part])})(typeof window!=="undefined"?window:globalThis);
@@ -527,7 +527,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
527
527
  active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
528
528
  close()}else{return}
529
529
  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 position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
530
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"record-panel":["94adeb844689e329","canopyx-record-panel.d0d71d38743e3476.js","canopyx-record-panel.66edd824ab6111c1.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
530
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"record-panel":["82aa828bc880087b","canopyx-record-panel.e0736e2285995701.js","canopyx-record-panel.4b9f1a99c5b76321.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
531
531
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
532
532
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
533
533
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -109,3 +109,11 @@ html.cx-record-printing .cx-record-print{display:block;padding:0;font:var(--cx-s
109
109
  }
110
110
  @media (prefers-reduced-motion:reduce){.cx-record-toggle .cx-ico{transition:none;}}
111
111
  @media (forced-colors:active){.cx-record-tab[aria-selected="true"]{border-bottom-color:Highlight;}.cx-timeline-dot{forced-color-adjust:none;background:CanvasText;}}
112
+ .cx-record-footer{flex:none;display:flex;justify-content:flex-end;gap:var(--cx-size-8px);padding:var(--cx-size-12px) var(--cx-size-16px);border-top:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));}
113
+ .cx-record-footer .cx-record-primary{color:var(--hfx-color-accent-contrast,light-dark(#ffffff,#0c0d10));background:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));border-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
114
+ .cx-record-footer .cx-record-primary:disabled{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-color:var(--hfx-color-border,light-dark(#e2e4e7,#272a30));cursor:wait;}
115
+ .cx-record-subtitle{margin:var(--cx-size-4px) 0 0;font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
116
+ .cx-record-drawer .cx-dl dt{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--cx-size-12px);font-weight:normal;}
117
+ .cx-record-drawer .cx-dl dd{font-size:var(--cx-size-14px);}
118
+ .cx-drawer.cx-record-drawer .cx-drawer-h h4{width:auto;max-width:100%;overflow-wrap:anywhere;}
119
+ .cx-drawer.cx-record-drawer .cx-drawer-h > :not(:first-child){flex:none;}
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"94adeb844689e329",install(context){if(installed.has(context.RECORD_IMPL))return;const{RECORD_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,validateGridRows,badgeElement,loadSidecar,requireIdentifier,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField,columnNumericTone,columnValueTone,validateColumnValues}=context;const RECORD_KINDS=["items","fields","records","events","changes"],RECORD_LINK_KEY=/^[A-Za-z][\w.-]{0,31}$/, RECORD_MAX_STRUCTURE_DEPTH = 8;
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"82aa828bc880087b",install(context){if(installed.has(context.RECORD_IMPL))return;const{RECORD_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,validateGridRows,badgeElement,loadSidecar,requireIdentifier,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField,columnNumericTone,columnValueTone,validateColumnValues}=context;const RECORD_KINDS=["items","fields","records","events","changes"],RECORD_LINK_KEY=/^[A-Za-z][\w.-]{0,31}$/, RECORD_MAX_STRUCTURE_DEPTH = 8;
2
2
  const recordKind=cell=>{const kinds=isCellObject(cell)&&!Array.isArray(cell)?RECORD_KINDS.filter(name=>cell[name]!==undefined):[];if(kinds.length>1)recordFail("a cell carries at most one structured value.");return kinds[0]||null};const recordFail=message=>{throw new Error("CanopyX: "+message)};const recordText=(value,max=256)=>typeof value==="string"&&!!value.trim()&&value.length<=max;const recordGridHelpers=()=>RECORD_IMPL.grid||{};function recordCheckValue(cell,depth=0){if(cell==null)return;if(depth>RECORD_MAX_STRUCTURE_DEPTH)recordFail("structured values nest at most "+RECORD_MAX_STRUCTURE_DEPTH+" levels.");const kind=recordKind(cell);if(kind==="items")for(const item of cell.items||[])recordCheckValue(item,depth+1);if(kind==="fields")for(const field of cell.fields||[])recordCheckValue(field.value,depth+1);if(kind==="changes")for(const change of cell.changes||[]){recordCheckValue(change.before,depth+1);recordCheckValue(change.after,depth+1)}
3
3
  if(kind==="events")for(const event of cell.events||[])for(const change of event.changes||[]){recordCheckValue(change.before,depth+1);recordCheckValue(change.after,depth+1)}
4
4
  if(kind==="records")recordCheckRows(cell.records.rows||cell.records.roots,depth+1)}
@@ -136,7 +136,7 @@ return api.openRecord(ref.id,{stack:[...state.stack,entry].slice(-20),returnFocu
136
136
  function recordBack(view,dialog,steps=1){const stack=dialog._cxPanel?.stack||[],entry=stack[stack.length-steps],api=entry&&recordApi(entry.view);if(!api)return;api.openRecord(entry.id,{stack:stack.slice(0,stack.length-steps),tab:entry.tab,origin:entry.origin,back:true,returnFocus:dialog._returnFocus})
137
137
  .then(()=>recordRetire(dialog),error=>{recordAnnounce(dialog,fill(view.labels.recordUnavailable,{id:entry.id}));view.emit("error",{error})})}
138
138
  function recordRetire(dialog){if(dialog.isConnected&&dialog.open&&document.querySelectorAll("dialog.cx-drawer[open]").length>1){dialog._replaced=true;dialog.close();dialog.remove()}}
139
- RECORD_IMPL.open=async(view,id,options={})=>{requireIdentifier(id,"record ID");if(view.destroyed)recordFail("the view was destroyed.");await view.ready;const dialog=view.kind==="tree"?await recordOpenNode(view,id,options):await recordOpenRow(view,id,options);if(!dialog)return;const origin=options.origin&&dialog.querySelector('[data-cx-origin="'+CSS.escape(options.origin)+ '"]');if(origin)origin.focus({preventScroll:false});if(options.stack)recordAnnounce(dialog,fill(options.back?view.labels.recordBackTo:view.labels.recordShowing,{record:recordTitle(dialog)}))};async function recordOpenRow(view,id,options){await view.requirePart("filter-editor");let index=null,row=null;const loaded=[...view.rowCache.values()].find(item=>!item.status&&item.key===id);if(loaded){row=loaded.h;index=loaded._ri;if(!view.pendingQuery)await view.focusResult(index,false).catch(()=>{})}
139
+ RECORD_IMPL.open=async(view,id,options={})=>{requireIdentifier(id,"record ID");if(view.destroyed)recordFail("the view was destroyed.");await view.ready;if(options.reload===true)RECORD_IMPL.invalidate(view,id);const dialog=view.kind==="tree"?await recordOpenNode(view,id,options):await recordOpenRow(view,id,options);if(!dialog)return;const origin=options.origin&&dialog.querySelector('[data-cx-origin="'+CSS.escape(options.origin)+ '"]');if(origin)origin.focus({preventScroll:false});if(options.stack)recordAnnounce(dialog,fill(options.back?view.labels.recordBackTo:view.labels.recordShowing,{record:recordTitle(dialog)}))};async function recordOpenRow(view,id,options){await view.requirePart("filter-editor");let index=null,row=null;const loaded=[...view.rowCache.values()].find(item=>!item.status&&item.key===id);if(loaded){row=loaded.h;index=loaded._ri;if(!view.pendingQuery)await view.focusResult(index,false).catch(()=>{})}
140
140
  else if(view.acceptedQuery&&!view.pendingQuery&&typeof view.source.position==="function"){const position=await view.runGridHook(signal=>view.source.position(view.acceptedQuery,id,{signal}));if(Number.isInteger(position)&&position>=0&&position<view.rowCount()){await view.focusResult(position,false);const item=view.rowCache.get(position);if(item&&!item.status&&item.key===id){row=item.h;index=position}}}
141
141
  if(!row&&typeof view.source.row==="function")row=view.source.row(id);if(!row&&recordLoader(view)){const key=recordCacheKey(view,id);const payload=await recordFetch(view,id,{row:true});if(payload?.row){row=payload.row;(view._recordPayloads||=new Map()).set(key,{state:"ready",payload,promise:Promise.resolve(payload)})}}
142
142
  if(!row)recordFail("record "+id+" is not available.");const returnFocus=options.returnFocus||document.activeElement;if(typeof view.opts.onDetails==="function"){const record=recordGridHelpers().gridFreeze(JSON.parse(JSON.stringify(row)));await view.runGridHook(signal=>view.opts.onDetails({row:record,query:view.acceptedQuery,signal,returnFocus}));return null}
@@ -155,13 +155,18 @@ view._recordLinkOpen=record?recordLinkPath(recordLinkRead(view)||[]):null}
155
155
  RECORD_IMPL.start=view=>{if(view._recordStarted||!view.view.record?.deepLink)return;view._recordStarted=true;const read=()=>{const ids=recordLinkRead(view),key=ids?recordLinkPath(ids):null,owner=view._recordLinkOwner?.dialog;if(!ids){view._recordLinkOpen=null;view._recordLinkOwner=null;return}
156
156
  if(key===view._recordLinkOpen&&(!owner||owner.open||owner._replaced))return;view._recordLinkOwner=null;view._recordLinkOpen=key;RECORD_IMPL.open(view,ids[ids.length-1],{path:ids}).catch(error=>view.emit("error",{error}))};global.addEventListener("hashchange",read,{signal:view.lifetime.signal});view.lifetime.signal.addEventListener("abort",()=>{view._recordLinkOwner=null;view._recordLinkOpen=null},{once:true});Promise.resolve(view.ready).then(read,()=>{})};RECORD_IMPL.decorate=(view,dialog,{head,identity,options})=>{if(!view.view.record)return;try{recordSpec(view)}catch(error){return}
157
157
  dialog.id||=view.id+"-record";dialog.classList.add("cx-record-drawer");const state=dialog._cxPanel={stack:Array.isArray(options.stack)?options.stack:[],tab:options.tab||null,collapsed:new Map()},labels=view.labels;const live=h("div","cx-record-live cx-sr-only");live.setAttribute("aria-live","polite");dialog.appendChild(live);if(state.stack.length){const trail=h("nav","cx-record-trail"),crumbs=h("ol","cx-record-crumbs"),last=state.stack[state.stack.length-1];trail.setAttribute("aria-label",labels.recordTrail);const back=recordButton(labels.recordBack,()=>recordBack(view,dialog),"cx-record-back","back");back.setAttribute("aria-label",fill(labels.recordBackTo,{record:last.title||last.id}));state.stack.slice(-3).forEach((entry,at,list)=>{const item=h("li");item.appendChild(recordButton(entry.title||entry.id,()=>recordBack(view,dialog,list.length-at),"cx-record-crumb"));crumbs.appendChild(item)});trail.append(back,crumbs);identity.prepend(trail)}
158
- const summary=h("div","cx-record-summary");summary.hidden=true;head.after(summary);recordActionsMenu(view,dialog,identity);dialog.addEventListener("keydown",event=>{if(event.altKey&&event.key==="ArrowLeft"&&state.stack.length){event.preventDefault();recordBack(view,dialog)}});dialog.addEventListener("close",()=>{if(view.destroyed)return;const owner=view._recordLinkOwner;if(owner?.dialog!==dialog)return;if(dialog._replaced){view._recordLinkOwner=null;return}
159
- const ids=recordLinkRead(view);if(ids&&owner.link===recordLinkPrefix(view)+ recordLinkPath(ids))recordLinkWrite(view,null);view._recordLinkOwner=null;view._recordLinkOpen=null},{once:true})};function recordActionsMenu(view,dialog,identity){const spec=recordSpec(view),switches=spec.actions||{},labels=view.labels,items=[];const add=(label,task)=>items.push({label,task});if(switches.link!==false&&spec.deepLink)add(labels.recordCopyLink,()=>recordCopy(view,dialog,recordAddress(view,dialog._cxRecord)));if(switches.copy!==false){add(labels.recordCopyValues,()=>recordCopy(view,dialog,recordExport(view,dialog,"text")));add(labels.recordCopyJson,()=>recordCopy(view,dialog,recordExport(view,dialog,"json")))}
158
+ const summary=h("div","cx-record-summary");summary.hidden=true;head.after(summary);let projectedSubtitle;if(typeof view.opts.recordHeading==="function")dialog.addEventListener("cx-drawer-paint",()=>{if(projectedSubtitle){setText(projectedSubtitle,"");projectedSubtitle.hidden=true}
159
+ try{const heading=view.opts.recordHeading(Object.freeze(JSON.parse(JSON.stringify(dialog._cxRecord))));if(heading&&typeof heading.title==="string"&&heading.title.length<=512)setText(identity.querySelector("h4"),heading.title);if(heading&&typeof heading.subtitle==="string"&&heading.subtitle.length<=2000){let subtitle=identity.querySelector("p");if(!subtitle){subtitle=projectedSubtitle=h("p");identity.appendChild(subtitle)}
160
+ subtitle.classList.add("cx-record-subtitle");setText(subtitle,heading.subtitle);subtitle.hidden=!heading.subtitle}}catch(error){view.emit("error",{error})}});recordActionsMenu(view,dialog,identity);dialog.addEventListener("keydown",event=>{if(event.altKey&&event.key==="ArrowLeft"&&state.stack.length){event.preventDefault();recordBack(view,dialog)}});dialog.addEventListener("close",()=>{if(view.destroyed)return;const owner=view._recordLinkOwner;if(owner?.dialog!==dialog)return;if(dialog._replaced){view._recordLinkOwner=null;return}
161
+ const ids=recordLinkRead(view);if(ids&&owner.link===recordLinkPrefix(view)+ recordLinkPath(ids))recordLinkWrite(view,null);view._recordLinkOwner=null;view._recordLinkOpen=null},{once:true})};function recordActionsMenu(view,dialog,identity){dialog.querySelector(".cx-record-footer")?.remove();const spec=recordSpec(view),switches=spec.actions||{},labels=view.labels,items=[];const failed=error=>{recordAnnounce(dialog,error?.message??String(error));view.emit("error",{error})};const add=(label,task,prominent=false,visible=()=>true)=>{let running=false,button;const run=async()=>{if(running||!visible())return;running=true;if(button)button.disabled=true;try{return await task()}
162
+ finally{running=false;if(button)button.disabled=false}};const item={label,task:run,visible,primary:typeof prominent==="function"?prominent:()=>prominent===true};items.push(item);if(prominent){let footer=dialog.querySelector(".cx-record-footer");if(!footer){footer=h("footer","cx-record-footer");dialog.appendChild(footer)}
163
+ button=recordButton(label,()=>{Promise.resolve().then(run).catch(failed)},"cx-record-btn cx-record-primary");item.footer=button;footer.appendChild(button)}};if(switches.link!==false&&spec.deepLink)add(labels.recordCopyLink,()=>recordCopy(view,dialog,recordAddress(view,dialog._cxRecord)));if(switches.copy!==false){add(labels.recordCopyValues,()=>recordCopy(view,dialog,recordExport(view,dialog,"text")));add(labels.recordCopyJson,()=>recordCopy(view,dialog,recordExport(view,dialog,"json")))}
160
164
  if(switches.export!==false){add(labels.recordExportCsv,()=>recordDownload(view,dialog,"csv"));add(labels.recordExportJson,()=>recordDownload(view,dialog,"json"))}
161
- if(switches.print!==false)add(labels.recordPrint,()=>recordPrint(view,dialog));for(const action of[...(Array.isArray(view.opts.recordActions)?view.opts.recordActions:[]),...view.plugins.flatMap(item=>item.recordActions||[])]){if(!action||typeof action.label!=="string"||typeof action.run!=="function")continue;add(action.label,()=>{const record=dialog._cxRecord,entry=recordEntry(view,record.id);return action.run(Object.freeze({record:JSON.parse(JSON.stringify(record)),view:view.view.id,api:view.host.canopyx,payload:entry?.payload||null,signal:view.lifetime.signal}))})}
162
- if(!items.length)return;const menu=h("div","cx-record-menu"),toggle=recordButton("",()=>show(list.hidden),"cx-record-menu-btn","more"),list=h("div","cx-record-menu-list");list.id=dialog.id+"-actions";list.setAttribute("role","menu");list.setAttribute("aria-label",labels.recordActions);list.hidden=true;toggle.setAttribute("aria-label",labels.recordActions);toggle.title=labels.recordActions;toggle.setAttribute("aria-haspopup","menu");toggle.setAttribute("aria-expanded","false");toggle.setAttribute("aria-controls",list.id);const show=open=>{list.hidden=!open;toggle.setAttribute("aria-expanded",String(open));if(open)buttons[0].focus()};const buttons=items.map(item=>{const button=recordButton(item.label,()=>{show(false);toggle.focus();Promise.resolve().then(item.task).catch(error=>{recordAnnounce(dialog,error.message);view.emit("error",{error})})},"cx-record-menu-item");button.setAttribute("role","menuitem");button.tabIndex=-1;return button});list.append(...buttons);menu.append(toggle,list);identity.after(menu);menu.addEventListener("keydown",event=>{if(list.hidden)return;if(event.key==="Escape"){event.preventDefault();event.stopPropagation();show(false);toggle.focus();return}
165
+ if(switches.print!==false)add(labels.recordPrint,()=>recordPrint(view,dialog));for(const action of[...(Array.isArray(view.opts.recordActions)?view.opts.recordActions:[]),...view.plugins.flatMap(item=>item.recordActions||[])]){if(!action||typeof action.label!=="string"||typeof action.run!=="function")continue;const context=()=>{const record=dialog._cxRecord,entry=record&&recordEntry(view,record.id);return Object.freeze({record:record?JSON.parse(JSON.stringify(record)):{id:""},view:view.view.id,api:view.host.canopyx,payload:entry?.state==="ready"?JSON.parse(JSON.stringify(entry.payload)):null,signal:view.lifetime.signal})};const condition=(value,fallback)=>{if(typeof value!=="function")return value===undefined?fallback:value===true;try{return value(context())===true}catch(error){failed(error);return false}};add(action.label,()=>action.run(context()),()=>condition(action.prominent,false),()=>condition(action.visible,true))}
166
+ if(!items.length)return;const menu=h("div","cx-record-menu"),toggle=recordButton("",()=>show(list.hidden),"cx-record-menu-btn","more"),list=h("div","cx-record-menu-list");list.id=dialog.id+"-actions";list.setAttribute("role","menu");list.setAttribute("aria-label",labels.recordActions);list.hidden=true;toggle.setAttribute("aria-label",labels.recordActions);toggle.title=labels.recordActions;toggle.setAttribute("aria-haspopup","menu");toggle.setAttribute("aria-expanded","false");toggle.setAttribute("aria-controls",list.id);const show=open=>{list.hidden=!open;toggle.setAttribute("aria-expanded",String(open));if(open)buttons.find(button=>!button.hidden)?.focus()};const buttons=items.map(item=>{const button=recordButton(item.label,()=>{show(false);toggle.focus();Promise.resolve().then(item.task).catch(failed)},"cx-record-menu-item");button.setAttribute("role","menuitem");button.tabIndex=-1;item.button=button;return button});list.append(...buttons);menu.append(toggle,list);identity.after(menu);menu.addEventListener("keydown",event=>{if(list.hidden)return;if(event.key==="Escape"){event.preventDefault();event.stopPropagation();show(false);toggle.focus();return}
163
167
  if(event.key==="Tab"){show(false);return}
164
- const at=buttons.indexOf(document.activeElement);if(at<0||!["ArrowDown","ArrowUp","Home","End"].includes(event.key))return;event.preventDefault();event.stopPropagation();buttons[{ArrowDown:(at+1)%buttons.length,ArrowUp:(at-1+buttons.length)%buttons.length,Home:0,End:buttons.length-1}[event.key]].focus()});menu.addEventListener("focusout",event=>{if(!menu.contains(event.relatedTarget)&&event.relatedTarget)show(false)});dialog.addEventListener("pointerdown",event=>{if(!menu.contains(event.target))show(false)})}
168
+ const visible=buttons.filter(button=>!button.hidden),at=visible.indexOf(document.activeElement);if(at<0||!["ArrowDown","ArrowUp","Home","End"].includes(event.key))return;event.preventDefault();event.stopPropagation();visible[{ArrowDown:(at+1)%visible.length,ArrowUp:(at-1+visible.length)%visible.length,Home:0,End:visible.length-1}[event.key]].focus()});menu.addEventListener("focusout",event=>{if(!menu.contains(event.relatedTarget)&&event.relatedTarget)show(false)});dialog.addEventListener("pointerdown",event=>{if(!menu.contains(event.target))show(false)});const paint=()=>{for(const item of items){const visible=item.visible();item.button.hidden=!visible;if(item.footer)item.footer.hidden=!visible||!item.primary()}
169
+ menu.hidden=!items.some(item=>!item.button.hidden);const footer=dialog.querySelector(".cx-record-footer");if(footer)footer.hidden=!items.some(item=>item.footer&&!item.footer.hidden);if(menu.hidden)show(false)};dialog.addEventListener("cx-drawer-paint",paint);paint()}
165
170
  async function recordCopy(view,dialog,text){if(!global.navigator.clipboard?.writeText)recordFail("the clipboard is not available.");await global.navigator.clipboard.writeText(text);recordAnnounce(dialog,view.labels.recordCopied)}
166
171
  function recordFlat(cell,field,fmt){const kind=recordKind(cell),text=(value,spec=field)=>recordFlat(value,spec,fmt);if(kind==="items")return cell.items.map(item=>text(item)).join(", ");if(kind==="fields")return cell.fields.map(entry=>entry.name+": "+text(entry.value,{kind:entry.kind||"text"})).join("; ");if(kind==="records")return(cell.records.rows||cell.records.roots||[]).map(row=>cell.records.columns.map(column=>text(row.cells?.[column.id]??null,column)).filter(Boolean).join(" · ")).join("\n");if(kind==="events")return cell.events.map(event=>[event.time?formatValue(event.time,"datetime",fmt):"",event.kind,event.actor,event.summary].filter(Boolean).join(" · ")).join("\n");if(kind==="changes")return cell.changes.map(change=>change.name+": "+text(change.before??null)+ " → "+text(change.after??null)).join("\n");return cellText(cell,field.column||field,fmt)}
167
172
  function recordData(view,dialog){const record=dialog._cxRecord,entry=recordEntry(view,record.id),payload=entry?.state==="ready"?entry.payload:null;const fields=recordFields(view),layout=recordLayout(view,fields),items=[],seen=new Set();const walk=(sections,path)=>{for(const section of sections){const name=path?path+" / "+section.label:section.label;for(const field of section.fields)if(!seen.has(field.id)){seen.add(field.id);items.push({section:name,field,cell:recordCell(view,record,payload,field)})}
@@ -527,7 +527,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
527
527
  active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
528
528
  close()}else{return}
529
529
  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 position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
530
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"presenters":["4337e3756b443220","canopyx-presenters.c8c9d0651df602b1.js"],"filter-editor":["e0db9c3f94866fa2","canopyx-filter-editor.bd27d6fec3d8b005.js","canopyx-filter-editor.0aa102aa92982a0f.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["3dcab112113081dd","canopyx-pager.15bb475e4365fe79.js","canopyx-pager.e39f321db5bdfde4.css"],"enhance":["a101e32b0f8a1644","canopyx-enhance.dd25035ab5f23d01.js"],"data":["d74a01c46f1c40cc","canopyx-data.afe3b097f19b5797.js"],"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["e7dea789e4893860","canopyx-flow.bce98a6e89aa358e.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["3ca22040c60d5689","canopyx-flow-checks.7856290d3c486f84.js","canopyx-flow-checks.d3b182bf1d633e48.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["a9b5bce11baa2499","canopyx-flow-dialog.271f746b459ec0da.js","canopyx-flow-dialog.7f5a8ca5841006af.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"],"matrix":["da5c61ff2cb9ebda","canopyx-matrix.ed85d343a2f623b2.js","canopyx-matrix.195d1a1dda7a6f14.css"],"changes":["2810fb06a78b85e3","canopyx-changes.b4d09ab480688573.js","canopyx-changes.4bc51f4c6ae04082.css"],"editing":["579a74b205923fd5","canopyx-editing.ecebf88153edf03a.js","canopyx-editing.e0a3e646f4093e3b.css"],"column-groups":["cd6d93e033719439","canopyx-column-groups.922e21b9bdf57efa.js","canopyx-column-groups.6a6c9704c4ee7884.css"],"cell-range":["91e39c68baaf1d09","canopyx-cell-range.a12cda7cbddf4aea.js","canopyx-cell-range.ce87ff1c2023feae.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["d3795e4b933d83a8","canopyx-formatting.ec13b95ea1f2b023.js","canopyx-formatting.922dc9fc7e6d35a7.css"],"format-editor":["b8c229ddfc1f218b","canopyx-format-editor.4a220f27a369d34e.js","canopyx-format-editor.dbdf4a154e7e5f48.css"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"detail-rows":["e4150bb67f40d597","canopyx-detail-rows.e7f93158e19cbb28.js","canopyx-detail-rows.cabc50f51ed091ad.css"],"grouping":["eedafc8438ac1b2b","canopyx-grouping.e7767e781127573d.js","canopyx-grouping.98fa290cd1652f71.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"facets":["2ffa91f40c9b9b21","canopyx-facets.2ad845e5213e7f5b.js","canopyx-facets.8d4c02348420a425.css"],"live":["42ad4b814f47bd00","canopyx-live.3cc50651bc9d2bc9.js","canopyx-live.39fe32cd642f60d2.css"],"record-panel":["94adeb844689e329","canopyx-record-panel.d0d71d38743e3476.js","canopyx-record-panel.66edd824ab6111c1.css"],"calendar":["463aadb3a2169631","canopyx-calendar.3f539daa1b0a1b6f.js","canopyx-calendar.2d299b0318447276.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["29a711a1cfd4be9a","canopyx-calendar-edit.ef7728c17ca4851b.js"],"calendar-ics":["ac8b2950fccbfb0f","canopyx-calendar-ics.4a18c1c4a1520418.js"],"timeline":["22c9e15c108aeaa1","canopyx-timeline.2b5fe21a0f24aa08.js","canopyx-timeline.e3c962ae517931d2.css"],"grid-options":["e74170bbb841519c","canopyx-grid-options.c5fa91fc19205d5a.js","canopyx-grid-options.9c393c5122332461.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
530
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"presenters":["4337e3756b443220","canopyx-presenters.c8c9d0651df602b1.js"],"filter-editor":["e0db9c3f94866fa2","canopyx-filter-editor.bd27d6fec3d8b005.js","canopyx-filter-editor.0aa102aa92982a0f.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["3dcab112113081dd","canopyx-pager.15bb475e4365fe79.js","canopyx-pager.e39f321db5bdfde4.css"],"enhance":["a101e32b0f8a1644","canopyx-enhance.dd25035ab5f23d01.js"],"data":["d74a01c46f1c40cc","canopyx-data.afe3b097f19b5797.js"],"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["93f8d2eb57cc1770","canopyx-flow.c3f65a21ced2d654.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["318849d97560c594","canopyx-flow-checks.21dcc732a9145c71.js","canopyx-flow-checks.5a98f4038542c1d3.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["217410758cdb73da","canopyx-flow-dialog.e45cf5f0b12f802a.js","canopyx-flow-dialog.35310d9dc1d73395.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-facts":["385b5e61ed487e16","canopyx-flow-facts.8dad3bc07a71fdb0.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"],"matrix":["da5c61ff2cb9ebda","canopyx-matrix.ed85d343a2f623b2.js","canopyx-matrix.195d1a1dda7a6f14.css"],"changes":["2810fb06a78b85e3","canopyx-changes.b4d09ab480688573.js","canopyx-changes.4bc51f4c6ae04082.css"],"editing":["579a74b205923fd5","canopyx-editing.ecebf88153edf03a.js","canopyx-editing.e0a3e646f4093e3b.css"],"column-groups":["cd6d93e033719439","canopyx-column-groups.922e21b9bdf57efa.js","canopyx-column-groups.6a6c9704c4ee7884.css"],"cell-range":["91e39c68baaf1d09","canopyx-cell-range.a12cda7cbddf4aea.js","canopyx-cell-range.ce87ff1c2023feae.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["d3795e4b933d83a8","canopyx-formatting.ec13b95ea1f2b023.js","canopyx-formatting.922dc9fc7e6d35a7.css"],"format-editor":["b8c229ddfc1f218b","canopyx-format-editor.4a220f27a369d34e.js","canopyx-format-editor.dbdf4a154e7e5f48.css"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"detail-rows":["e4150bb67f40d597","canopyx-detail-rows.e7f93158e19cbb28.js","canopyx-detail-rows.cabc50f51ed091ad.css"],"grouping":["eedafc8438ac1b2b","canopyx-grouping.e7767e781127573d.js","canopyx-grouping.98fa290cd1652f71.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"facets":["2ffa91f40c9b9b21","canopyx-facets.2ad845e5213e7f5b.js","canopyx-facets.8d4c02348420a425.css"],"live":["3b3c9833ff68a72b","canopyx-live.e4b062f6eeb0ea36.js","canopyx-live.39fe32cd642f60d2.css"],"record-panel":["82aa828bc880087b","canopyx-record-panel.e0736e2285995701.js","canopyx-record-panel.4b9f1a99c5b76321.css"],"calendar":["463aadb3a2169631","canopyx-calendar.3f539daa1b0a1b6f.js","canopyx-calendar.2d299b0318447276.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["29a711a1cfd4be9a","canopyx-calendar-edit.ef7728c17ca4851b.js"],"calendar-ics":["ac8b2950fccbfb0f","canopyx-calendar-ics.4a18c1c4a1520418.js"],"timeline":["22c9e15c108aeaa1","canopyx-timeline.2b5fe21a0f24aa08.js","canopyx-timeline.e3c962ae517931d2.css"],"grid-options":["e74170bbb841519c","canopyx-grid-options.c5fa91fc19205d5a.js","canopyx-grid-options.9c393c5122332461.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
531
531
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
532
532
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
533
533
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -793,7 +793,7 @@ if(offset){const snapshot={revision:page.revision,total:page.total,matched:page.
793
793
  gridOperationActive(this,lifetime.signal);const hadFocus=this.canvas.contains(document.activeElement),previousId=this.focused&&this.focused.key;const retireSelection=this.view.rowIdentity==="ordinal"&&this.snapshot&&this.snapshot.revision!==page.revision;this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.focused=null;this.acceptedQuery=gridQuery(this.view,{...query,revision:page.revision});this.snapshot={revision:page.revision,total:page.total,matched:page.matched};if(retireSelection)this.clearSnapshotSelection();this.pageLength=length;if(paging)this.pageAll=!!paging.allRows;this.pageOffset=this.cursor?page.offset:this.paged?query.offset:0;if(this.cursor)this.cursorWindow={end:page.offset+page.items.length,next:page.nextCursor,previous:page.previousCursor};if(this.autoRows){if(!same)this.rowHeights.clear();this.rowOffsets=null}
794
794
  this.storePage(page);this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=null;this.lastFailedPaging=null;this.version++;const hasRows=this.cursor?page.items.length:page.matched;this.total=(this.cursor?page.items.length:this.paged?Math.min(length,page.matched-this.pageOffset):page.matched)*this.rowH;this.grid.setAttribute("aria-rowcount",page.matched===null?"-1":String(page.matched+1 +(this.headDepth||0)));this.grid.tabIndex=hasRows?-1:0;this.syncScrollRange(this.paged?0:query.offset*this.rowH);this.buildHeader();this.syncColumnControls();this.setNotice(hasRows?"":this.labels.searchNoResults,false);this.grid.setAttribute("aria-busy","false");if(hadFocus||this.focusOrigin){this.focused=[...this.rowCache.values()].find(row=>row.key===previousId)||this.rowCache.get(this.cursor?page.offset:query.offset)||null}
795
795
  this.render();if(hadFocus){const element=this.focused&&this.rendered.get(this.focused);(element||this.grid).focus({preventScroll:true})}
796
- this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=initial;this.lastFailedPaging={...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(fill(this.labels.queryFailed,{error:error.message}),true);this.syncPager();this.emit("error",{error})}
796
+ this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){const cancelled=lifetime.signal.aborted&&error?.name==="AbortError";this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=cancelled?null:initial;this.lastFailedPaging=cancelled?null:{...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(cancelled?"":fill(this.labels.queryFailed,{error:error.message}),!cancelled);this.syncPager();if(!cancelled)this.emit("error",{error})}
797
797
  throw error}}
798
798
  querySortHeader(id,event){const previous=gridQuery(this.view,this.queryForChange(true)),sorts=previous.sort.slice();const found=sorts.findIndex(sort=>sort.column===id),old=found>=0?sorts[found].direction:null;const authored=this.columns.find(column=>column.id===id).orderSequence;const sequence=authored?.length?authored:["asc","desc","none"];const direction=sequence[(sequence.indexOf(old||"none")+ 1)%sequence.length];const next=direction==="none"?null:direction;const changed=event&&event.shiftKey?sorts.filter(sort=>sort.column!==id):[];if(next)changed.splice(event&&event.shiftKey&&found>=0?Math.min(found,changed.length):changed.length,0,{column:id,direction:next});this.setQuery(gridQueryStart(previous,{sort:changed})).catch(()=>{})}
799
799
  sort(sorts){return this.setQuery(gridQueryStart(this.queryForChange(true),{sort:sorts}))}
@@ -1430,10 +1430,10 @@ this.slotted=[...this.host.querySelectorAll(":scope > [data-cx-slot]")];this.slo
1430
1430
  throw new Error("CanopyX: an action has a label and either a run or a render function.");const entry=h("details","cx-grid-action"),summary=h("summary","cx-button"),body=h("div","cx-grid-action-body"),menu=this.overflow.details;setText(summary,action.label);summary.setAttribute("role","button");entry.append(summary,body);entry.addEventListener("toggle",()=>{if(!entry.open)return;if(!body.drawn){body.drawn=true;try{render(body,{close:()=>{entry.open=false;menu.open=false;menu.firstChild.focus()},signal:this.lifetime.signal})}
1431
1431
  catch(error){body.drawn=false;body.replaceChildren();this.emit("error",{error})}}
1432
1432
  (body.querySelector(":is(input:not([type=hidden]),select,textarea,button):not(:disabled),[href],[tabindex]:not([tabindex=\"-1\"])")||summary).focus()});entry.addEventListener("keydown",event=>{if(event.key==="Escape"&&entry.open){entry.open=false;summary.focus();event.preventDefault();event.stopPropagation()}});return entry}});GRID_REPORTING.api=(api,grid)=>{TOOLBAR_API(api,grid);api.toolbarSlot=name=>grid.toolbarSlot(name)};class FlowHost{}
1433
- const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent"])
1434
- FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
1433
+ const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent","facts"])
1434
+ FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("facts",step.facts!==undefined);add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
1435
1435
  hooks=object(hooks)?hooks:{};return{required:[...names],optional:[typeof hooks.preview==="function"&&"preview",object(hooks.presetStore)&&"drafts"].filter(name=>name&&!names.has(name))}}
1436
- const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
1436
+ const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","invalidateChecks","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
1437
1437
  .catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;disposeTheme();try{impl?.destroy()}
1438
1438
  finally{impl=null;mountError?.remove();if(activeFlows.get(host)===api){activeFlows.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");host.removeAttribute("data-cx-ready");host.removeAttribute("data-cx-error");host.classList.remove("cx-flow-host")}}};ready.catch(error=>{if(destroyed)return;const notice=mountError=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);host.setAttribute("data-cx-error",notice.textContent);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeFlows.set(host,api);host.classList.add("cx-host","cx-flow-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
1439
1439
  const FLOW_API={createFlow};function createTreeGrid(host,options){if(!host||!options||!options.view){throw new Error("CanopyX: createTreeGrid needs a host element and a view document.")}
@@ -525,7 +525,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
525
525
  active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
526
526
  close()}else{return}
527
527
  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 position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
528
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"presenters":["4337e3756b443220","canopyx-presenters.c8c9d0651df602b1.js"],"filter-editor":["e0db9c3f94866fa2","canopyx-filter-editor.bd27d6fec3d8b005.js","canopyx-filter-editor.0aa102aa92982a0f.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["3dcab112113081dd","canopyx-pager.15bb475e4365fe79.js","canopyx-pager.e39f321db5bdfde4.css"],"enhance":["a101e32b0f8a1644","canopyx-enhance.dd25035ab5f23d01.js"],"data":["d74a01c46f1c40cc","canopyx-data.afe3b097f19b5797.js"],"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["e7dea789e4893860","canopyx-flow.bce98a6e89aa358e.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["3ca22040c60d5689","canopyx-flow-checks.7856290d3c486f84.js","canopyx-flow-checks.d3b182bf1d633e48.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["a9b5bce11baa2499","canopyx-flow-dialog.271f746b459ec0da.js","canopyx-flow-dialog.7f5a8ca5841006af.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"],"matrix":["da5c61ff2cb9ebda","canopyx-matrix.ed85d343a2f623b2.js","canopyx-matrix.195d1a1dda7a6f14.css"],"changes":["2810fb06a78b85e3","canopyx-changes.b4d09ab480688573.js","canopyx-changes.4bc51f4c6ae04082.css"],"editing":["579a74b205923fd5","canopyx-editing.ecebf88153edf03a.js","canopyx-editing.e0a3e646f4093e3b.css"],"column-groups":["cd6d93e033719439","canopyx-column-groups.922e21b9bdf57efa.js","canopyx-column-groups.6a6c9704c4ee7884.css"],"cell-range":["91e39c68baaf1d09","canopyx-cell-range.a12cda7cbddf4aea.js","canopyx-cell-range.ce87ff1c2023feae.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["d3795e4b933d83a8","canopyx-formatting.ec13b95ea1f2b023.js","canopyx-formatting.922dc9fc7e6d35a7.css"],"format-editor":["b8c229ddfc1f218b","canopyx-format-editor.4a220f27a369d34e.js","canopyx-format-editor.dbdf4a154e7e5f48.css"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"detail-rows":["e4150bb67f40d597","canopyx-detail-rows.e7f93158e19cbb28.js","canopyx-detail-rows.cabc50f51ed091ad.css"],"grouping":["eedafc8438ac1b2b","canopyx-grouping.e7767e781127573d.js","canopyx-grouping.98fa290cd1652f71.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"facets":["2ffa91f40c9b9b21","canopyx-facets.2ad845e5213e7f5b.js","canopyx-facets.8d4c02348420a425.css"],"live":["42ad4b814f47bd00","canopyx-live.3cc50651bc9d2bc9.js","canopyx-live.39fe32cd642f60d2.css"],"record-panel":["94adeb844689e329","canopyx-record-panel.d0d71d38743e3476.js","canopyx-record-panel.66edd824ab6111c1.css"],"calendar":["463aadb3a2169631","canopyx-calendar.3f539daa1b0a1b6f.js","canopyx-calendar.2d299b0318447276.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["29a711a1cfd4be9a","canopyx-calendar-edit.ef7728c17ca4851b.js"],"calendar-ics":["ac8b2950fccbfb0f","canopyx-calendar-ics.4a18c1c4a1520418.js"],"timeline":["22c9e15c108aeaa1","canopyx-timeline.2b5fe21a0f24aa08.js","canopyx-timeline.e3c962ae517931d2.css"],"grid-options":["e74170bbb841519c","canopyx-grid-options.c5fa91fc19205d5a.js","canopyx-grid-options.9c393c5122332461.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
528
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"presenters":["4337e3756b443220","canopyx-presenters.c8c9d0651df602b1.js"],"filter-editor":["e0db9c3f94866fa2","canopyx-filter-editor.bd27d6fec3d8b005.js","canopyx-filter-editor.0aa102aa92982a0f.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["3dcab112113081dd","canopyx-pager.15bb475e4365fe79.js","canopyx-pager.e39f321db5bdfde4.css"],"enhance":["a101e32b0f8a1644","canopyx-enhance.dd25035ab5f23d01.js"],"data":["d74a01c46f1c40cc","canopyx-data.afe3b097f19b5797.js"],"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["93f8d2eb57cc1770","canopyx-flow.c3f65a21ced2d654.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["318849d97560c594","canopyx-flow-checks.21dcc732a9145c71.js","canopyx-flow-checks.5a98f4038542c1d3.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["217410758cdb73da","canopyx-flow-dialog.e45cf5f0b12f802a.js","canopyx-flow-dialog.35310d9dc1d73395.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-facts":["385b5e61ed487e16","canopyx-flow-facts.8dad3bc07a71fdb0.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"],"matrix":["da5c61ff2cb9ebda","canopyx-matrix.ed85d343a2f623b2.js","canopyx-matrix.195d1a1dda7a6f14.css"],"changes":["2810fb06a78b85e3","canopyx-changes.b4d09ab480688573.js","canopyx-changes.4bc51f4c6ae04082.css"],"editing":["579a74b205923fd5","canopyx-editing.ecebf88153edf03a.js","canopyx-editing.e0a3e646f4093e3b.css"],"column-groups":["cd6d93e033719439","canopyx-column-groups.922e21b9bdf57efa.js","canopyx-column-groups.6a6c9704c4ee7884.css"],"cell-range":["91e39c68baaf1d09","canopyx-cell-range.a12cda7cbddf4aea.js","canopyx-cell-range.ce87ff1c2023feae.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["d3795e4b933d83a8","canopyx-formatting.ec13b95ea1f2b023.js","canopyx-formatting.922dc9fc7e6d35a7.css"],"format-editor":["b8c229ddfc1f218b","canopyx-format-editor.4a220f27a369d34e.js","canopyx-format-editor.dbdf4a154e7e5f48.css"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"detail-rows":["e4150bb67f40d597","canopyx-detail-rows.e7f93158e19cbb28.js","canopyx-detail-rows.cabc50f51ed091ad.css"],"grouping":["eedafc8438ac1b2b","canopyx-grouping.e7767e781127573d.js","canopyx-grouping.98fa290cd1652f71.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"facets":["2ffa91f40c9b9b21","canopyx-facets.2ad845e5213e7f5b.js","canopyx-facets.8d4c02348420a425.css"],"live":["3b3c9833ff68a72b","canopyx-live.e4b062f6eeb0ea36.js","canopyx-live.39fe32cd642f60d2.css"],"record-panel":["82aa828bc880087b","canopyx-record-panel.e0736e2285995701.js","canopyx-record-panel.4b9f1a99c5b76321.css"],"calendar":["463aadb3a2169631","canopyx-calendar.3f539daa1b0a1b6f.js","canopyx-calendar.2d299b0318447276.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["29a711a1cfd4be9a","canopyx-calendar-edit.ef7728c17ca4851b.js"],"calendar-ics":["ac8b2950fccbfb0f","canopyx-calendar-ics.4a18c1c4a1520418.js"],"timeline":["22c9e15c108aeaa1","canopyx-timeline.2b5fe21a0f24aa08.js","canopyx-timeline.e3c962ae517931d2.css"],"grid-options":["e74170bbb841519c","canopyx-grid-options.c5fa91fc19205d5a.js","canopyx-grid-options.9c393c5122332461.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
529
529
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
530
530
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
531
531
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -791,7 +791,7 @@ if(offset){const snapshot={revision:page.revision,total:page.total,matched:page.
791
791
  gridOperationActive(this,lifetime.signal);const hadFocus=this.canvas.contains(document.activeElement),previousId=this.focused&&this.focused.key;const retireSelection=this.view.rowIdentity==="ordinal"&&this.snapshot&&this.snapshot.revision!==page.revision;this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.focused=null;this.acceptedQuery=gridQuery(this.view,{...query,revision:page.revision});this.snapshot={revision:page.revision,total:page.total,matched:page.matched};if(retireSelection)this.clearSnapshotSelection();this.pageLength=length;if(paging)this.pageAll=!!paging.allRows;this.pageOffset=this.cursor?page.offset:this.paged?query.offset:0;if(this.cursor)this.cursorWindow={end:page.offset+page.items.length,next:page.nextCursor,previous:page.previousCursor};if(this.autoRows){if(!same)this.rowHeights.clear();this.rowOffsets=null}
792
792
  this.storePage(page);this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=null;this.lastFailedPaging=null;this.version++;const hasRows=this.cursor?page.items.length:page.matched;this.total=(this.cursor?page.items.length:this.paged?Math.min(length,page.matched-this.pageOffset):page.matched)*this.rowH;this.grid.setAttribute("aria-rowcount",page.matched===null?"-1":String(page.matched+1 +(this.headDepth||0)));this.grid.tabIndex=hasRows?-1:0;this.syncScrollRange(this.paged?0:query.offset*this.rowH);this.buildHeader();this.syncColumnControls();this.setNotice(hasRows?"":this.labels.searchNoResults,false);this.grid.setAttribute("aria-busy","false");if(hadFocus||this.focusOrigin){this.focused=[...this.rowCache.values()].find(row=>row.key===previousId)||this.rowCache.get(this.cursor?page.offset:query.offset)||null}
793
793
  this.render();if(hadFocus){const element=this.focused&&this.rendered.get(this.focused);(element||this.grid).focus({preventScroll:true})}
794
- this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=initial;this.lastFailedPaging={...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(fill(this.labels.queryFailed,{error:error.message}),true);this.syncPager();this.emit("error",{error})}
794
+ this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){const cancelled=lifetime.signal.aborted&&error?.name==="AbortError";this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=cancelled?null:initial;this.lastFailedPaging=cancelled?null:{...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(cancelled?"":fill(this.labels.queryFailed,{error:error.message}),!cancelled);this.syncPager();if(!cancelled)this.emit("error",{error})}
795
795
  throw error}}
796
796
  querySortHeader(id,event){const previous=gridQuery(this.view,this.queryForChange(true)),sorts=previous.sort.slice();const found=sorts.findIndex(sort=>sort.column===id),old=found>=0?sorts[found].direction:null;const authored=this.columns.find(column=>column.id===id).orderSequence;const sequence=authored?.length?authored:["asc","desc","none"];const direction=sequence[(sequence.indexOf(old||"none")+ 1)%sequence.length];const next=direction==="none"?null:direction;const changed=event&&event.shiftKey?sorts.filter(sort=>sort.column!==id):[];if(next)changed.splice(event&&event.shiftKey&&found>=0?Math.min(found,changed.length):changed.length,0,{column:id,direction:next});this.setQuery(gridQueryStart(previous,{sort:changed})).catch(()=>{})}
797
797
  sort(sorts){return this.setQuery(gridQueryStart(this.queryForChange(true),{sort:sorts}))}
@@ -1428,10 +1428,10 @@ this.slotted=[...this.host.querySelectorAll(":scope > [data-cx-slot]")];this.slo
1428
1428
  throw new Error("CanopyX: an action has a label and either a run or a render function.");const entry=h("details","cx-grid-action"),summary=h("summary","cx-button"),body=h("div","cx-grid-action-body"),menu=this.overflow.details;setText(summary,action.label);summary.setAttribute("role","button");entry.append(summary,body);entry.addEventListener("toggle",()=>{if(!entry.open)return;if(!body.drawn){body.drawn=true;try{render(body,{close:()=>{entry.open=false;menu.open=false;menu.firstChild.focus()},signal:this.lifetime.signal})}
1429
1429
  catch(error){body.drawn=false;body.replaceChildren();this.emit("error",{error})}}
1430
1430
  (body.querySelector(":is(input:not([type=hidden]),select,textarea,button):not(:disabled),[href],[tabindex]:not([tabindex=\"-1\"])")||summary).focus()});entry.addEventListener("keydown",event=>{if(event.key==="Escape"&&entry.open){entry.open=false;summary.focus();event.preventDefault();event.stopPropagation()}});return entry}});GRID_REPORTING.api=(api,grid)=>{TOOLBAR_API(api,grid);api.toolbarSlot=name=>grid.toolbarSlot(name)};class FlowHost{}
1431
- const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent"])
1432
- FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
1431
+ const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent","facts"])
1432
+ FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("facts",step.facts!==undefined);add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
1433
1433
  hooks=object(hooks)?hooks:{};return{required:[...names],optional:[typeof hooks.preview==="function"&&"preview",object(hooks.presetStore)&&"drafts"].filter(name=>name&&!names.has(name))}}
1434
- const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
1434
+ const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","invalidateChecks","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
1435
1435
  .catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;disposeTheme();try{impl?.destroy()}
1436
1436
  finally{impl=null;mountError?.remove();if(activeFlows.get(host)===api){activeFlows.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");host.removeAttribute("data-cx-ready");host.removeAttribute("data-cx-error");host.classList.remove("cx-flow-host")}}};ready.catch(error=>{if(destroyed)return;const notice=mountError=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);host.setAttribute("data-cx-error",notice.textContent);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeFlows.set(host,api);host.classList.add("cx-host","cx-flow-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
1437
1437
  const FLOW_API={createFlow};function createTreeGrid(host,options){if(!host||!options||!options.view){throw new Error("CanopyX: createTreeGrid needs a host element and a view document.")}
@@ -525,7 +525,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
525
525
  active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
526
526
  close()}else{return}
527
527
  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 position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
528
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"record-panel":["94adeb844689e329","canopyx-record-panel.d0d71d38743e3476.js","canopyx-record-panel.66edd824ab6111c1.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
528
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"record-panel":["82aa828bc880087b","canopyx-record-panel.e0736e2285995701.js","canopyx-record-panel.4b9f1a99c5b76321.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
529
529
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
530
530
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
531
531
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -150,6 +150,8 @@ export interface FlowStep {
150
150
  title?: string;
151
151
  description?: string;
152
152
  type?: "form" | "info" | "pick" | "review";
153
+ /** Information steps: at most 32 read-only facts, with full wrapped plain-text values up to 32768 characters. Never submitted as answers. */
154
+ facts?: readonly { readonly label: string; readonly value: string }[];
153
155
  fields?: readonly FlowField[];
154
156
  sections?: readonly FlowSection[];
155
157
  when?: FlowCondition;
@@ -261,6 +263,8 @@ export interface FlowHookContext { signal: AbortSignal }
261
263
 
262
264
  /** The submit event's detail: the proposal, how to answer it, and each secret once. */
263
265
  export interface FlowSubmitDetail extends Readonly<FlowSubmission> {
266
+ /** Retired when answers change, the flow resets/destroys, or the submission settles. Cancellation cannot undo a server write already committed. */
267
+ readonly signal: AbortSignal;
264
268
  respondWith(answer: FlowAnswer | Promise<FlowAnswer>): void;
265
269
  /** A secret's value, once per field, until the answer settles; null afterwards. */
266
270
  secret(fieldId: string): string | null;
@@ -371,6 +375,8 @@ export interface FlowApi {
371
375
  /** Runs a check now; resolves with its result as the flow keeps it (field messages show in place), or null when it was cancelled.
372
376
  * Rejects for a check the flow does not have. */
373
377
  runCheck(checkId: string): Promise<{ status: FlowCheckStatus; message: string | null; details: { label: string; value: string }[]; at: string } | null>;
378
+ /** Marks selected checks (all when omitted) stale after an external dependency changes. Cancels runs and ignores late answers without changing field values or dirty state. */
379
+ invalidateChecks(checkIds?: readonly string[]): void;
374
380
  /** Loads a host-option field's options again. Rejects for any other field. */
375
381
  refreshOptions(fieldId: string): Promise<void>;
376
382
  /** Sets a task's state as the host sees it; null returns it to what the answers say. Throws for a flow that is no task list. */
@@ -5,7 +5,7 @@ import type { HostOptions, ExportFormat, ExportFormatOptions, ExportFormatResult
5
5
  import type { CanopyPlugin } from "./plugins.js";
6
6
  import type { GridEditorDefinition, GridValidation, GridEditingSettings, GridEditingOptions, GridEditingApi, GridCellValueChange,
7
7
  GridRowCommit, GridCommitRowResult, GridCommitOutcome, GridCommit, GridCommitResult } from "./editing.js";
8
- import type { RecordPanelDefinition, RecordLoader, RecordSectionRenderer, RecordAction, RecordOpenAll, OpenRecordOptions } from "./records.js";
8
+ import type { RecordPanelDefinition, RecordPanelOptions, RecordLoader, RecordSectionRenderer, RecordAction, RecordOpenAll, OpenRecordOptions } from "./records.js";
9
9
  export * from "./records.js";
10
10
  export * from "./index.js";
11
11
  export * from "./enhance.js";
@@ -761,6 +761,8 @@ interface GridHostBehavior<Q extends AcceptedGridQuery = GridQuery, Row extends
761
761
  recordSections?: Readonly<Record<string, RecordSectionRenderer>>;
762
762
  /** Actions of the record actions menu, after the built-in ones. */
763
763
  recordActions?: readonly RecordAction[];
764
+ /** Projects a bounded plain-text record title and optional subtitle, without changing record identity. */
765
+ recordHeading?: RecordPanelOptions["recordHeading"];
764
766
  /** Open all in grid of a collection; return false (or cancel canopyx:openAll) to filter the target yourself. */
765
767
  onOpenAll?: (event: RecordOpenAll) => boolean | void;
766
768
  /** Print one record; return false (or cancel canopyx:recordPrint) to print the sheet yourself. */
@@ -75,6 +75,8 @@ export interface GridLiveState {
75
75
  }
76
76
 
77
77
  export interface GridPollOptions<Row extends GridRow = GridRow, Q extends AcceptedGridQuery = GridQuery> {
78
+ /** After a successful native refresh, including unchanged rows. Not called for cancelled or failed loads; useful for snapshot provenance beside the grid. */
79
+ onRefresh?: (result: GridLiveResult) => void;
78
80
  /** 250..86400000; defaults to the live pollMs. */
79
81
  intervalMs?: number;
80
82
  /** Poll at once instead of after the first interval. */