@evotecit/canopyx 0.3.10 → 0.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,7 +13,7 @@
13
13
  .cx-kind-number .cx-editor{text-align:right;font-variant-numeric:tabular-nums;}
14
14
  .cx-editor.cx-editor-toggle{flex:none;width:var(--cx-size-18px);height:var(--cx-size-18px);margin:0 auto 0 var(--cx-size-6px);accent-color:var(--cx-accent);}
15
15
  .cx-edit-tip{position:fixed;inset:auto;margin:0;box-sizing:border-box;background:var(--cx-surface);color:var(--cx-text);border:var(--cx-size-1px) solid var(--cx-line-strong);border-radius:var(--cx-radius);box-shadow:var(--cx-panel-shadow);font:var(--cx-size-13d5px)/1.4 var(--cx-font);}
16
- .cx-edit-tip{max-width:var(--cx-size-280px);padding:var(--cx-size-6px) var(--cx-size-10px);border-left:var(--cx-size-3px) solid var(--cx-tone-danger);white-space:normal;}
16
+ .cx-edit-tip{max-width:var(--cx-size-280px);padding:var(--cx-size-6px) var(--cx-size-10px);border-left:var(--cx-size-3px) solid var(--cx-tone-danger);white-space:normal;pointer-events:none;}
17
17
  .cx-editbar{display:flex;align-items:center;gap:var(--cx-size-4px);height:var(--cx-control-h);padding:0 var(--cx-size-4px) 0 var(--cx-size-10px);border-radius:var(--cx-radius);background:var(--cx-head-bg);font-size:var(--cx-size-13d5px);}
18
18
  .cx-editbar[hidden]{display:none;}
19
19
  .cx-editbar-text{margin-right:var(--cx-size-4px);white-space:nowrap;}
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"c82648dfaa7e5ee5",requires:["filter-editor","forms"],install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,FORMS_IMPL,h,setText,fill,gridButton,gridDecorateButton,GRID_ICONS,cellValue,cellText,isCellObject,gridFreeze,gridMomentFromParts,numberFormat,gridQuery,foldText,requireIdentifier,checkDocument,validateGridRows,inlineGridSource,PROTOCOL,boundedPattern,validateGridFacetPage,RECORD_IMPL}=context;const{EDIT_EDITORS,editOptions,formRuleSpec,formCheck,FORM_LABELS}=FORMS_IMPL;const EDIT_LABELS={...FORM_LABELS,gridEditCell:"Edit {column}",gridEditSave:"Save",gridEditCancel:"Cancel",gridEditDiscard:"Discard",gridEditUndo:"Undo",gridEditRedo:"Redo",gridEditEdited:"Edited",gridEditChanges:"Unsaved changes: {count}",gridEditErrors:"Errors: {count}",gridEditSaving:"Saving…",gridEditSaved:"Saved rows: {count}",gridEditFailed:"Rows not saved: {count}",gridEditConflict:"Someone else changed this row. Reload it and try again.",gridEditRejected:"Not saved: {error}",gridEditNotSaved:"Not saved.",gridEditUndone:"Undone: {column}",gridEditRedone:"Redone: {column}"};const editCopy=value=>gridFreeze(JSON.parse(JSON.stringify(value===undefined?null:value)));const editSame=(left,right)=>left===right||left==null&&right==null;const editScalar=value=>value===null||typeof value==="string"||typeof value==="boolean"||Number.isFinite(value);const editBad=(id,problem)=>{throw new Error("CanopyX: column "+id+" "+problem+".")};function editSpec(column,editors,columns){const id=column.id,raw=column.editor===undefined?{}:typeof column.editor==="string"?{type:column.editor}:column.editor;const rules=column.validation===undefined?{}:column.validation,object=value=>value&&typeof value==="object"&&!Array.isArray(value);if(!object(raw)||!object(rules))editBad(id,"has an invalid editor or validation");const type=raw.type??column.kind;if(typeof type!=="string"||!Object.hasOwn(editors,type))editBad(id,"names an editor nobody registered");const fits={number:["number"],text:["text"],toggle:["text"],date:["datetime","text"],datetime:["datetime","text"],time:["datetime","text"]}[type];if(fits&&!fits.includes(column.kind))editBad(id,"cannot use a "+type+" editor for its kind");const{pattern,rules:checks}=formRuleSpec(raw,rules,problem=>editBad(id,problem));const lookup=raw.lookup??(type==="lookup"?{}:null);if(lookup&&(!object(lookup)||lookup.column!==undefined&&!columns.some(item=>item.id===lookup.column)||
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"05fcb2c8be754b50",requires:["filter-editor","forms"],install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,FORMS_IMPL,h,setText,fill,gridButton,gridDecorateButton,GRID_ICONS,cellValue,cellText,isCellObject,gridFreeze,gridMomentFromParts,numberFormat,gridQuery,foldText,requireIdentifier,checkDocument,validateGridRows,inlineGridSource,PROTOCOL,boundedPattern,validateGridFacetPage,RECORD_IMPL}=context;const{EDIT_EDITORS,editOptions,formRuleSpec,formCheck,FORM_LABELS}=FORMS_IMPL;const EDIT_LABELS={...FORM_LABELS,gridEditCell:"Edit {column}",gridEditSave:"Save",gridEditCancel:"Cancel",gridEditDiscard:"Discard",gridEditUndo:"Undo",gridEditRedo:"Redo",gridEditEdited:"Edited",gridEditChanges:"Unsaved changes: {count}",gridEditErrors:"Errors: {count}",gridEditSaving:"Saving…",gridEditSaved:"Saved rows: {count}",gridEditFailed:"Rows not saved: {count}",gridEditConflict:"Someone else changed this row. Reload it and try again.",gridEditRejected:"Not saved: {error}",gridEditNotSaved:"Not saved.",gridEditUndone:"Undone: {column}",gridEditRedone:"Redone: {column}"};const editCopy=value=>gridFreeze(JSON.parse(JSON.stringify(value===undefined?null:value)));const editSame=(left,right)=>left===right||left==null&&right==null;const editScalar=value=>value===null||typeof value==="string"||typeof value==="boolean"||Number.isFinite(value);const editBad=(id,problem)=>{throw new Error("CanopyX: column "+id+" "+problem+".")};function editSpec(column,editors,columns){const id=column.id,raw=column.editor===undefined?{}:typeof column.editor==="string"?{type:column.editor}:column.editor;const rules=column.validation===undefined?{}:column.validation,object=value=>value&&typeof value==="object"&&!Array.isArray(value);if(!object(raw)||!object(rules))editBad(id,"has an invalid editor or validation");const type=raw.type??column.kind;if(typeof type!=="string"||!Object.hasOwn(editors,type))editBad(id,"names an editor nobody registered");const fits={number:["number"],text:["text"],toggle:["text"],date:["datetime","text"],datetime:["datetime","text"],time:["datetime","text"]}[type];if(fits&&!fits.includes(column.kind))editBad(id,"cannot use a "+type+" editor for its kind");const{pattern,rules:checks}=formRuleSpec(raw,rules,problem=>editBad(id,problem));const lookup=raw.lookup??(type==="lookup"?{}:null);if(lookup&&(!object(lookup)||lookup.column!==undefined&&!columns.some(item=>item.id===lookup.column)||
2
2
  lookup.limit!==undefined&&!(Number.isInteger(lookup.limit)&&lookup.limit>=1&&lookup.limit<=50)||
3
3
  lookup.minLength!==undefined&&!(Number.isInteger(lookup.minLength)&&lookup.minLength>=0&&lookup.minLength<=16)))editBad(id,"has invalid lookup settings");return Object.freeze({id,column,type,editor:gridFreeze({...raw,type}),options:editOptions(raw.options,id),lookup:lookup&&Object.freeze({column:lookup.column??id,limit:lookup.limit??20,minLength:lookup.minLength??1}),pattern,rules:checks})}
4
4
  function editCell(original,value,text){if(!isCellObject(original)&&text===undefined)return value;const cell=isCellObject(original)?{...original}:{};delete cell.text;delete cell.searchText;delete cell.sort;delete cell.secondary;cell.value=value;if(text!==undefined)cell.text=text;return cell}
@@ -73,13 +73,14 @@ this.editRowsChanged()}
73
73
  for(const list of[state.undo,state.redo])for(let at=list.length-1;at>=0;at--)if(list[at].some(step=>step.insert&&step.id===from))list.splice(at,1);if(to!==from)for(const steps of[...state.undo,...state.redo])for(const step of steps)if(step.id===from){step.id=to;if(step.insert)step.insert.id=to}
74
74
  if(to!==from)this.emit("rowIdChanged",{from,to});if(later.length){const outer=state.group,target=this.editRecord(to)||record;state.group=[];try{for(const column of later)this.editApply(to,state.specs.get(column),entry.values[column],"accept",target)}
75
75
  finally{state.group=outer}}
76
- if(to!==from&&this.editOwnsRows())Promise.resolve(this.reload?.()).catch(()=>{})}});GRID_ICONS.undo='<path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/>';GRID_ICONS.redo='<path d="m15 14 5-5-5-5"/><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"/>';const editAttr=(element,name,value)=>{if(value==null)element.removeAttribute(name);else if(element.getAttribute(name)!==value)element.setAttribute(name,value)};Object.assign(DataGrid.prototype,{buildEditing(){const state=this.edit,signal=this.lifetime.signal,grid=this.grid,labels=state.labels;state.tip=h("div","cx-edit-tip");state.tip.id=this.id+"-edit-tip";state.tip.popover="manual";state.notes=h("div","cx-sr-only");state.notes.id=this.id+"-edit-notes";this.host.append(state.tip,state.notes);grid.addEventListener("keydown",event=>this.editGridKey(event),{capture:true,signal});grid.addEventListener("pointerdown",event=>{const cell=event.target.closest?.(".cx-cell");state.armed=cell&&cell===document.activeElement?cell:null},{capture:true,signal});grid.addEventListener("click",event=>this.editClick(event),{signal});grid.addEventListener("dblclick",event=>{const at=!this.phone&&this.editCellAt(event.target);if(at){event.stopPropagation();this.setFocus(at.row,false);this.editStart(at.row,at.column)}},{capture:true,signal});this.canvas.addEventListener("focusin",event=>{const row=event.target.closest(".cx-row")?._w;if(row&&!row.status)this.editEnterRow(row.key);this.editRefreshMessage()},{signal});this.canvas.addEventListener("focusout",event=>{if(!event.relatedTarget||!this.canvas.contains(event.relatedTarget))this.editHideMessage()},{signal});grid.addEventListener("scroll",()=>{if(state.tip.matches(":popover-open"))this.editRefreshMessage()},{passive:true,signal});signal.addEventListener("abort",()=>{if(state.session)for(const field of state.session.fields.values())this.editDispose(field);state.tip.remove();state.notes.remove();state.barEl?.remove()},{once:true});if(!state.bar)return;const bar=state.barEl=h("div","cx-editbar"),status=h("span","cx-editbar-text");state.barText=status.appendChild(h("span"));state.barErrors=status.appendChild(h("span","cx-editbar-errors"));status.setAttribute("role","status");const act=run=>()=>Promise.resolve().then(run).catch(error=>this.emit("error",{error}));const icon=(name,text,run)=>{const button=gridDecorateButton(gridButton("",act(run)),name,true);button.classList.add("icon");button.setAttribute("aria-label",text);button.title=text;return button};state.undoButton=icon("undo",labels.gridEditUndo,()=>this.undo());state.redoButton=icon("redo",labels.gridEditRedo,()=>this.redo());state.discardButton=gridDecorateButton(gridButton(labels.gridEditDiscard,act(()=>this.revertChanges())),null,true);state.saveButton=gridDecorateButton(gridButton(labels.gridEditSave,act(()=>this.commitChanges())),"check");state.saveButton.classList.add("cx-edit-save");bar.append(status,state.undoButton,state.redoButton,state.discardButton,state.saveButton);(this.spacer&&this.spacer.parentNode===this.toolbar?this.spacer:this.toolbar.lastChild)?.after(bar);this.syncEditBar()},editGridKey(event){const state=this.edit;if(event.defaultPrevented||event.isComposing||event.target.closest(".cx-editor-host"))return;const key=event.key.toLowerCase(),command=(event.ctrlKey||event.metaKey)&&!event.altKey;if(command&&(key==="z"||key==="y")&&!event.target.closest("input,textarea,select,[contenteditable]")){event.preventDefault();event.stopPropagation();if(key==="y"||event.shiftKey)this.redo();else this.undo();return}
76
+ if(to!==from&&this.editOwnsRows())Promise.resolve(this.reload?.()).catch(()=>{})}});GRID_ICONS.undo='<path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/>';GRID_ICONS.redo='<path d="m15 14 5-5-5-5"/><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"/>';const editAttr=(element,name,value)=>{if(value==null)element.removeAttribute(name);else if(element.getAttribute(name)!==value)element.setAttribute(name,value)};Object.assign(DataGrid.prototype,{buildEditing(){const state=this.edit,signal=this.lifetime.signal,grid=this.grid,labels=state.labels;state.tip=h("div","cx-edit-tip");state.tip.id=this.id+"-edit-tip";state.tip.popover="manual";state.notes=h("div","cx-sr-only");state.notes.id=this.id+"-edit-notes";state.tipObserver=new ResizeObserver(()=>{if(state.tip.matches(":popover-open"))this.editTip(state.tipAnchor,state.tip.textContent)});this.host.append(state.tip,state.notes);grid.addEventListener("keydown",event=>this.editGridKey(event),{capture:true,signal});grid.addEventListener("pointerdown",event=>{const cell=event.target.closest?.(".cx-cell");state.armed=cell&&cell===document.activeElement?cell:null},{capture:true,signal});grid.addEventListener("click",event=>this.editClick(event),{signal});grid.addEventListener("dblclick",event=>{const at=!this.phone&&this.editCellAt(event.target);if(at){event.stopPropagation();this.setFocus(at.row,false);this.editStart(at.row,at.column)}},{capture:true,signal});this.canvas.addEventListener("focusin",event=>{const row=event.target.closest(".cx-row")?._w;if(row&&!row.status)this.editEnterRow(row.key);this.editRefreshMessage()},{signal});this.canvas.addEventListener("focusout",event=>{if(!event.relatedTarget||!this.canvas.contains(event.relatedTarget))this.editHideMessage()},{signal});grid.addEventListener("scroll",()=>{if(state.tip.matches(":popover-open"))this.editRefreshMessage()},{passive:true,signal});signal.addEventListener("abort",()=>{state.tipObserver.disconnect();if(state.session)for(const field of state.session.fields.values())this.editDispose(field);state.tip.remove();state.notes.remove();state.barEl?.remove()},{once:true});if(!state.bar)return;const bar=state.barEl=h("div","cx-editbar"),status=h("span","cx-editbar-text");state.barText=status.appendChild(h("span"));state.barErrors=status.appendChild(h("span","cx-editbar-errors"));status.setAttribute("role","status");const act=run=>()=>Promise.resolve().then(run).catch(error=>this.emit("error",{error}));const icon=(name,text,run)=>{const button=gridDecorateButton(gridButton("",act(run)),name,true);button.classList.add("icon");button.setAttribute("aria-label",text);button.title=text;return button};state.undoButton=icon("undo",labels.gridEditUndo,()=>this.undo());state.redoButton=icon("redo",labels.gridEditRedo,()=>this.redo());state.discardButton=gridDecorateButton(gridButton(labels.gridEditDiscard,act(()=>this.revertChanges())),null,true);state.saveButton=gridDecorateButton(gridButton(labels.gridEditSave,act(()=>this.commitChanges())),"check");state.saveButton.classList.add("cx-edit-save");bar.append(status,state.undoButton,state.redoButton,state.discardButton,state.saveButton);(this.spacer&&this.spacer.parentNode===this.toolbar?this.spacer:this.toolbar.lastChild)?.after(bar);this.syncEditBar()},editGridKey(event){const state=this.edit;if(event.defaultPrevented||event.isComposing||event.target.closest(".cx-editor-host"))return;const key=event.key.toLowerCase(),command=(event.ctrlKey||event.metaKey)&&!event.altKey;if(command&&(key==="z"||key==="y")&&!event.target.closest("input,textarea,select,[contenteditable]")){event.preventDefault();event.stopPropagation();if(key==="y"||event.shiftKey)this.redo();else this.undo();return}
77
77
  const at=!command&&!event.altKey&&this.editCellAt(event.target,true);if(!at)return;const typed=event.key.length===1&&event.key!==" ",empty=event.key==="Backspace"||event.key==="Delete";if((typed||empty||event.key==="F2"||event.key==="Enter")&&this.editStart(at.row,at.column,typed?event.key:empty?"":undefined)){event.preventDefault();event.stopPropagation()}
78
78
  if(state.session===null&&event.key==="Escape")this.editHideMessage()},editCellAt(target,own){const cell=target.closest?.(".cx-cell"),element=cell?.parentNode,row=element?._w;if(!row||row.status||own&&target!==cell||target.closest(".cx-editor-host"))return null;const column=this.visibleColumns()[this.rowCells(element).indexOf(cell)];return column&&this.canEditCell(row.h,column.id)?{row,column:column.id,cell}:null},editClick(event){const at=!this.phone&&!event.target.closest("a,button,input,select,textarea,[contenteditable]")&&this.editCellAt(event.target);if(!at||event.detail>1)return;if(this.edit.armed===at.cell)this.editStart(at.row,at.column);else this.focusCell(at.row,this.editColumnIndex(at.column),null)},editNote(key,text){const state=this.edit;let note=state.messages.get(key);if(!note){note=h("span");note.id=this.id+"-en" + ++state.sequence;state.notes.appendChild(note);state.messages.set(key,note)}
79
79
  if(note.textContent!==text)setText(note,text);return note.id},paintEdits(element,row){const state=this.edit,entry=state.changes.get(row.key),session=state.session?.wrapper===row?state.session:null;const rowError=entry&&(entry.error||entry.rowError);element.classList.toggle("cx-row-invalid",!!rowError);editAttr(element,"aria-describedby",rowError?this.editNote("\u0001"+row.key,rowError):null);editAttr(element,"aria-busy",entry?.status==="saving"?"true":null);const errors=entry?editErrors(entry):Object.create(null);this.cols.forEach((column,index)=>{const slot=element._cells[index],cell=slot.cell,dirty=!!entry&&Object.hasOwn(entry.values,column.id),error=errors[column.id];const editable=state.specs.has(column.id)&&this.canEditCell(row.h,column.id),field=session?.fields.get(column.id);cell.classList.toggle("cx-dirty",dirty);cell.classList.toggle("cx-invalid",!!error);cell.classList.toggle("cx-editable",editable);editAttr(cell,"aria-readonly",editable?null:"true");editAttr(cell,"aria-invalid",error?"true":null);editAttr(cell,"aria-describedby",[dirty&&this.editNote("edited",state.labels.gridEditEdited),error&&this.editNote(row.key+"\u0000"+column.id,error)].filter(Boolean).join(" ")||null);if(field&&field.cell!==cell){field.cell.classList.remove("cx-editing");field.cell=cell}
80
80
  if(field){cell.classList.add("cx-editing");if(field.host.parentNode!==cell)cell.appendChild(field.host)}})},editShowMessage(field,message){const state=this.edit,entry=state.changes.get(field.record.id);const text=message||(entry&&!Object.hasOwn(entry.values,field.spec.id)?null:entry&&editErrors(entry)[field.spec.id])||null;editAttr(field.control,"aria-invalid",text?"true":null);editAttr(field.control,"aria-describedby",text?state.tip.id:null);if(text)this.editTip(field.cell||field.host,text);else this.editHideMessage()},editRefreshMessage(){const state=this.edit,active=document.activeElement,session=state.session;const field=session&&[...session.fields.values()].find(item=>item.host.contains(active));if(field){this.editShowMessage(field);return}
81
- const cell=active?.classList?.contains("cx-cell")&&this.canvas.contains(active)?active:null,row=cell?.parentNode._w;const column=row&&this.visibleColumns()[this.rowCells(cell.parentNode).indexOf(cell)],entry=row&&state.changes.get(row.key);const text=entry&&column?editErrors(entry)[column.id]||(column===this.visibleColumns()[0]?entry.error||entry.rowError:null):null;if(text)this.editTip(cell,text);else this.editHideMessage()},editTip(anchor,text){const tip=this.edit.tip,box=anchor.getBoundingClientRect();if(!anchor.isConnected||!box.width){this.editHideMessage();return}
82
- setText(tip,text);tip.style.left=Math.max(4,Math.min(box.left,innerWidth-280))+ "px";tip.style.top=box.bottom+4+"px";if(!tip.matches(":popover-open"))tip.showPopover()},editHideMessage(){const tip=this.edit?.tip;if(tip?.matches(":popover-open"))tip.hidePopover()},editAnnounce(text){if(text)setText(this.live,text +((this.edit.flip=!this.edit.flip)?" ":""))},syncEditBar(){const state=this.edit;if(!state)return;for(const[key,note]of state.messages){const row=key[0]==="\u0001",[id,column]=(row?key.slice(1):key).split("\u0000"),entry=state.changes.get(id);if(key!=="edited"&&!(entry&&(row?entry.error||entry.rowError:editErrors(entry)[column]))){note.remove();state.messages.delete(key)}}
81
+ const cell=active?.classList?.contains("cx-cell")&&this.canvas.contains(active)?active:null,row=cell?.parentNode._w;const column=row&&this.visibleColumns()[this.rowCells(cell.parentNode).indexOf(cell)],entry=row&&state.changes.get(row.key);const text=entry&&column?editErrors(entry)[column.id]||(column===this.visibleColumns()[0]?entry.error||entry.rowError:null):null;if(text)this.editTip(cell,text);else this.editHideMessage()},editTip(anchor,text){const state=this.edit,tip=state.tip,box=anchor.getBoundingClientRect();if(!anchor.isConnected||!box.width){this.editHideMessage();return}
82
+ setText(tip,text);tip.style.left=Math.max(4,Math.min(box.left,innerWidth-280))+ "px";if(!tip.matches(":popover-open"))tip.showPopover();const control=anchor.querySelector("[aria-controls]"),list=document.getElementById(control?.getAttribute("aria-controls"));const popup=list?.closest("[popover]");state.tipAnchor=anchor;if(state.tipPopup!==popup){state.tipObserver.disconnect();state.tipPopup=popup;if(popup)state.tipObserver.observe(popup)}
83
+ const options=popup?.matches(":popover-open")?popup.getBoundingClientRect():box;const top=Math.min(box.top,options.top),bottom=Math.max(box.bottom,options.bottom);const left=Math.min(box.left,options.left),right=Math.max(box.right,options.right);if(top-tip.offsetHeight>=8)tip.style.top=top-tip.offsetHeight-4+"px";else if(right+tip.offsetWidth+8<=innerWidth||left-tip.offsetWidth>=8){tip.style.left=(right+tip.offsetWidth+8<=innerWidth?right+4:left-tip.offsetWidth-4)+ "px";tip.style.top=Math.max(4,Math.min(box.top,innerHeight-tip.offsetHeight-4))+ "px"}else tip.style.top=bottom+4+"px"},editHideMessage(){const state=this.edit;state?.tipObserver.disconnect();if(state){state.tipAnchor=state.tipPopup=null;if(state.tip.matches(":popover-open"))state.tip.hidePopover()}},editAnnounce(text){if(text)setText(this.live,text +((this.edit.flip=!this.edit.flip)?" ":""))},syncEditBar(){const state=this.edit;if(!state)return;for(const[key,note]of state.messages){const row=key[0]==="\u0001",[id,column]=(row?key.slice(1):key).split("\u0000"),entry=state.changes.get(id);if(key!=="edited"&&!(entry&&(row?entry.error||entry.rowError:editErrors(entry)[column]))){note.remove();state.messages.delete(key)}}
83
84
  if(!state.barEl)return;const entries=this.editEntries(),count=entries.length,errors=entries.filter(editInvalid).length,saving=[...state.changes.values()].some(entry=>entry.status==="saving");state.barEl.hidden=!count&&!state.undo.length&&!state.redo.length&&!saving;setText(state.barText,saving?state.labels.gridEditSaving:fill(state.labels.gridEditChanges,{count:numberFormat(this.lang).format(count)}));setText(state.barErrors,errors&&!saving?" · "+fill(state.labels.gridEditErrors,{count:numberFormat(this.lang).format(errors)}):"");state.undoButton.disabled=!state.undo.length;state.redoButton.disabled=!state.redo.length;state.discardButton.disabled=state.saveButton.disabled=!count||saving},editRemember(column,option){const seen=(this.edit.seen||=new Map()),list=seen.get(column)||[];if(!list.some(item=>item.value===option.value)){list.push(option);if(list.length>1000)list.shift()}
84
85
  seen.set(column,list)},async editLookup(spec,search,record,signal){const limit=spec.lookup.limit,lookups=this.edit.options.lookups,own=lookups&&Object.hasOwn(lookups,spec.id)?lookups[spec.id]:null,text=foldText(search.trim());const matching=list=>list.filter(option=>foldText(option.label).includes(text)).slice(0,limit);if(typeof own==="function")return editOptions(await own({column:spec.id,search,limit,row:editCopy(record),signal}),spec.id).slice(0,limit);if(spec.options)return matching(spec.options);const column=this.columns.find(item=>item.id===spec.lookup.column);if(this.view.source.kind==="inline"){await this.source.decoded;const values=new Map();for(const row of this.view.rows){const value=cellValue(row.cells[column.id]);if(value!=null&&!values.has(value))values.set(value,{value,label:cellText(row.cells[column.id],column,this.fmt)})}
85
86
  return matching([...values.values()].sort((left,right)=>left.label.localeCompare(right.label,this.lang)))}
@@ -1,9 +1,10 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"8a058a87bbba3cbe",install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,gridButton,gridInputLabel,gridOption,gridScalar,gridDateInputMoment,gridQuery,gridQueryStart,GRID_FILTER_LABELS,gridResultShape,gridQueryRows,gridOrder,gridColumnProjection,gridCellRenderer,cellValue,cellText,foldText,reachable,gridMatchesGroup,gridDecorateButton,gridIcon,numberFormat,numberText,fill,announceMenu,reportingRangeRows,applyTone,toneOf,badgeElement,isCellObject,RECORD_IMPL}=context;const buildFilters=DataGrid.prototype.buildGridFilters;function gridOverlayTheme(grid,element){for(const name of(grid.opts.overlayClass||"").split(/\s+/).filter(Boolean)) element.classList.add(name);
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"20fda9e421ce521f",install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,gridButton,gridInputLabel,gridOption,gridScalar,gridDateInputMoment,gridQuery,gridQueryStart,GRID_FILTER_LABELS,gridResultShape,gridQueryRows,gridOrder,gridColumnProjection,gridCellRenderer,cellValue,cellText,foldText,reachable,gridMatchesGroup,gridDecorateButton,gridIcon,numberFormat,numberText,fill,announceMenu,reportingRangeRows,applyTone,toneOf,badgeElement,isCellObject,RECORD_IMPL}=context;const buildFilters=DataGrid.prototype.buildGridFilters;function gridOverlayTheme(grid,element){for(const name of(grid.opts.overlayClass||"").split(/\s+/).filter(Boolean)) element.classList.add(name);
2
2
  element.setAttribute("data-cx-theme",grid.host.getAttribute("data-cx-theme"));const theme=getComputedStyle(grid.host);element.style.colorScheme=theme.colorScheme;for(const name of theme)if(name.startsWith("--cx-"))element.style.setProperty(name,theme.getPropertyValue(name))}
3
3
  function gridRestoreFocus(grid,returnFocus,rowId,column){if(grid.destroyed)return;if(returnFocus?.isConnected&&reachable(returnFocus)){returnFocus.focus({preventScroll:true});return}
4
4
  const row=[...grid.rowCache.values()].find(item=>!item.status&&item.key===rowId);const index=grid.visibleColumns().findIndex(item=>item.id===column?.id);if(row&&index>=0)grid.focusCell(row,index,0);else if(row)grid.setFocus(row,true);else grid.grid.focus({preventScroll:true})}
5
5
  const COLUMNS_MENU={moveColumnChoice(column,target,after){column.pin=target.pin;const ids=this.columns.map(item=>item.id).filter(id=>id!==column.id);ids.splice(ids.indexOf(target.id)+ after,0,column.id);this.setColumnOrder(ids)},renderGridColumns(panel){if(!this.columnList){const find=this.columnFind=h("input","cx-grid-column-find"),actions=h("div","cx-grid-column-actions");find.type="search";find.placeholder=this.labels.gridFindColumn;find.setAttribute("aria-label",find.placeholder);find.hidden=this.columns.length<9;find.oninput=()=>this.syncColumnControls();actions.append(gridButton(this.labels.gridShowAllColumns,()=>this.showAllColumns()),gridButton(this.labels.gridResetColumns,()=>this.resetColumns()));panel.replaceChildren(find,this.columnList=h("div"),actions)}
6
6
  this.syncColumnControls()},syncColumnControls(){const list=this.columnList,active=document.activeElement,query=foldText(this.columnFind?.value.trim()||"");if(!list)return;const focus=list.contains(active)&&active.closest(".cx-grid-column-choice").dataset.cxColumn,held=focus&&active.matches(".cx-grid-column-handle"),last=this.columns.filter(item=>!item.hidden).length<2;list.textContent="";for(const column of this.columns){const row=h("div","cx-grid-column-choice"),label=h("label"),input=h("input"),name=h("span","cx-grid-column-name"),handle=h("button","cx-grid-column-handle"),note=column.fitHidden||column.responsiveHidden?this.labels.gridResponsiveHidden:column.pin==="left"?this.labels.gridPinnedLeft:column.pin==="right"?this.labels.gridPinnedRight:"";input.type="checkbox";input.checked=!column.hidden;input.disabled=!column.hidden&&last;input.onchange=()=>{input.focus({preventScroll:true});this.setColumnVisible(column.id,input.checked)};setText(name,name.title=column.title);handle.type="button";setText(handle,"⋮⋮");handle.setAttribute("aria-label",fill(this.labels.gridReorderColumn,{column:column.title}));label.append(input,name);row.append(handle,label);row.hidden=!!query&&!foldText(column.title).includes(query);if(note){const span=h("span","cx-grid-column-note");setText(span,note);row.append(span)}
7
+ if(this.openColumnMenu&&this.tools.columnMenus!==false){const menu=gridDecorateButton(gridButton("",()=>this.openColumnMenu(column.id,menu)),"more",true);menu.classList.add("cx-grid-column-options","icon");menu.setAttribute("aria-label",fill(this.labels.gridColumnMenu,{column:column.title}));menu.setAttribute("aria-haspopup","menu");row.append(menu)}
7
8
  row.onkeydown=event=>{const target=event.altKey&&this.columns[this.columns.indexOf(column)+(event.key==="ArrowUp"?-1:event.key==="ArrowDown"?1:NaN)];if(target){event.preventDefault();event.stopPropagation();this.moveColumnChoice(column,target,event.key==="ArrowDown")}};handle.onpointerdown=event=>{if(event.button)return;event.preventDefault();handle.focus();handle.setPointerCapture(event.pointerId);let target,after;const clear=()=>{for(const item of list.children)item.classList.remove("cx-drop-before","cx-drop-after")};handle.onpointermove=move=>{clear();const over=document.elementFromPoint(move.clientX,move.clientY)?.closest(".cx-grid-column-choice");target=over!==row&&list.contains(over)&&this.columns[[...list.children].indexOf(over)];if(target){const box=over.getBoundingClientRect();after=move.clientY>box.top+box.height / 2; over.classList.add(after ? "cx-drop-after" : "cx-drop-before"); }
8
9
  };handle.onpointerup=handle.onpointercancel=up=>{handle.onpointermove=handle.onpointerup=handle.onpointercancel=null;clear();if(up.type==="pointerup"&&target)this.moveColumnChoice(column,target,after)}};row.dataset.cxColumn=column.id;list.appendChild(row);if(focus===column.id)(held?handle:input).focus({preventScroll:true})}}};function gridFilterValue(grid,column,type,raw){if(column.kind==="number"){if(!raw.trim()||!Number.isFinite(Number(raw)))throw new Error(grid.labels.gridInvalidFilter);return Number(raw)}
9
10
  if(column.kind==="datetime"){let text=raw;if(!/(?:Z|[+-]\d\d:\d\d)$/.test(raw)) {
@@ -54,8 +55,8 @@ const predicates=definition?.filters||[];(this.view.reporting&&reportingRangeRow
54
55
  return filters.length||groups.length?{operator:segment._operator,filters,groups}:null};const readQuery=()=>{if(editingText){const value=JSON.parse(text.value);return gridQueryStart(this.queryForChange(true),{filters:value.filters||[],filterGroup:value.filterGroup})}
55
56
  const value=readBlock(root);if(!value)return gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:undefined});if(value.operator==="or")return gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:value});return gridQueryStart(this.queryForChange(true),{filters:value.filters,filterGroup:value.groups.length===1?value.groups[0]:value.groups.length?{operator:"and",filters:[],groups:value.groups}:undefined})};const root=makeGroup(body,{operator:"and",filters:this.queryForChange().filters||[],groups:this.queryForChange().filterGroup?[this.queryForChange().filterGroup]:[]},0);syncWords(root);form.addEventListener("input",update);form.addEventListener("change",update);form.addEventListener("submit",event=>{event.preventDefault();update()})};function gridMenuFocus(panel,event){const items=[...panel.querySelectorAll('[role="menuitem"]')].filter(item=>!item.disabled),index=items.indexOf(document.activeElement);if(!items.length)return;let next;if(["ArrowDown","ArrowUp","Home","End"].includes(event.key))next=event.key==="Home"?0:event.key==="End"?items.length-1:(index+(event.key==="ArrowDown"?1:-1)+items.length)%items.length;else if(event.key.length===1&&!event.ctrlKey&&!event.metaKey&&!event.altKey){const now=performance.now();panel._typeAhead=now-(panel._typeAt||0)>700?event.key:panel._typeAhead+event.key;panel._typeAt=now;const matches=items.map((_,i)=>(index+i+1)%items.length);next=matches.find(i=>foldText(items[i].textContent.trim()).startsWith(foldText(panel._typeAhead)))}else return;if(next===undefined)return;event.preventDefault();items.forEach((item,i)=>item.tabIndex=i===next?0:-1);items[next].focus({preventScroll:true})}
56
57
  Object.assign(DataGrid.prototype,{openGridPopover(anchor,className,title,columnId){this.closeGridPopover(false);const panel=h("div","cx-host cx-grid-overlay cx-pop "+className),controller=new AbortController(),signal=controller.signal;gridOverlayTheme(this,panel);panel.setAttribute("role","dialog");panel.setAttribute("aria-label",title);panel.tabIndex=-1;panel.id=this.id+"-popover";anchor.setAttribute("aria-controls",panel.id);anchor.setAttribute("aria-expanded","true");document.body.appendChild(panel);announceMenu(panel);const pressed=new Set();let positionPending=false,releaseFrame=0;const position=()=>{if(signal.aborted)return;if(pressed.size||releaseFrame){positionPending=true;return}
57
- positionPending=false;const current=this.headCells.find(cell=>cell.dataset.cxColumn===columnId)||anchor,bounds=current.getBoundingClientRect();if(panel.classList.toggle("cx-phone",this.host.clientWidth<=640)){panel.style.left="0";panel.style.top="auto";panel.style.bottom="0";panel.style.width="100%";panel.style.maxHeight="80vh"}
58
- else{panel.style.width="";panel.style.bottom="auto";panel.style.maxHeight=Math.min(500,global.innerHeight-16)+"px";panel.style.left=Math.max(8,Math.min(bounds.left,global.innerWidth-panel.offsetWidth-8))+"px";panel.style.top=Math.max(8,Math.min(bounds.bottom,global.innerHeight-panel.offsetHeight-8))+"px"}};this.gridPopover={panel,controller,anchor,columnId,position};panel.addEventListener("pointerdown",event=>pressed.add(event.pointerId),{signal});const release=event=>{if(!pressed.delete(event.pointerId))return;if(!releaseFrame)releaseFrame=global.requestAnimationFrame(()=>{releaseFrame=0;if(positionPending)position()})};for(const type of["pointerup","pointercancel"])global.addEventListener(type,release,{capture:true,signal});global.addEventListener("resize",position,{signal});global.addEventListener("scroll",position,{capture:true,signal});panel.addEventListener("keydown",event=>{if(event.key==="Escape"){event.preventDefault();event.stopPropagation();this.closeGridPopover()}else gridMenuFocus(panel,event)},{signal});this.lifetime.signal.addEventListener("abort",()=>controller.abort(),{once:true,signal});signal.addEventListener("abort",()=>{global.cancelAnimationFrame(releaseFrame);pressed.clear();panel.remove()},{once:true});queueMicrotask(position);return panel},openColumnMenu(id,anchor){const column=this.columns.find(item=>item.id===id),panel=this.openGridPopover(anchor,"cx-column-menu",fill(this.labels.gridColumnMenu,{column:column.title}),id);const menu=h("div");menu.setAttribute("role","menu");menu.setAttribute("aria-label",panel.getAttribute("aria-label"));panel.appendChild(menu);const icons=new Map([[this.labels.gridSortAscending,"up"],[this.labels.gridSortDescending,"down"],[this.labels.gridFilterColumn,"filter"],[this.labels.gridPinLeft,"pin"],[this.labels.gridPinRight,"pin"],[this.labels.gridFitContent,"fit"],[this.labels.gridHideColumn,"hide"]]);const paths={pin:'<path d="M9 4h6l-1 6 3 3H7l3-3zM12 13v7"/>',fit:'<path d="M4 12h16M7 9l-3 3 3 3M17 9l3 3-3 3M4 5v14M20 5v14"/>',hide:'<path d="M3 3l18 18M10.6 6.1A9.8 9.8 0 0 1 12 6c5 0 8.5 4.5 9 6-.3.8-1.2 2.3-2.6 3.6M6.4 7.6C4.6 8.9 3.4 10.8 3 12c.5 1.5 4 6 9 6 1.6 0 3-.4 4.3-1.1"/>'};const add=(label,action,disabled=false)=>{const button=gridButton(label,()=>{this.closeGridPopover(false);Promise.resolve().then(action).catch(error=>this.emit("error",{error}))});const icon=h("span","ico"),name=icons.get(label);if(name){icon.appendChild(gridIcon(name,paths[name]))}button.prepend(icon);button.classList.add("cx-mi");button.setAttribute("role","menuitem");button.tabIndex=-1;button.disabled=disabled;menu.appendChild(button)};const sort=direction=>this.setQuery(gridQueryStart(this.queryForChange(true),{sort:[...(this.queryForChange().sort||[]).filter(item=>item.column!==id),...direction?[{column:id,direction}]:[]]}));add(this.labels.gridSortAscending,()=>sort("asc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridSortDescending,()=>sort("desc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridClearSort,()=>sort(null),!(this.getQuery()?.sort||[]).some(item=>item.column===id));menu.appendChild(h("hr","cx-menu-rule"));add(this.labels.gridFilterColumn,()=>this.openColumnFilter(id,this.headRow.querySelector('[data-cx-column-menu="'+CSS.escape(id)+'"]')),column.filterable===false);menu.appendChild(h("hr","cx-menu-rule"));for(const[pin,label]of[["left","gridPinLeft"],["right","gridPinRight"],["none","gridUnpin"]])add(this.labels[label],()=>this.setColumnPinned(id,pin));menu.appendChild(h("hr","cx-menu-rule"));add(this.labels.gridFitContent,()=>this.autoFitColumn(id),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridFitAllColumns,()=>this.autoFitColumns(),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridHideColumn,()=>this.setColumnVisible(id,false),this.columns.filter(item=>!item.hidden).length===1);const first=panel.querySelector('[role="menuitem"]:not(:disabled)');if(first){first.tabIndex=0;first.focus()}}});let activeRecordDrawer;DataGrid.prototype.openGridDrawer=function(record,index,returnFocus,options){if(activeRecordDrawer?.contains(returnFocus))returnFocus=activeRecordDrawer._returnFocus;if(activeRecordDrawer){activeRecordDrawer._replaced=true;activeRecordDrawer.close();activeRecordDrawer.remove()}
58
+ positionPending=false;const current=this.headCells.find(cell=>cell.dataset.cxColumn===columnId)||(anchor.checkVisibility()?anchor:this.grid),bounds=current.getBoundingClientRect();if(panel.classList.toggle("cx-phone",this.host.clientWidth<=640)){panel.style.left="0";panel.style.top="auto";panel.style.bottom="0";panel.style.width="100%";panel.style.maxHeight="80vh"}
59
+ else{panel.style.width="";panel.style.bottom="auto";panel.style.maxHeight=Math.min(500,global.innerHeight-16)+"px";panel.style.left=Math.max(8,Math.min(bounds.left,global.innerWidth-panel.offsetWidth-8))+"px";panel.style.top=Math.max(8,Math.min(bounds.bottom,global.innerHeight-panel.offsetHeight-8))+"px"}};this.gridPopover={panel,controller,anchor,columnId,position};panel.addEventListener("pointerdown",event=>pressed.add(event.pointerId),{signal});const release=event=>{if(!pressed.delete(event.pointerId))return;if(!releaseFrame)releaseFrame=global.requestAnimationFrame(()=>{releaseFrame=0;if(positionPending)position()})};for(const type of["pointerup","pointercancel"])global.addEventListener(type,release,{capture:true,signal});global.addEventListener("resize",position,{signal});global.addEventListener("scroll",position,{capture:true,signal});panel.addEventListener("keydown",event=>{if(event.key==="Escape"){event.preventDefault();event.stopPropagation();this.closeGridPopover()}else gridMenuFocus(panel,event)},{signal});this.lifetime.signal.addEventListener("abort",()=>controller.abort(),{once:true,signal});signal.addEventListener("abort",()=>{global.cancelAnimationFrame(releaseFrame);pressed.clear();panel.remove()},{once:true});queueMicrotask(()=>{if(signal.aborted)return;position();if(!panel.contains(document.activeElement))panel.focus({preventScroll:true})});return panel},openColumnMenu(id,anchor){const column=this.columns.find(item=>item.id===id),panel=this.openGridPopover(anchor,"cx-column-menu",fill(this.labels.gridColumnMenu,{column:column.title}),id);const menu=h("div");menu.setAttribute("role","menu");menu.setAttribute("aria-label",panel.getAttribute("aria-label"));panel.appendChild(menu);const icons=new Map([[this.labels.gridSortAscending,"up"],[this.labels.gridSortDescending,"down"],[this.labels.gridFilterColumn,"filter"],[this.labels.gridPinLeft,"pin"],[this.labels.gridPinRight,"pin"],[this.labels.gridFitContent,"fit"],[this.labels.gridHideColumn,"hide"]]);const paths={pin:'<path d="M9 4h6l-1 6 3 3H7l3-3zM12 13v7"/>',fit:'<path d="M4 12h16M7 9l-3 3 3 3M17 9l3 3-3 3M4 5v14M20 5v14"/>',hide:'<path d="M3 3l18 18M10.6 6.1A9.8 9.8 0 0 1 12 6c5 0 8.5 4.5 9 6-.3.8-1.2 2.3-2.6 3.6M6.4 7.6C4.6 8.9 3.4 10.8 3 12c.5 1.5 4 6 9 6 1.6 0 3-.4 4.3-1.1"/>'};const add=(label,action,disabled=false)=>{const button=gridButton(label,()=>{this.closeGridPopover(false);Promise.resolve().then(action).catch(error=>this.emit("error",{error}))});const icon=h("span","ico"),name=icons.get(label);if(name){icon.appendChild(gridIcon(name,paths[name]))}button.prepend(icon);button.classList.add("cx-mi");button.setAttribute("role","menuitem");button.tabIndex=-1;button.disabled=disabled;menu.appendChild(button)};const sort=direction=>this.setQuery(gridQueryStart(this.queryForChange(true),{sort:[...(this.queryForChange().sort||[]).filter(item=>item.column!==id),...direction?[{column:id,direction}]:[]]}));add(this.labels.gridSortAscending,()=>sort("asc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridSortDescending,()=>sort("desc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridClearSort,()=>sort(null),!(this.getQuery()?.sort||[]).some(item=>item.column===id));menu.appendChild(h("hr","cx-menu-rule"));add(this.labels.gridFilterColumn,()=>this.openColumnFilter(id,this.headRow.querySelector('[data-cx-column-menu="'+CSS.escape(id)+'"]')||anchor),column.filterable===false);menu.appendChild(h("hr","cx-menu-rule"));for(const[pin,label]of[["left","gridPinLeft"],["right","gridPinRight"],["none","gridUnpin"]])add(this.labels[label],()=>this.setColumnPinned(id,pin));menu.appendChild(h("hr","cx-menu-rule"));add(this.labels.gridFitContent,()=>this.autoFitColumn(id),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridFitAllColumns,()=>this.autoFitColumns(),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridHideColumn,()=>this.setColumnVisible(id,false),this.columns.filter(item=>!item.hidden).length===1);const first=panel.querySelector('[role="menuitem"]:not(:disabled)');if(first){first.tabIndex=0;first.focus()}}});let activeRecordDrawer;DataGrid.prototype.openGridDrawer=function(record,index,returnFocus,options){if(activeRecordDrawer?.contains(returnFocus))returnFocus=activeRecordDrawer._returnFocus;if(activeRecordDrawer){activeRecordDrawer._replaced=true;activeRecordDrawer.close();activeRecordDrawer.remove()}
59
60
  const dialog=h("dialog","cx-host cx-grid-overlay cx-drawer"),head=h("div","cx-drawer-h"),identity=h("div"),title=h("h4"),subtitle=h("p"),body=h("div","cx-drawer-body");dialog._returnFocus=returnFocus;gridOverlayTheme(this,dialog);title.id=this.id+"-record-title";title.tabIndex=-1;title.setAttribute("aria-level","2");dialog.setAttribute("aria-labelledby",title.id);const previous=gridDecorateButton(gridButton("",()=>navigate(-1)),"up",true),next=gridDecorateButton(gridButton("",()=>navigate(1)),"down",true),close=gridDecorateButton(gridButton("",()=>dialog.close()),"close",true);previous.setAttribute("aria-label",this.labels.gridPreviousRecord);next.setAttribute("aria-label",this.labels.gridNextRecord);close.setAttribute("aria-label",this.labels.gridCloseRecord);for(const button of[previous,next,close])button.classList.add("icon");identity.append(title,subtitle);head.append(identity,previous,next,close);dialog.append(head,body);document.body.appendChild(dialog);activeRecordDrawer=dialog;this.recordDrawer=dialog;DataGrid.activeDrawers.set(dialog,this);const primary=this.visibleColumns()[0],shape=gridResultShape(this.acceptedQuery),owner=this.dataLifetime;let retiredForNavigation=false,paints=null;const placed=()=>Number.isInteger(index);const steps=()=>{previous.disabled=!placed()||index<=0||this.cursor&&index<=this.rowBounds().first;next.disabled=!placed()||index>=this.rowCount()-1};const paint=(row,position)=>{record=row;index=position;paints?.abort();paints=new AbortController();setText(title,cellText(row.cells[primary.id],primary,this.fmt)||row.id);const options=primary.presenter;const secondary=row.cells[primary.id]?.secondary||options?.secondaryColumn&&cellText(row.cells[options.secondaryColumn],this.columns.find(column=>column.id===options.secondaryColumn),this.fmt)||"";setText(subtitle,secondary);subtitle.hidden=!secondary;dialog._cxRecord=row;dialog._cxIndex=index;dialog.setAttribute("data-cx-record",row.id);dialog.setAttribute("data-cx-view",this.view.id);steps();this.paintDrawerBody(row,body,dialog,{index,signal:paints.signal});dialog.dispatchEvent(new CustomEvent("cx-drawer-paint",{detail:{id:row.id,index}}))};const navigate=async direction=>{const position=index+direction;if(!placed()||position<0||position>=this.rowCount()||this.pendingQuery)return;dialog._navigating=true;previous.disabled=next.disabled=true;try{await this.focusResult(position,false);if(this.destroyed||this.pendingQuery||gridResultShape(this.acceptedQuery)!==shape)return;const row=this.rowCache.get(position);if(!row)return;if(dialog.isConnected){paint(row.h,position);this.focusRing(title)}else if(retiredForNavigation)await this.openDetails(row.key)}catch(error){if(error.name!=="AbortError")this.emit("error",{error})}
60
61
  finally{dialog._navigating=false;if(dialog.isConnected)steps()}};dialog._cxPaint=paint;dialog.addEventListener("keydown",event=>{if(event.key==="Escape"&&!event.defaultPrevented){event.preventDefault();dialog.close()}
61
62
  else if(["ArrowUp","ArrowDown"].includes(event.key)&&!event.defaultPrevented&&!event.target.matches('input,textarea,select,[contenteditable],[role=tab]')&&!event.target.closest(".cx-record-nested")){event.preventDefault();navigate(event.key==="ArrowUp"?-1:1)}});const abort=()=>{retiredForNavigation=dialog._navigating;dialog.close()};owner.signal.addEventListener("abort",abort,{once:true});const refreshHooks=()=>DataGrid.refreshDrawerHooks(this,dialog);this.host.addEventListener("canopyx:format",refreshHooks);dialog.addEventListener("close",()=>{owner.signal.removeEventListener("abort",abort);this.host.removeEventListener("canopyx:format",refreshHooks);DataGrid.activeDrawers.delete(dialog);cancelAnimationFrame(dialog._cxHooksFrame);paints?.abort();dialog.remove();if(activeRecordDrawer===dialog)activeRecordDrawer=null;if(this.recordDrawer===dialog)this.recordDrawer=null;if(!this.recordDrawer&&!dialog._navigating&&!dialog._replaced&&!this.destroyed)gridRestoreFocus(this,returnFocus,record.id,primary)},{once:true});RECORD_IMPL.decorate?.(this,dialog,{head,identity,title,subtitle,body,options:options||{}});DataGrid.applyDrawerHooks(this,dialog);paint(record,index);const phone=this.host.clientWidth<=640;dialog.classList.toggle("cx-phone",phone);if(phone)dialog.showModal();else dialog.show();this.focusRing(title);return dialog};Object.assign(DataGrid.prototype,{paintDrawerBody(row,body,dialog,context){if(RECORD_IMPL.paint&&this.recordNeeded(row))return RECORD_IMPL.paint(this,row,body,dialog,context);body.replaceChildren();const sections=new Map();for(const column of this.columns){if(column.drawer===false)continue;const name=column.section||this.labels.gridDetailsSection;if(!sections.has(name)){const heading=h("div","cx-drawer-s"),list=h("dl","cx-dl");setText(heading,name);sections.set(name,list);body.append(heading,list)}
@@ -506,7 +506,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
506
506
  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=""}
507
507
  close()}else{return}
508
508
  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)}}}
509
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["4c6c4101089c4444","canopyx-tree-tools.510207e8f47014fd.js","canopyx-tree-tools.ef7a3fb9c9115a82.css"],"filter-editor":["8a058a87bbba3cbe","canopyx-filter-editor.15e355b04c7138cc.js","canopyx-filter-editor.01b7bb6820dc9edb.css"],"export":["8b99c0b7b0ec37c5","canopyx-export.6989ea36f5d6da7b.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["8f804f70b96409f2","canopyx-pager.ac543250cf2f6e8b.js","canopyx-pager.08ad67c69026852e.css"],"enhance":["31162b1ffa622bf8","canopyx-enhance.65868addbc5c4a1a.js"],"data":["f07aebe37f3d1bb4","canopyx-data.401d09bc34c61d2f.js"],"forms":["a8c60f205d9babca","canopyx-forms.16987de1cdf9bda9.js","canopyx-forms.29058ce3c88af96e.css"],"flow":["842e1f1956f6213f","canopyx-flow.efc6250968e8b10a.js","canopyx-flow.3152e616c5557452.css"],"flow-host":["de4f9b11ab881eca","canopyx-flow-host.aea5ed35816df2af.js","canopyx-flow-host.1301fcf3454a723a.css"],"flow-checks":["ec2451183901867b","canopyx-flow-checks.29c4586a80f04b6a.js","canopyx-flow-checks.4502d6f7f7487b73.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["426718e2fa1f3cd0","canopyx-flow-pick.379205e09325bca3.js","canopyx-flow-pick.771b06ac50c141a1.css"],"flow-records":["f3c09661bdffb8d0","canopyx-flow-records.fddf130ace0764b1.js","canopyx-flow-records.e362111fb5f85732.css"],"flow-drafts":["4f112f64736ca8e3","canopyx-flow-drafts.09b88e275c7bc3b9.js","canopyx-flow-drafts.2dd86fb31fc10458.css"],"flow-preview":["f4fb5c42743873c0","canopyx-flow-preview.5778d5fce9ae0d78.js","canopyx-flow-preview.7928e22901da2088.css"],"flow-command":["39472118ca80ef02","canopyx-flow-command.78f4f931c52b1bfc.js","canopyx-flow-command.0c1247a371b7e775.css"],"flow-tasks":["147dd31638a9cb94","canopyx-flow-tasks.f012a521560f7075.js","canopyx-flow-tasks.524df90f908f81dd.css"],"flow-dialog":["ebb432cd6e34aba6","canopyx-flow-dialog.b00addd6a176198e.js","canopyx-flow-dialog.e6192e827eca25d2.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":["16ab7faa98c96b46","canopyx-matrix.4d417eaeba54ca4f.js","canopyx-matrix.9b3f57c1d0f090b6.css"],"changes":["2db8e138da4b5658","canopyx-changes.053104f8f56b0a87.js","canopyx-changes.dfbdb3d6c468ccb1.css"],"editing":["c82648dfaa7e5ee5","canopyx-editing.4fe83feec389c2ce.js","canopyx-editing.67c43d3b80f20232.css"],"column-groups":["b42238fd108a8614","canopyx-column-groups.d8ad6322f769b915.js","canopyx-column-groups.37e177d74cebb516.css"],"cell-range":["e99a39e7cccc57b1","canopyx-cell-range.647da96e57924f3e.js","canopyx-cell-range.23f3222652588441.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["1a28068597f435de","canopyx-formatting.68c501f97b71f1ec.js","canopyx-formatting.a59507e4e8334891.css"],"format-editor":["24f176a39c02944a","canopyx-format-editor.3b1dec2527e53988.js","canopyx-format-editor.1ba153c82aa87b04.css"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"detail-rows":["4908d1d2b7f67aa8","canopyx-detail-rows.fe29b1759c962565.js","canopyx-detail-rows.8e38a8ad01fded76.css"],"grouping":["0970f2edbcb32de8","canopyx-grouping.84660cd1a0ea5f8f.js","canopyx-grouping.6c93259b4b89e523.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"facets":["f9219d35a87635f8","canopyx-facets.8bf477b7915bdcd6.js","canopyx-facets.648a88d2f36d4999.css"],"live":["a27c818b731c22e3","canopyx-live.d19df9edc92e7d09.js","canopyx-live.cc4b94a2dec6f064.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.css"],"calendar":["762f4b4b62ecb4d8","canopyx-calendar.dc45ebdeb704d9c3.js","canopyx-calendar.1099197a45632f63.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["bdde26d4b7de2096","canopyx-calendar-edit.4ab2cf55e84f310f.js"],"calendar-ics":["feb3ed2cd67d057f","canopyx-calendar-ics.2a3af9eb3bf444fc.js"],"timeline":["3f04ba99401e9ebd","canopyx-timeline.76928f089774b3de.js","canopyx-timeline.0393f92746f8fa09.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
509
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["bbcdb89bb78ede8b","canopyx-tree-tools.8f90c97d2d2dda86.js","canopyx-tree-tools.ef7a3fb9c9115a82.css"],"filter-editor":["20fda9e421ce521f","canopyx-filter-editor.a5edb204d5e10be3.js","canopyx-filter-editor.01b7bb6820dc9edb.css"],"export":["8b99c0b7b0ec37c5","canopyx-export.6989ea36f5d6da7b.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["8f804f70b96409f2","canopyx-pager.ac543250cf2f6e8b.js","canopyx-pager.08ad67c69026852e.css"],"enhance":["31162b1ffa622bf8","canopyx-enhance.65868addbc5c4a1a.js"],"data":["f07aebe37f3d1bb4","canopyx-data.401d09bc34c61d2f.js"],"forms":["a8c60f205d9babca","canopyx-forms.16987de1cdf9bda9.js","canopyx-forms.29058ce3c88af96e.css"],"flow":["842e1f1956f6213f","canopyx-flow.efc6250968e8b10a.js","canopyx-flow.3152e616c5557452.css"],"flow-host":["de4f9b11ab881eca","canopyx-flow-host.aea5ed35816df2af.js","canopyx-flow-host.1301fcf3454a723a.css"],"flow-checks":["ec2451183901867b","canopyx-flow-checks.29c4586a80f04b6a.js","canopyx-flow-checks.4502d6f7f7487b73.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["426718e2fa1f3cd0","canopyx-flow-pick.379205e09325bca3.js","canopyx-flow-pick.771b06ac50c141a1.css"],"flow-records":["f3c09661bdffb8d0","canopyx-flow-records.fddf130ace0764b1.js","canopyx-flow-records.e362111fb5f85732.css"],"flow-drafts":["4f112f64736ca8e3","canopyx-flow-drafts.09b88e275c7bc3b9.js","canopyx-flow-drafts.2dd86fb31fc10458.css"],"flow-preview":["f4fb5c42743873c0","canopyx-flow-preview.5778d5fce9ae0d78.js","canopyx-flow-preview.7928e22901da2088.css"],"flow-command":["39472118ca80ef02","canopyx-flow-command.78f4f931c52b1bfc.js","canopyx-flow-command.0c1247a371b7e775.css"],"flow-tasks":["147dd31638a9cb94","canopyx-flow-tasks.f012a521560f7075.js","canopyx-flow-tasks.524df90f908f81dd.css"],"flow-dialog":["ebb432cd6e34aba6","canopyx-flow-dialog.b00addd6a176198e.js","canopyx-flow-dialog.e6192e827eca25d2.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":["16ab7faa98c96b46","canopyx-matrix.4d417eaeba54ca4f.js","canopyx-matrix.9b3f57c1d0f090b6.css"],"changes":["2db8e138da4b5658","canopyx-changes.053104f8f56b0a87.js","canopyx-changes.dfbdb3d6c468ccb1.css"],"editing":["05fcb2c8be754b50","canopyx-editing.d96e5d0bee7fb477.js","canopyx-editing.b6bfd3c6c383bcbd.css"],"column-groups":["b42238fd108a8614","canopyx-column-groups.d8ad6322f769b915.js","canopyx-column-groups.37e177d74cebb516.css"],"cell-range":["e99a39e7cccc57b1","canopyx-cell-range.647da96e57924f3e.js","canopyx-cell-range.23f3222652588441.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["1a28068597f435de","canopyx-formatting.68c501f97b71f1ec.js","canopyx-formatting.a59507e4e8334891.css"],"format-editor":["24f176a39c02944a","canopyx-format-editor.3b1dec2527e53988.js","canopyx-format-editor.1ba153c82aa87b04.css"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"detail-rows":["4908d1d2b7f67aa8","canopyx-detail-rows.fe29b1759c962565.js","canopyx-detail-rows.8e38a8ad01fded76.css"],"grouping":["0970f2edbcb32de8","canopyx-grouping.84660cd1a0ea5f8f.js","canopyx-grouping.6c93259b4b89e523.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"facets":["f9219d35a87635f8","canopyx-facets.8bf477b7915bdcd6.js","canopyx-facets.648a88d2f36d4999.css"],"live":["a27c818b731c22e3","canopyx-live.d19df9edc92e7d09.js","canopyx-live.cc4b94a2dec6f064.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.css"],"calendar":["762f4b4b62ecb4d8","canopyx-calendar.dc45ebdeb704d9c3.js","canopyx-calendar.1099197a45632f63.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["bdde26d4b7de2096","canopyx-calendar-edit.4ab2cf55e84f310f.js"],"calendar-ics":["feb3ed2cd67d057f","canopyx-calendar-ics.2a3af9eb3bf444fc.js"],"timeline":["3f04ba99401e9ebd","canopyx-timeline.76928f089774b3de.js","canopyx-timeline.0393f92746f8fa09.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
510
510
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
511
511
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
512
512
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -731,7 +731,7 @@ const same=this.acceptedQuery&&gridResultShape(initial)===gridResultShape(this.a
731
731
  const epoch=++this.queryEpoch;clearTimeout(this.searchTimer);this.searchTimer=null;this.dataLifetime.abort();this.dataLifetime=new AbortController();const lifetime=this.dataLifetime;this.pendingPages.clear();this.pendingQuery=query;this.pendingPaging=paging?{...paging,pageLength:length}:null;this.setNotice(this.labels.loading,false);this.grid.setAttribute("aria-busy","true");this.syncPager();try{let page=(this.cursor?validateGridCursorPage:validateGridPage)(await this.requestPage(query,lifetime.signal),this.view,query,same?this.snapshot:null);if(this.cursor&&paging&&paging.direction)this.validateCursorTransition(page,paging);if(this.paged&&!this.cursor&&!same&&desired){gridOperationActive(this,lifetime.signal);const offset=Math.min(desired,Math.max(0,Math.ceil(page.matched / length) - 1) * length);
732
732
  if(offset){const snapshot={revision:page.revision,total:page.total,matched:page.matched};query=gridQuery(this.view,{...query,offset,revision:page.revision});page=validateGridPage(await this.requestPage(query,lifetime.signal),this.view,query,snapshot)}}
733
733
  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}
734
- 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.focused=[...this.rowCache.values()].find(row=>row.key===previousId)||this.rowCache.get(this.cursor?page.offset:query.offset)||null}
734
+ 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}
735
735
  this.render();if(hadFocus){const element=this.focused&&this.rendered.get(this.focused);(element||this.grid).focus({preventScroll:true})}
736
736
  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})}
737
737
  throw error}}
@@ -746,13 +746,14 @@ indexOf(row){if(!row||this.paged&&(row._ri<this.pageOffset||row._ri>=this.pageOf
746
746
  rowItem(index){if(index<0||index>=this.rowCount()||this.paged&&(index<this.pageOffset||index>=this.pageOffset+this.pageLength))return null;if(this.rowCache.has(index))return this.rowCache.get(index);if(!this.placeholders.has(index))this.placeholders.set(index,{_ri:index,hpx:this.rowH,status:"loading",h:{cells:{}}});const row=this.placeholders.get(index),page=this.pages.get(Math.floor(index / this.pageSize) * this.pageSize);
747
747
  row.status=page&&page.error?"error":"loading";return row}
748
748
  render(){if(this.destroyed||!this.sized)return;let measured=false;if(this.autoRows)this.syncRowOffsets();for(let pass=0;;pass++){this.renderPass();if(!this.autoRows||!this.measureGridRows())break;measured=true;if(pass===3){this.scheduleRender();break}}
749
- for(const[index,row]of this.placeholders)if(!this.rendered.has(row)&&this.focused!==row)this.placeholders.delete(index);this.loadWindow();return measured}
749
+ for(const[index,row]of this.placeholders)if(!this.rendered.has(row)&&this.focused!==row)this.placeholders.delete(index);this.loadWindow();const origin=this.focusOrigin;if(origin&&this.hasGridSize()){this.focusOrigin=null;if(document.activeElement===origin)(this.rendered.get(this.focused)||this.grid).focus({preventScroll:true})}
750
+ return measured}
750
751
  observeDetail(){}
751
752
  trimInactiveCache(){this.trimPages()}
752
753
  clearSnapshotSelection(){const changed=this.selected.size||this.querySelection;this.selectionController?.abort();this.selectionAnchor=null;this.querySelection=null;this.selectionExcluded=null;this.selected.clear();if(changed){this.version++;this.scheduleRender();this.emit("select",{ids:[]});this.syncGridChrome()}}
753
754
  setSelection(ids){if(this.destroyed)return;if(!Array.isArray(ids))throw new Error("CanopyX: selection must be an array of row IDs.");ids.forEach(id=>requireIdentifier(id,"selection ID"));const next=new Set(ids);if(this.view.selection==="none"&&next.size||!this.multi&&next.size>1)throw new Error("CanopyX: selection exceeds the view's mode.");this.selected=next;this.version++;this.scheduleRender();this.emit("select",{ids:[...next]});this.syncGridChrome();this.stateChanged()}
754
755
  setColumnVisible(id,visible){const column=this.columns.find(item=>item.id===id);if(!column||typeof visible!=="boolean")throw new Error("CanopyX: visibility needs a declared column and boolean.");if(!visible&&this.columns.filter(item=>!item.hidden).length===1&&!column.hidden)throw new Error("CanopyX: keep at least one column visible.");column.hidden=!visible;this.buildHeader();this.version++;this.scheduleRender();this.stateChanged();this.syncColumnControls()}
755
- destroy(){if(this.destroyed)return;this.writeStoredState(this.getState());this.destroyed=true;this.queryEpoch++;this.lifetime.abort();this.dataLifetime.abort();for(const row of[...this.rendered.values(),...this.pool])disposeRowHostCells(row);if(this.rafId)cancelAnimationFrame(this.rafId);clearTimeout(this.searchTimer);this.searchTimer=null;clearTimeout(this.stateTimer);if(this.disposeControls)this.disposeControls();if(this.cancelResize)this.cancelResize();this.resizeObserver.disconnect();this.detailObserver?.disconnect();this.rowHeights?.clear();this.rowOffsets=null;this.restoreHeight();this.host.classList.remove("cx-data-grid","cx-chrome","cx-phone","cx-has-selection","cx-scroll-left","cx-scroll-right","cx-grid-awaiting","cx-pins");this.grid.removeEventListener("wheel",this.onScaledWheel);this.grid.removeEventListener("touchstart",this.onScaledTouchStart);this.grid.removeEventListener("touchmove",this.onScaledTouchMove);this.grid.removeEventListener("touchend",this.onScaledTouchEnd);this.grid.removeEventListener("touchcancel",this.onScaledTouchEnd);this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.pendingPages.clear();this.rendered.clear();this.pool.length=0;this.toolbar.remove();this.grid.remove();this.notice.remove();this.live.remove();this.querySummary?.remove();if(this.pager)this.pager.remove();this.statusBar?.remove();this.groupBar?.remove();this.statusAggregateController?.abort();this.host.removeAttribute("data-cx-ready");this.host.removeAttribute("data-canopyx-mounted")}}
756
+ destroy(){if(this.destroyed)return;this.writeStoredState(this.getState());this.destroyed=true;this.queryEpoch++;this.lifetime.abort();this.dataLifetime.abort();this.focusOrigin=null;for(const row of[...this.rendered.values(),...this.pool])disposeRowHostCells(row);if(this.rafId)cancelAnimationFrame(this.rafId);clearTimeout(this.searchTimer);this.searchTimer=null;clearTimeout(this.stateTimer);if(this.disposeControls)this.disposeControls();if(this.cancelResize)this.cancelResize();this.resizeObserver.disconnect();this.detailObserver?.disconnect();this.rowHeights?.clear();this.rowOffsets=null;this.restoreHeight();this.host.classList.remove("cx-data-grid","cx-chrome","cx-phone","cx-has-selection","cx-scroll-left","cx-scroll-right","cx-grid-awaiting","cx-pins");this.grid.removeEventListener("wheel",this.onScaledWheel);this.grid.removeEventListener("touchstart",this.onScaledTouchStart);this.grid.removeEventListener("touchmove",this.onScaledTouchMove);this.grid.removeEventListener("touchend",this.onScaledTouchEnd);this.grid.removeEventListener("touchcancel",this.onScaledTouchEnd);this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.pendingPages.clear();this.rendered.clear();this.pool.length=0;this.toolbar.remove();this.grid.remove();this.notice.remove();this.live.remove();this.querySummary?.remove();if(this.pager)this.pager.remove();this.statusBar?.remove();this.groupBar?.remove();this.statusAggregateController?.abort();this.host.removeAttribute("data-cx-ready");this.host.removeAttribute("data-canopyx-mounted")}}
756
757
  Object.assign(DataGrid.prototype,ROW_SCROLLING,ROW_DOM_ORDER,ROW_VIEWPORT,ROW_HELPERS);Object.assign(DataGrid.prototype,{requestPage(query,signal){return this.runGridHook(signal=>this.source.query(query,{signal}),signal)},storePage(page){const rows=page.items.map((item,i)=>({key:item.id,h:item,_ri:page.offset+i,hpx:this.rowH}));const incoming=new Map(rows.map(row=>[row.key,row._ri]));for(const cached of this.rowCache.values())if(incoming.has(cached.key)&&incoming.get(cached.key)!==cached._ri)
757
758
  throw new Error("CanopyX: inconsistent grid row identity.");for(const row of rows){const existing=this.rowCache.get(row._ri);if(existing&&existing.key!==row.key)throw new Error("CanopyX: inconsistent grid row identity.")}
758
759
  const retained=rows.map(row=>this.rowCache.get(row._ri)||row);let restoreFocus=false;for(const row of retained){const placeholder=this.placeholders.get(row._ri);if(this.focused===placeholder){const element=this.rendered.get(placeholder);restoreFocus=!!(element&&element.contains(document.activeElement));this.focused=row}
@@ -794,10 +795,11 @@ this.pendingNavigation===navigation&&this.rowCache.get(index)===initial&&this.fo
794
795
  this.rendered.get(initial)?.isConnected)return;const navigationTop=this.logicalTop();const row=await this.waitForRow(index,epoch);if(this.destroyed||epoch!==this.queryEpoch||this.pendingQuery)throw new DOMException("Grid navigation was superseded.","AbortError");if(this.pendingNavigation!==navigation)return;if(focus&&(!ownsFocus||!this.canvas.contains(document.activeElement)||!this.focused||this.focused._ri!==index))return;const currentColumn=columnId?this.visibleColumns().findIndex(item=>item.id===columnId):-1;if(!focus||currentColumn<0||!row||row.status){if(this.logicalTop()===navigationTop)this.setFocus(row,focus)}else{const currentTop=this.logicalTop();this.focusCell(row,currentColumn,control);if(currentTop!==navigationTop){this.setLogicalTop(currentTop);this.render()}}}finally{if(this.pendingNavigation===navigation)this.pendingNavigation=null}}});Object.assign(DataGrid.prototype,{build(){const host=this.host,style=host.style,signal=this.lifetime.signal;const minimum=style.getPropertyValue("--cx-min-h"),priority=style.getPropertyPriority("--cx-min-h"),rowHeight=style.getPropertyValue("--cx-row-h"),rowPriority=style.getPropertyPriority("--cx-row-h"),density=host.getAttribute("data-cx-density"),maximum=style.maxHeight;this.restoreHeight=()=>{style.maxHeight=maximum;style.setProperty("--cx-min-h",minimum,priority);style.setProperty("--cx-row-h",rowHeight,rowPriority);if(density===null)host.removeAttribute("data-cx-density");else host.setAttribute("data-cx-density",density)};style.removeProperty("--cx-min-h");host.classList.add("cx-host","cx-data-grid","cx-chrome");host.classList.toggle("cx-row-accents",!!this.view.rowAccents);host.setAttribute("data-cx-density",this.view.density||"default");if(!host.hasAttribute("data-cx-theme"))host.setAttribute("data-cx-theme","auto");style.setProperty("--cx-row-h",this.rowH+"px");this.toolbar=h("div","cx-toolbar");this.toolbar.hidden=this.opts.toolbar===false;if(this.view.search&&this.tools.search!==false)this.buildGridSearch();this.buildGridControls();this.buildGridChrome();this.buildQuerySummary();const grid=this.grid=h("div","cx-grid");grid.id=this.id;grid.tabIndex=-1;grid.setAttribute("role","grid");grid.setAttribute("aria-label",this.view.label);if(this.multi)grid.setAttribute("aria-multiselectable","true");this.head=h("div","cx-head");this.head.setAttribute("role","rowgroup");this.headRow=h("div","cx-hrow");this.headRow.setAttribute("role","row");this.headRow.setAttribute("aria-rowindex","1");this.head.appendChild(this.headRow);this.canvas=h("div","cx-canvas");this.canvas.setAttribute("role","rowgroup");grid.appendChild(this.head);grid.appendChild(this.canvas);this.notice=h("div","cx-grid-notice");this.notice.hidden=true;this.live=h("div","cx-live cx-sr-only");this.live.setAttribute("aria-live","polite");host.append(this.toolbar,this.querySummary);if(this.groupBar)host.appendChild(this.groupBar);host.append(this.notice,grid,this.live);this.buildPager();this.buildGridStatus();this.buildHeader();grid.addEventListener("scroll",()=>{this.scheduleRender();this.syncPinnedShadows();this.stateChanged()},{passive:true,signal});grid.addEventListener("click",event=>this.onClick(event),{signal});grid.addEventListener("pointerover",event=>this.cellTip(event),{signal});grid.addEventListener("dblclick",event=>{const element=event.target.closest(".cx-row"),row=element&&element._w;if(row&&!row.status&&!event.target.closest("a,button,input,select,textarea,[contenteditable]")&&!this.clickAction(element))
795
796
  this.activateRow(row,false)},{signal});grid.addEventListener("keydown",event=>this.onKey(event),{signal});if(this.view.dragRows){grid.addEventListener("dragstart",event=>this.gridDragStart(event),{signal});grid.addEventListener("dragend",()=>{GRID_DRAG.item=null},{signal})}
796
797
  this.canvas.addEventListener("focusin",event=>{const element=event.target.closest(".cx-row");if(element&&element._w&&this.pendingNavigation&&this.pendingQuery&&element._w._ri!==this.pendingNavigation.index)
797
- this.pendingNavigation=null;if(element&&element._w&&this.focused!==element._w){this.pendingNavigation=null;this.focused=element._w;this.scheduleRender()}},{signal});document.addEventListener("focusin",event=>{if(this.pendingNavigation&&this.pendingNavigation.focus&&!this.canvas.contains(event.target))this.pendingNavigation=null},{signal});this.canvas.addEventListener("focusout",event=>this.settleCell(event.relatedTarget),{signal});this.sized=this.hasGridSize();this.resizeObserver=new ResizeObserver(()=>requestAnimationFrame(()=>{if(this.destroyed)return;if(!grid.clientWidth||!grid.checkVisibility()){this.sized=false;return}
798
+ this.pendingNavigation=null;if(element&&element._w&&this.focused!==element._w){this.pendingNavigation=null;this.focused=element._w;this.scheduleRender()}},{signal});document.addEventListener("focusin",event=>{if(this.pendingNavigation&&this.pendingNavigation.focus&&!this.canvas.contains(event.target))this.pendingNavigation=null;if(this.focusOrigin&&event.target!==this.focusOrigin)this.focusOrigin=null},{signal,capture:true});document.addEventListener("focusout",event=>{if(event.target===this.focusOrigin)this.focusOrigin=null},{signal,capture:true});this.canvas.addEventListener("focusout",event=>this.settleCell(event.relatedTarget),{signal});this.sized=this.hasGridSize();grid.style.opacity="0";let resizeFrame;signal.addEventListener("abort",()=>cancelAnimationFrame(resizeFrame),{once:true});this.resizeObserver=new ResizeObserver(entries=>{const size=entries.find(entry=>entry.target===grid);if(size)this.fitContentWidth=size.contentRect.width;if(size&&!size.contentRect.width)grid.style.opacity="0";const resize=()=>{if(this.destroyed)return;if(!grid.clientWidth||!grid.checkVisibility()){this.sized=false;return}
798
799
  style.setProperty("--cx-min-h",(this.toolbar.hidden?0:[...host.children].reduce((height,child)=>
799
800
  height +(child===grid?0:child.offsetHeight),this.rowH*Math.min(4,Math.max(1,this.rowCount()))+ 2))+ "px");this.fitHeight();if(!(this.sized=this.hasGridSize()))return;this.applyWidths();this.updateGridPhone();this.fitHeight();this.viewportHeight=grid.clientHeight-this.head.offsetHeight;if(this.hiddenScrollTop!==undefined){const top=this.hiddenScrollTop;delete this.hiddenScrollTop;this.setLogicalTop(top)}
800
- this.scheduleRender()}));this.resizeObserver.observe(grid);this.resizeObserver.observe(this.head)},setLogicalTop(top){if(!this.hasGridSize()){this.hiddenScrollTop=top;return}
801
+ if(grid.style.opacity){this.render();grid.style.opacity=""}
802
+ else this.scheduleRender()};cancelAnimationFrame(resizeFrame);resizeFrame=requestAnimationFrame(resize)});this.resizeObserver.observe(grid);this.resizeObserver.observe(this.head)},setLogicalTop(top){if(!this.hasGridSize()){this.hiddenScrollTop=top;return}
801
803
  return ROW_SCROLLING.setLogicalTop.call(this,top)},logicalTop(){return this.hiddenScrollTop??ROW_SCROLLING.logicalTop.call(this)},hasGridSize(){return!!(this.grid.clientWidth&&this.grid.clientHeight&&this.grid.checkVisibility())},buildHeader(){const sorts=this.acceptedQuery?this.acceptedQuery.sort:[];this.sortState=sorts[0]||null;ROW_HELPERS.buildHeader.call(this);for(const cell of this.headCells){const button=cell.querySelector(".cx-sort");if(button){const label=h("span","cx-htext");setText(label,button.textContent);button.replaceChildren(label)}
802
804
  const index=sorts.findIndex(sort=>sort.column===cell.getAttribute("data-cx-column"));if(index>=0){cell.setAttribute("aria-sort",sorts.length===1?sorts[index].direction==="asc"?"ascending":"descending":"other");cell.setAttribute("data-cx-sort",sorts[index].direction);cell.setAttribute("data-cx-sort-priority",String(index+1));button.setAttribute("data-cx-sort-priority",String(index+1));if(sorts.length>1){const priority=h("sup","cx-sort-priority");setText(priority,String(index+1));button.appendChild(priority)}
803
805
  button.setAttribute("aria-label",cell.getAttribute("aria-label")+ ", "+sorts[index].direction+", " +(index+1))}}
@@ -827,7 +829,7 @@ this.total=this.rowOffsets.top(count);this.syncScrollRange(this.logicalTop());th
827
829
  if(changed){this.total=this.rowOffsets.top(this.rowOffsets.count);this.syncScrollRange(rows.rowTop(anchor.index)+ anchor.offset)}
828
830
  return changed},revealGridRow(row,index,rows=this){const top=rows.rowTop(index),viewport=Math.max(0,this.grid.clientHeight-this.head.offsetHeight);if(top<this.logicalTop())this.setLogicalTop(top);else if(top+Math.min(row.hpx,viewport)>this.logicalTop()+ viewport)this.setLogicalTop(top+Math.min(row.hpx,viewport)- viewport)},gridPageStep(row,direction,rows=this){const index=this.rowProjection?rows.indexOf(row):row._ri;if(!this.autoRows)return index+direction*Math.max(1,Math.floor((this.grid.clientHeight-this.head.offsetHeight)/ this.rowH));
829
831
  const proposed=rows.rowAt(Math.max(0,rows.rowTop(index)+ direction*(this.grid.clientHeight-this.head.offsetHeight)));return direction>0?Math.max(index+1,proposed):Math.min(index-1,proposed)}});const HEIGHT_RENDER=DataGrid.prototype.render;DataGrid.prototype.render=function(){const measured=HEIGHT_RENDER.call(this);if(this.sized&&this.total!==this.fitTotal){this.fitTotal=this.total;this.fitHeight()}
830
- return measured};DataGrid.prototype.fitHeight=function(){if(this.view.autoHeight===false||this.pendingQuery||!this.grid.clientWidth||!this.host.checkVisibility())return;const grid=this.grid,style=this.host.style,box=grid.getBoundingClientRect(),computed=getComputedStyle(grid);const borders=parseFloat(computed.borderTopWidth)+ parseFloat(computed.borderBottomWidth);const scrollbar=grid.scrollWidth>grid.clientWidth?Math.max(0,grid.offsetHeight-grid.clientHeight-borders):0;const content=[...grid.children].reduce((sum,child)=>sum+child.getBoundingClientRect().height,borders+scrollbar);if(this.fitInline===undefined){const own=getComputedStyle(this.host).maxHeight;this.fitInline=style.maxHeight;this.fitMax=own==="none"||!own?Infinity:/^-?[\d.]+px$/.test(own) ? parseFloat(own) : own;
832
+ return measured};DataGrid.prototype.fitHeight=function(){if(this.view.autoHeight===false||this.pendingQuery||!this.grid.clientWidth||!this.host.checkVisibility())return;const grid=this.grid,style=this.host.style,box=grid.getBoundingClientRect(),computed=getComputedStyle(grid);const borders=parseFloat(computed.borderTopWidth)+ parseFloat(computed.borderBottomWidth);const scrollbar=Math.max(0,grid.offsetHeight-grid.clientHeight-borders);const content=[...grid.children].reduce((sum,child)=>sum+child.getBoundingClientRect().height,borders+scrollbar);if(this.fitInline===undefined){const own=getComputedStyle(this.host).maxHeight;this.fitInline=style.maxHeight;this.fitMax=own==="none"||!own?Infinity:/^-?[\d.]+px$/.test(own) ? parseFloat(own) : own;
831
833
  }
832
834
  const hostStyle=getComputedStyle(this.host);const chrome=[...this.host.children].filter(child=>child!==grid).reduce((sum,child)=>{const css=getComputedStyle(child);return css.position==="absolute"||css.position==="fixed"?sum:sum+child.getBoundingClientRect().height},parseFloat(hostStyle.borderTopWidth)+ parseFloat(hostStyle.borderBottomWidth)+ parseFloat(hostStyle.paddingTop)+ parseFloat(hostStyle.paddingBottom));const height=Math.ceil(Math.max(this.host.getBoundingClientRect().height-box.height,chrome)+ content),bound=this.fitMax;const value=!this.rowCount()?this.fitInline:typeof bound==="number"?Math.min(bound,height)+ "px":"min("+height+"px, "+bound+")";if(this.host.style.maxHeight!==value)this.host.style.maxHeight=value};function gridPriority(value){return["essential","normal","optional"].includes(value)||Number.isInteger(value)&&value>=0&&value<=MAX_PROTOCOL_INTEGER}
833
835
  function gridRank(column){const value=column.priority;return typeof value==="number"?value:value==="optional"?10000:value==="essential"||value===undefined&&column.identity?0:5000}
@@ -849,36 +851,36 @@ if(!digits)return measured;let width=measured;for(let index=0;index<text.length;
849
851
  return width}
850
852
  function gridTextual(column){return column.kind==="text"&&!["statusStrip","sparklineBars","sparklineLine","boolean","progress"].includes(gridOptions(column).kind)}
851
853
  function gridFitColumn(column,identity){prepareWidth(column);column.identity=column===identity;column.pref=column.autoWidth?0:column.width;column.basePriority=column.priority;column.declared=column.width;column.flexWeight=typeof column.flex==="number"?column.flex:0;if(column.flexWeight)column.flex=true;else if(typeof column.flex==="number")delete column.flex}
854
+ function gridFitGrow(columns,spare,weight){let target;while(spare>.5&&columns.length){const before=spare,total=columns.reduce((sum,column)=>sum+weight(column),0);for(const column of columns){const add=Math.min(before*weight(column)/ total, column.maxW - column.renderWidth);
855
+ if(add>0){column.renderWidth +=add;spare -=add;target=column}}
856
+ columns=columns.filter(column=>column.maxW-column.renderWidth>.5)}
857
+ return{spare,target}}
852
858
  const COLUMN_FIT={fitManual(column){column.width=column.renderWidth??column.width;column.sized=true},fitSize(column,level){const need=(column.need??column.width)+(column.reserve||0);if(level===0)return column.identity&&column.priority===undefined&&!column.fixed&&!column.sized?
853
859
  Math.max(column.minW,column.headNeed||0):column.renderWidth;return Math.round(columnWidth(column,column.fixed||column.sized?column.width:!level?Math.max(need,column.pref):level>1||!gridLevel(column)?need:
854
860
  Math.min(need,Math.max(column.headNeed||0,gridTextual(column)?this.fitCh||88:column.contentNeed??need))))},fitWidths(cols,width){let total=0,target;for(const column of cols)total +=column.renderWidth=this.fitSize(column);if(width&&total>width&&this.layoutMode&&this.layoutMode!=="fit")width=total;for(const level of[2,1,0])if(width&&total>width&&(level||cols.reduce((sum,column)=>sum+column.renderWidth-this.fitSize(column,0),0)>=total-width))
855
861
  total=width+this.fitShrink(cols,total-width,level);if(width&&total<width)target=this.fitSpare(cols.filter(column=>!column.fixed&&!column.sized),width-total);total=0;for(const column of cols)total +=column.renderWidth=Math.floor(column.renderWidth);if(width>total&&!(target?.renderWidth<target?.maxW))for(const column of cols)
856
862
  if(!column.fixed&&!column.sized&&column.renderWidth<column.maxW&&gridTextual(column))target=column;if(target)target.renderWidth +=Math.min(width-total,target.maxW-target.renderWidth);return cols.map(column=>column.renderWidth)},fitShrink(cols,excess,level){for(const group of[cols.filter(column=>column.flex),cols.filter(gridTextual),cols]){if(excess<=0.5)break;const floor=new Map(group.map(column=>[column,Math.min(column.renderWidth,this.fitSize(column,level))]));const cut=width=>group.reduce((sum,column)=>sum+Math.max(0,column.renderWidth-Math.max(width,floor.get(column))),0);let low=0,high=Math.max(0,...group.map(column=>column.renderWidth));for(let step=0;step<24;step++){const middle=(low+high)/ 2; if (cut(middle) >= excess) low = middle; else high = middle; }
857
863
  excess -=cut(low);for(const column of group)column.renderWidth=Math.min(column.renderWidth,Math.max(low,floor.get(column)))}
858
- return excess},fitSpare(columns,spare){let target,flex=columns.filter(column=>column.flex&&column.flexWeight);const grow=(column,limit)=>{const add=column?Math.min(spare,Math.min(limit,column.maxW)- column.renderWidth):0;if(add>0){column.renderWidth +=add;spare -=add;target=column}};for(let before=0;spare>0.5&&flex.length&&before!==spare;){const weight=flex.reduce((sum,column)=>sum+column.flexWeight,0);before=spare;for(const column of flex)grow(column,column.renderWidth+before*column.flexWeight / weight);
859
- flex=flex.filter(column=>column.maxW-column.renderWidth>0.5)}
860
- const identity=columns.find(column=>column.identity),widest=columns.filter(column=>!column.identity&&
864
+ return excess},fitSpare(columns,spare){let target;({spare,target}=gridFitGrow(columns.filter(column=>column.flex&&column.flexWeight),spare,column=>column.flexWeight));const grow=(column,limit)=>{const add=column?Math.min(spare,Math.min(limit,column.maxW)- column.renderWidth):0;if(add>0){column.renderWidth +=add;spare -=add;target=column}};const identity=columns.find(column=>column.identity),widest=columns.filter(column=>!column.identity&&
861
865
  gridTextual(column)&&gridLevel(column)===1).sort((a,b)=>b.need-a.need)[0];grow(identity,420);if(identity&&widest)grow(widest,widest.renderWidth+spare*widest.need / (widest.need + identity.need));
862
- grow(identity,Infinity);grow(widest,Infinity);return target},fitHide(shown,width,phone,size=column=>this.fitSize(column,1)){let total=0,remaining=shown.length;const order=(a,b)=>gridLevel(b)- gridLevel(a)||gridRank(b)- gridRank(a)||shown.indexOf(b)- shown.indexOf(a),identity=phone&&shown.find(column=>column.identity);const hide=(column,pinned)=>!column.sized&&!column.alwaysVisible&&(column.pin==="none")!==pinned&&!(phone&&column.identity)&&gridLevel(column)>!phone;for(const column of this.columns)column.fitHidden=false;if(this.layoutMode&&this.layoutMode!=="fit")return;for(const column of shown)total +=size(column);for(const column of shown.filter(column=>hide(column,false)).sort(order))
866
+ grow(identity,Infinity);grow(widest,Infinity);return target},fitHide(shown,width,phone,size=column=>this.fitSize(column,1),level=!phone){let total=0,remaining=shown.length;const order=(a,b)=>gridLevel(b)- gridLevel(a)||gridRank(b)- gridRank(a)||shown.indexOf(b)- shown.indexOf(a),identity=phone&&shown.find(column=>column.identity);const hide=(column,pinned)=>!column.fixed&&!column.sized&&!column.alwaysVisible&&(column.pin==="none")!==pinned&&!(phone&&column.identity)&&gridLevel(column)>level;for(const column of this.columns)column.fitHidden=false;if(this.layoutMode&&this.layoutMode!=="fit")return;for(const column of shown)total +=size(column);for(const column of shown.filter(column=>hide(column,false)).sort(order))
863
867
  if(total>width&&remaining>1){column.fitHidden=true;total -=size(column);remaining--}
864
868
  if(identity&&!identity.fixed&&!identity.sized)total +=Math.min(identity.need??identity.width,(identity.indentNeed||0)+ 2*(this.fitCh||88))+(identity.reserve||0)- size(identity);if(identity)for(const column of shown.filter(column=>hide(column,true)).sort(order))
865
869
  if(total>width){column.fitHidden=true;total -=size(column)}}};const FIT={};for(const name of["applyWidths","newCell","setColumnWidth","startResize","buildHeader","visibleColumns"])FIT[name]=DataGrid.prototype[name];function gridFitPrepare(grid){const identity=grid.columns.find(column=>column.rowHeader)||grid.columns[0];for(const column of grid.columns){gridFitColumn(column,identity);column.pin??=column.pinned===undefined?column.identity?"left":"none":column.pinned||"none"}
866
870
  grid.columns=["left","none","right"].flatMap(side=>grid.columns.filter(column=>column.pin===side))}
867
- Object.assign(DataGrid.prototype,COLUMN_FIT,{fitHide(shown,width,phone){COLUMN_FIT.fitHide.call(this,shown,width,phone);if(!phone||(this.layoutMode||"fit")!=="fit")return;const identity=shown.find(column=>column.identity);if(!identity)return;for(const column of shown)if(!column.identity&&gridLevel(column)>0&&!column.alwaysVisible&&!column.fixed&&!column.sized)column.fitHidden=true;const peers=shown.filter(column=>!column.fitHidden&&!column.identity&&gridLevel(column)===0);if(identity.fixed||identity.sized)return;const primary=columnWidth(identity,Math.min(Math.max(identity.contentNeed||0,identity.pref||0,identity.controlNeed||0),Math.max(160,width*.65)));if(primary+peers.reduce((sum,column)=>sum+this.fitSize(column,2),0)>width)
868
- for(const column of peers)if(!column.fixed&&!column.sized&&!column.alwaysVisible)column.fitHidden=true},fitSize(column,level){if(column.fixed||column.sized)return columnWidth(column,column.width);const need=column.need??column.width,content=column.autoSize==="header"?need:column.contentNeed??need;const header=level===undefined||level===2?column.headWrapNeed||0:column.headWordNeed||column.controlNeed||0;const floor=Math.max(level===undefined?need:content,header);let width=Math.max(floor,level===undefined?column.pref||0:0);if(column.identity&&this.host.clientWidth<=640&&(this.layoutMode||"fit")==="fit"){const minimum=Math.min(content,this.grid.clientWidth*.4);width=Math.max(minimum,Math.min(width,Math.max(minimum,this.grid.clientWidth*.5)))}
869
- return Math.ceil(columnWidth(column,width))},fitShrink(cols,excess,level){const slack=cols.map(column=>Math.max(0,column.renderWidth-this.fitSize(column,level)));const total=slack.reduce((sum,width)=>sum+width,0),ratio=total?Math.min(1,excess / total) : 0;
870
- cols.forEach((column,index)=>column.renderWidth -=slack[index]*ratio);return Math.max(0,excess-total)},fitSpare(columns,spare){for(const target of["headWrapNeed","pref"]){const deficits=columns.map(column=>Math.max(0,Math.min(column[target]||0,column.maxW)- column.renderWidth));const total=deficits.reduce((sum,value)=>sum+value,0),ratio=total?Math.min(1,spare / total) : 0;
871
- columns.forEach((column,index)=>column.renderWidth +=deficits[index]*ratio);spare=Math.max(0,spare-total)}
872
- return COLUMN_FIT.fitSpare.call(this,columns,spare)},visibleColumns(){return FIT.visibleColumns.call(this).filter(column=>!column.fitHidden)},newCell(index,width,kind){return FIT.newCell.call(this,index,kind?this.cols[index].renderWidth??width:width,kind)},buildHeader(){this.fitLayout();this.fitBuilding=true;try{FIT.buildHeader.call(this)}finally{this.fitBuilding=false}
871
+ Object.assign(DataGrid.prototype,COLUMN_FIT,{fitAvailableWidth(){const grid=this.grid;if(!grid.clientWidth)return 0;const style=this.fitContentWidth===undefined&&getComputedStyle(grid);const width=style?grid.clientWidth-parseFloat(style.paddingLeft)- parseFloat(style.paddingRight)- 1:this.fitContentWidth;return Math.max(0,Math.floor(width))},fitHide(shown,width,phone){COLUMN_FIT.fitHide.call(this,shown,width,phone,undefined,0);if(!phone||(this.layoutMode||"fit")!=="fit")return;const identity=shown.find(column=>column.identity);if(!identity)return;for(const column of shown)if(!column.identity&&gridLevel(column)>0&&!column.alwaysVisible&&!column.fixed&&!column.sized)column.fitHidden=true;const peers=shown.filter(column=>!column.fitHidden&&!column.identity&&gridLevel(column)===0);if(identity.fixed||identity.sized)return;const primary=columnWidth(identity,Math.min(Math.max(identity.contentNeed||0,identity.pref||0,identity.headWrapNeed||0),Math.max(160,width*.65)));if(primary+peers.reduce((sum,column)=>sum+this.fitSize(column,2),0)>width)
872
+ for(const column of peers)if(!column.fixed&&!column.sized&&!column.alwaysVisible)column.fitHidden=true},fitSize(column,level){if(column.fixed||column.sized)return columnWidth(column,column.width);const need=column.need??column.width,content=column.autoSize==="header"?need:column.contentNeed??need;const header=column.headWrapNeed||0;const floor=Math.max(level===undefined?need:content,header);let width=Math.max(floor,level===undefined?column.pref||0:0);if(column.identity&&this.host.clientWidth<=640&&(this.layoutMode||"fit")==="fit"){const available=this.fitAvailableWidth(),minimum=Math.min(content,available*.4);width=Math.max(header,minimum,Math.min(width,Math.max(minimum,available*.5)))}
873
+ return Math.ceil(columnWidth(column,width))},fitShrink(cols,excess){const slack=cols.map(column=>Math.max(0,column.renderWidth-this.fitSize(column,1)));const total=slack.reduce((sum,width)=>sum+width,0),ratio=total?Math.min(1,excess / total) : 0;
874
+ cols.forEach((column,index)=>column.renderWidth -=slack[index]*ratio);return Math.max(0,excess-total)},fitSpare(columns,spare){const flex=columns.filter(column=>column.flexWeight);const first=gridFitGrow(flex,spare,column=>column.flexWeight);return gridFitGrow(columns.filter(gridTextual),first.spare,column=>column.contentNeed||column.need).target||first.target},visibleColumns(){return FIT.visibleColumns.call(this).filter(column=>!column.fitHidden)},newCell(index,width,kind){return FIT.newCell.call(this,index,kind?this.cols[index].renderWidth??width:width,kind)},buildHeader(){this.fitLayout();this.fitBuilding=true;try{FIT.buildHeader.call(this)}finally{this.fitBuilding=false}
873
875
  this.headCells.forEach((cell,index)=>{cell.querySelector(".cx-sort,.cx-htext").title=this.cols[index].title;cell.querySelector(".cx-resize").addEventListener("keydown",event=>{if(["ArrowLeft","ArrowRight","Home"].includes(event.key))this.fitManual(this.cols[index])},true)})},startResize(event,column){if(!this.destroyed&&!event.button){this.fitManual(column);global.addEventListener("pointerup",()=>this.emit("columnResize",{column:column.id,width:column.width}),{once:true,signal:this.lifetime.signal})}
874
- return FIT.startResize.call(this,event,column)},setColumnWidth(id,width){const column=this.columns.find(item=>item.id===id);if(column&&Number.isFinite(width))column.sized=true;FIT.setColumnWidth.call(this,id,width);this.emit("columnResize",{column:id,width:column.width})},applyWidths(){this.fitLayout();if(this.phone!==undefined)this.updateGridPhone();const visible=this.visibleColumns(),cols=this.cols,width=this.grid.clientWidth;if(cols&&(visible.length!==cols.length||visible.some((column,index)=>column!==cols[index]))){if(!this.fitBuilding){this.buildHeader();this.syncColumnControls();this.render();return}
876
+ return FIT.startResize.call(this,event,column)},setColumnWidth(id,width){const column=this.columns.find(item=>item.id===id);if(column&&Number.isFinite(width))column.sized=true;FIT.setColumnWidth.call(this,id,width);this.emit("columnResize",{column:id,width:column.width})},applyWidths(){this.fitLayout();if(this.phone!==undefined)this.updateGridPhone();const visible=this.visibleColumns(),cols=this.cols,width=this.fitAvailableWidth();if(cols&&(visible.length!==cols.length||visible.some((column,index)=>column!==cols[index]))){if(!this.fitBuilding){this.buildHeader();this.syncColumnControls();this.render();return}
875
877
  queueMicrotask(()=>this.destroyed||this.applyWidths())}
876
- FIT.applyWidths.call(this,this.fitWidths(cols,width));this.fitHeight()},fitLayout(){const width=this.grid.clientWidth,phone=this.host.clientWidth<=640,shown=FIT.visibleColumns.call(this).filter(column=>!column.responsiveHidden);if(!width)return;const key=this.pendingQuery?this.fitKey:this.queryEpoch+":"+phone;if(key!==this.fitKey||!this.fitCh){this.fitKey=key;this.fitFont=null;for(const column of this.columns){const result=this.measureGridColumn(column);column.need=result.width;column.headNeed=result.head}}
878
+ FIT.applyWidths.call(this,this.fitWidths(cols,width));if(this.headRow.matches(":hover"))this.syncColumnMenuRoom?.();this.fitHeight()},fitLayout(){const width=this.fitAvailableWidth(),phone=this.host.clientWidth<=640,shown=FIT.visibleColumns.call(this).filter(column=>!column.responsiveHidden);if(!width)return;const key=this.pendingQuery?this.fitKey:this.queryEpoch+":"+phone;if(key!==this.fitKey||!this.fitCh){this.fitKey=key;this.fitFont=null;for(const column of this.columns)column.need=this.measureGridColumn(column).width}
877
879
  for(const column of this.columns){if(!column.fixed&&!column.sized)column.width=this.fitSize(column)}
878
- this.fitHide(shown,width,phone)},measureGridColumn(column){const context=this.fitContext||=document.createElement("canvas").getContext("2d"),query=this.acceptedQuery;if(!context)throw new Error("CanopyX: no canvas context.");if(!this.fitFont){const style=getComputedStyle(this.grid),head=this.headCells?.[0]&&getComputedStyle(this.headCells[0]),family=" "+style.fontFamily;this.fitFont=[style.fontWeight+" "+style.fontSize+family,"700 12.5px"+family,(head?head.fontWeight+" "+head.fontSize:"700 13px")+ family,parseFloat(getComputedStyle(this.host).getPropertyValue("--cx-cell-px"))||12];this.fitFont.push(gridClassFont(this.grid,"p-mono"),gridClassFont(this.grid,"p-sub"),gridClassFont(this.grid,"p-pill",this.fitPill={}));this.fitNumericVariant=gridNumericVariant(this.grid);context.font=this.fitFont[0];this.fitCh=Math.ceil(gridMeasureText(context,"00000000000",this.fitNumericVariant))}
879
- const[,,headFont,pad,mono,sub,pillFont]=this.fitFont,first=column===FIT.visibleColumns.call(this)[0],options=gridOptions(column),kind=options.kind;const text=(value,font=this.fitFont[0],numeric=true)=>{context.font=font;return gridMeasureText(context,value,numeric?this.fitNumericVariant:"normal")};const move=this.view.reporting?.columnReorder?Math.max(32,Math.ceil(text("⋮⋮",headFont,false))+ 8):0;const chrome=2*pad +(this.tools.columnMenus===false?8:this.host.clientWidth<=640?52:32)+ move +
880
- (query?.sort.some(sort=>sort.column===column.id)?22:0)+(gridColumnFiltered(query,column.id)?24:0)+(first&&this.selectionControls?26:0);column.controlNeed=Math.ceil(24+chrome);const title=text(column.title,headFont,false),head=Math.ceil(Math.max(24,title)+ chrome);const words=column.title.trim().split(/\s+/);
881
- let balanced=title;for(let split=1;split<words.length;split++)balanced=Math.min(balanced,Math.max(text(words.slice(0,split).join(" "),headFont,false),text(words.slice(split).join(" "),headFont,false)));column.headWordNeed=Math.ceil(Math.max(24,...words.map(word=>text(word,headFont,false)))+ chrome);column.headWrapNeed=Math.ceil(Math.max(24,balanced)+ chrome);let values=0,sampled=0;const none=column.autoSize==="none"||column.pref&&(column.wrap||["longText","tags","list"].includes(kind));if(!none&&column.autoSize!=="header")for(const row of this.rowCache.values()){if(sampled===200)break;const cell=row.h.cells[column.id],value=cellText(cell,column,this.fmt)||"—",series=gridSeries(cell).length;const tone=gridPresenterTone(options,cellValue(cell),isCellObject(cell)&&cell.tone),quiet=options.quietTones?.includes(tone);const secondary=kind==="identifier"&&(options.secondaryColumn?cellText(row.h.cells[options.secondaryColumn],this.columns.find(item=>item.id===options.secondaryColumn),this.fmt):isCellObject(cell)&&cell.secondary);const atomic=kind==="enum"||kind==="state";const pill=kind==="enum"&&!quiet&&tone!=="success";const atomicWidth=atomic?text(value,pill?pillFont:undefined)+
880
+ this.fitHide(shown,width,phone)},measureGridColumn(column){const context=this.fitContext||=document.createElement("canvas").getContext("2d"),query=this.acceptedQuery;if(!context)throw new Error("CanopyX: no canvas context.");if(!this.fitFont){const style=getComputedStyle(this.grid),head=this.headCells?.[0]&&getComputedStyle(this.headCells[0]),family=" "+style.fontFamily;this.fitFont=[style.fontWeight+" "+style.fontSize+family,"700 12.5px"+family,(head?head.fontWeight+" "+head.fontSize:"700 13px")+ family,parseFloat(getComputedStyle(this.host).getPropertyValue("--cx-cell-px"))||12];this.fitFont.push(gridClassFont(this.grid,"p-mono"),gridClassFont(this.grid,"p-sub"),gridClassFont(this.grid,"p-pill",this.fitPill={}),gridClassFont(this.grid,"cx-sort-priority"));this.fitNumericVariant=gridNumericVariant(this.grid);context.font=this.fitFont[0];this.fitCh=Math.ceil(gridMeasureText(context,"00000000000",this.fitNumericVariant))}
881
+ const[,,headFont,pad,mono,sub,pillFont,priorityFont]=this.fitFont,first=column===FIT.visibleColumns.call(this)[0],options=gridOptions(column),kind=options.kind;const text=(value,font=this.fitFont[0],numeric=true)=>{context.font=font;return gridMeasureText(context,value,numeric?this.fitNumericVariant:"normal")};const move=this.view.reporting?.columnReorder?Math.max(32,Math.ceil(text("⋮⋮",headFont,false))+ 8):0,target=this.host.clientWidth<=640?44:24;const sort=query?.sort.findIndex(sort=>sort.column===column.id)??-1;const chrome=2*pad+8+move +(sort<0?0:22 +(query.sort.length>1?text(sort+1,priorityFont,false)+ 4:0))+
882
+ (gridColumnFiltered(query,column.id)?target:0)+(first&&this.selectionControls?target+2:0);const title=text(column.title,headFont,false),head=Math.ceil(Math.max(24,title)+ chrome);const words=column.title.trim().split(/\s+/);
883
+ let balanced=title;for(let split=1;split<words.length;split++)balanced=Math.min(balanced,Math.max(text(words.slice(0,split).join(" "),headFont,false),text(words.slice(split).join(" "),headFont,false)));column.headWrapNeed=Math.ceil(Math.max(24,balanced)+ chrome);let values=0,sampled=0;const none=column.autoSize==="none"||column.pref&&(column.wrap||["longText","tags","list"].includes(kind));if(!none&&column.autoSize!=="header")for(const row of this.rowCache.values()){if(sampled===200)break;const cell=row.h.cells[column.id],value=cellText(cell,column,this.fmt)||"—",series=gridSeries(cell).length;const tone=gridPresenterTone(options,cellValue(cell),isCellObject(cell)&&cell.tone),quiet=options.quietTones?.includes(tone);const secondary=kind==="identifier"&&(options.secondaryColumn?cellText(row.h.cells[options.secondaryColumn],this.columns.find(item=>item.id===options.secondaryColumn),this.fmt):isCellObject(cell)&&cell.secondary);const atomic=kind==="enum"||kind==="state";const pill=kind==="enum"&&!quiet&&tone!=="success";const atomicWidth=atomic?text(value,pill?pillFont:undefined)+
882
884
  (pill?this.fitPill.extra+this.fitPill.spacing*Array.from(value).length:quiet&&kind==="enum"?16:quiet?0:kind==="state"&&tone!=="success"?15:13):0;values=Math.max(values,atomic?atomicWidth:kind==="identifier"?Math.min(420,text(value,options.mono?mono:undefined,!options.mono)+(secondary?6+text(secondary,sub):0)):kind==="statusStrip"?Math.min(series,12)*7:kind==="sparklineBars"?Math.min(series,12)*6:kind==="sparklineLine"?80:kind==="boolean"?16:
883
885
  Math.min(kind==="longText"||kind==="tags"||kind==="list"||column.wrap?320:420,text(value))+
884
886
  (kind==="progress"?80:kind==="tags"||kind==="list"?48:0));sampled++}
@@ -919,8 +921,8 @@ if(error){this.notice.classList.add("cx-banner");const message=h("div"),title=h(
919
921
  if(this.snapshot&&(this.cursor?this.cursorWindow.end===this.pageOffset:this.snapshot.matched===0)){const query=this.acceptedQuery,active=!!query.search||gridFilterCount(query)>0,title=h("h4"),reason=h("p"),actions=h("div","acts");this.host.classList.add("cx-grid-awaiting");this.notice.classList.add("cx-state");this.host.insertBefore(this.notice,this.grid.nextSibling);title.setAttribute("aria-level","2");setText(title,fill(active?this.labels.gridNoMatches:this.labels.gridEmpty,{noun:this.noun}));setText(reason,active?fill(this.labels.gridNoMatchesReason,{search:query.search||"—",count:gridFilterCount(query)}):this.view.emptyReason||this.labels.gridEmptyReason);if(active)actions.appendChild(gridButton(this.labels.gridClearAll,()=>this.setQuery(gridQueryStart(this.queryForChange(true),{search:"",filters:[],filterGroup:undefined})).catch(()=>{})));this.notice.append(title,reason,actions);this.notice.hidden=false;setText(this.live,title.textContent+" "+reason.textContent)}else if(text){setText(this.notice,text);this.notice.hidden=false}},paintGridSkeleton(element,row){if(row.status!=="loading"){element._skeleton?.remove();element._skeleton=null;return}
920
922
  row.loadingAt??=performance.now();const wait=150-(performance.now()-row.loadingAt);if(wait>0){if(!this.gridSkeletonTimer)this.gridSkeletonTimer=setTimeout(()=>{this.gridSkeletonTimer=null;if(!this.destroyed){this.version++;this.scheduleRender()}},wait);return}
921
923
  const cell=element._cells[0].cell;element._cells[0].text.data="";if(element._skeleton?.isConnected)return;const skeleton=element._skeleton=h("span","cx-skel");skeleton.setAttribute("aria-hidden","true");for(const column of this.cols){const span=h("span"),bar=h("i");span.style.width=column.renderWidth+"px";span.appendChild(bar);skeleton.appendChild(span)}cell.appendChild(skeleton)},buildGridStatus(){if(!this.view.statusBar)return;this.statusBar=h("div","cx-grid-status");this.statusCount=h("span");this.statusAggregates=h("span","agg");this.statusBar.setAttribute("role","status");this.statusBar.append(this.statusCount,this.statusAggregates);this.host.appendChild(this.statusBar)},async syncGridStatus(){if(!this.statusBar)return;const count=this.querySelection?this.querySelection.matched==null?null:Math.max(0,this.querySelection.matched-this.selectionExcluded.size):this.selected.size;const number=numberFormat(this.lang);gridCountLabel(this.statusCount,this.labels.gridStatusCount,{count:this.snapshot?.matched==null?"—":number.format(this.snapshot.matched),noun:this.noun,selected:count==null?"—":number.format(count)});const columns=this.columns.filter(column=>column.aggregatable&&column.exportable!==false),key=JSON.stringify([this.queryEpoch,this.snapshot?.revision,count,[...this.selected],this.querySelection?.query,[...(this.selectionExcluded||[])],columns.map(column=>column.id)]);if(key===this.statusAggregateKey)return;this.statusAggregateKey=key;this.statusAggregateController?.abort();this.statusAggregates.replaceChildren();if(!columns.length||count===0||!this.acceptedQuery)return;try{await loadGridFilterEditor();if(!this.destroyed&&this.statusAggregateKey===key)await this.calculateGridAggregates(columns)}
922
- catch(error){if(!this.destroyed&&this.statusAggregateKey===key)setText(this.statusAggregates,this.labels.gridNoData)}}});Object.assign(DataGrid.prototype,{setFocus(row,focus){this.pendingNavigation=null;if(!row||this.indexOf(row)<0||this.destroyed)return;this.focused=row;this.revealGridRow(row,row._ri);if(this.render()){this.revealGridRow(row,row._ri);this.render()}
923
- if(focus){const element=this.rendered.get(row);if(element)element.focus({preventScroll:true})}},onClick(event){const element=event.target.closest(".cx-row"),row=element&&element._w,link=event.target.closest("a.p-link");if(row&&link&&!this.emit("link",{id:row.key,row:gridFreeze(JSON.parse(JSON.stringify(row.h))),href:link.href,column:this.visibleColumns()[this.rowCells(element).findIndex(cell=>cell.contains(link))]?.id}))event.preventDefault();if(!row||event.defaultPrevented||event.target.closest("a,button,input,select,textarea,[contenteditable]"))return;this.setFocus(row,true);if(row.status){if(row.status==="error")this.retry().catch(()=>{});return}
924
+ catch(error){if(!this.destroyed&&this.statusAggregateKey===key)setText(this.statusAggregates,this.labels.gridNoData)}}});Object.assign(DataGrid.prototype,{setFocus(row,focus){this.pendingNavigation=null;if(!row||this.indexOf(row)<0||this.destroyed)return;if(focus)this.focusOrigin=null;this.focused=row;this.revealGridRow(row,row._ri);if(this.render()){this.revealGridRow(row,row._ri);this.render()}
925
+ if(focus){const element=this.rendered.get(row);if(this.hasGridSize()&&element)element.focus({preventScroll:true});else{this.focusOrigin=document.activeElement;this.scheduleRender()}}},onClick(event){const element=event.target.closest(".cx-row"),row=element&&element._w,link=event.target.closest("a.p-link");if(row&&link&&!this.emit("link",{id:row.key,row:gridFreeze(JSON.parse(JSON.stringify(row.h))),href:link.href,column:this.visibleColumns()[this.rowCells(element).findIndex(cell=>cell.contains(link))]?.id}))event.preventDefault();if(!row||event.defaultPrevented||event.target.closest("a,button,input,select,textarea,[contenteditable]"))return;this.setFocus(row,true);if(row.status){if(row.status==="error")this.retry().catch(()=>{});return}
924
926
  const action=event.detail<2&&this.clickAction(element);if(action)this.activateRow(row,false,action!==true&&action,event)},clickAction(element){return this.view.rowAction==="link"&&element.querySelector("a[href]")||this.phone||this.view.rowAction==="details"},activateRow(row,keyboard,link,event={}){if(this.emit("rowActivate",{id:row.key,row:gridFreeze(JSON.parse(JSON.stringify(row.h))),keyboard}))link?
925
927
  link.dispatchEvent(new MouseEvent("click",{bubbles:true,cancelable:true,ctrlKey:event.ctrlKey,metaKey:event.metaKey,shiftKey:event.shiftKey})):
926
928
  Promise.resolve().then(()=>this.openDetails(row.key)).catch(error=>this.emit("error",{error}))},onKey(event){const element=event.target.closest(".cx-row"),row=element&&element._w;if(!row||event.defaultPrevented||event.isComposing||event.altKey)return;const cells=this.rowCells(element),navigation=this.pendingNavigation;const pendingPage=navigation&&navigation.focus&&navigation.epoch===this.queryEpoch&&this.pendingQuery&&
@@ -1002,9 +1004,9 @@ Object.assign(gridButton(this.labels.gridPrint,()=>global.print()),{className:"c
1002
1004
  this.host.addEventListener("canopyx:select",()=>this.syncGridChrome(),{signal});this.syncGridChrome();signal.addEventListener("abort",()=>{this.headerSelectionFlyout?.dispose();this.headerMenusLifetime?.abort();this.closeGridPopover(false)},{once:true})},syncGridChrome(){if(!this.selectionBar)return;const count=this.querySelection?this.querySelection.matched===null?null:Math.max(0,this.querySelection.matched-this.selectionExcluded.size):this.selected.size;const selected=count===null||count>0;this.selectionBar.hidden=!selected;this.toolbarSeparator.hidden=!selected;this.host.classList.toggle("cx-has-selection",selected);gridCountLabel(this.selectedCount,count===null?this.labels.gridSelectionQueryUnknown:this.labels.gridSelectionCount,{count:numberFormat(this.lang).format(count),excluded:String(this.selectionExcluded?.size||0)});const filterSummary=this.toolbar.querySelector(".cx-grid-filters > summary"),active=gridFilterCount(this.acceptedQuery);if(filterSummary){filterSummary.classList.toggle("active",!!active);filterSummary.querySelector(".badge")?.remove();if(active){const badge=h("span","badge");setText(badge,String(active));filterSummary.appendChild(badge)}}
1003
1005
  for(const button of this.selectionBar.querySelectorAll("button"))button.disabled=!!this.pendingQuery||!this.acceptedQuery;this.syncGridStatus?.()},updateGridPhone(){const phone=this.host.clientWidth<=640,autoRows=this.authoredAutoRows||phone&&(this.layoutMode||"fit")==="fit";this.host.classList.toggle("cx-phone",phone);if(phone===this.phone&&autoRows===this.autoRows)return;const anchor=this.gridRowAnchor();const changedRows=autoRows!==this.autoRows;this.phone=phone;this.autoRows=autoRows;if(changedRows){this.rowOffsets=null;this.rowHeights?.clear()}
1004
1006
  this.rowWidthShape=null;if(!this.autoRows&&!this.rowProjection){const bounds=this.rowBounds();this.total=Math.max(0,bounds.last-bounds.first+1)*this.rowH;this.syncScrollRange(this.rowTop(anchor.index)+ Math.min(anchor.offset,this.rowH-1))}
1005
- this.version++;this.scheduleRender();this.placeMenus(phone);this.syncPinnedShadows()},syncPinnedShadows(){if(!this.pinnedLeftWidth&&!this.pinnedRightWidth)return;this.host.classList.toggle("cx-scroll-left",this.grid.scrollLeft>0);this.host.classList.toggle("cx-scroll-right",this.grid.scrollLeft+this.grid.clientWidth<this.grid.scrollWidth-1)},gridAction(action,act){if(!action||typeof action.label!=="string"||typeof action.run!=="function")throw new Error("CanopyX: actions need a label and handler.");return gridButton(action.label,()=>act(()=>this.runGridHook(signal=>action.run({query:this.getQuery(),signal,api:this.host.canopyx}),this.dataLifetime.signal)))}});function gridColumnFiltered(query,id){const has=group=>group&&(group.filters.some(item=>item.column===id)||group.groups.some(has));return!!query&&(query.filters.some(item=>item.column===id)||!!has(query.filterGroup))}
1007
+ this.version++;this.scheduleRender();this.placeMenus(phone);this.syncPinnedShadows()},syncPinnedShadows(){const overflow=this.grid.scrollWidth>this.grid.clientWidth+1,pins=overflow&&(this.pinnedLeftWidth||this.pinnedRightWidth);this.host.classList.toggle("cx-scroll-x",overflow);this.host.classList.toggle("cx-scroll-left",!!pins&&this.grid.scrollLeft>0);this.host.classList.toggle("cx-scroll-right",!!pins&&this.grid.scrollLeft+this.grid.clientWidth<this.grid.scrollWidth-1)},gridAction(action,act){if(!action||typeof action.label!=="string"||typeof action.run!=="function")throw new Error("CanopyX: actions need a label and handler.");return gridButton(action.label,()=>act(()=>this.runGridHook(signal=>action.run({query:this.getQuery(),signal,api:this.host.canopyx}),this.dataLifetime.signal)))}});function gridColumnFiltered(query,id){const has=group=>group&&(group.filters.some(item=>item.column===id)||group.groups.some(has));return!!query&&(query.filters.some(item=>item.column===id)||!!has(query.filterGroup))}
1006
1008
  function gridColumnProjection(query,id){const project=group=>{if(!group)return undefined;const filters=group.filters.filter(item=>item.column!==id),groups=group.groups.map(project);if(group.operator==="or"&&(filters.length!==group.filters.length||groups.some(child=>!child)))return undefined;const children=groups.filter(Boolean);return filters.length||children.length?{operator:group.operator,filters,groups:children}:undefined};return{...query,filters:(query.filters||[]).filter(item=>item.column!==id),filterGroup:project(query.filterGroup)}}
1007
- Object.assign(DataGrid.prototype,{closeGridPopover(focus=true){const open=this.gridPopover;if(!open)return;this.gridPopover=null;open.controller.abort();open.panel.remove();open.anchor?.setAttribute("aria-expanded","false");if(focus){const anchor=open.anchor?.isConnected&&!open.anchor.hidden?open.anchor:this.headRow.querySelector('[data-cx-column-menu="'+CSS.escape(open.columnId||"")+'"]');(anchor||this.grid).focus({preventScroll:true})}},buildColumnMenus(){this.headerMenusLifetime?.abort();this.headerMenusLifetime=new AbortController();const signal=this.headerMenusLifetime.signal;for(const cell of this.headCells){const id=cell.dataset.cxColumn,column=this.columns.find(item=>item.id===id);const filter=gridDecorateButton(gridButton("",()=>this.openColumnFilter(id,filter)),"filter",true),menu=gridDecorateButton(gridButton("",()=>this.openColumnMenu(id,menu)),"more",true);filter.classList.add("cx-grid-header-filter","icon");menu.classList.add("cx-grid-column-menu","icon");filter.dataset.cxFilterColumn=id;menu.dataset.cxColumnMenu=id;filter.setAttribute("aria-label",this.labels.gridHeaderFilter?fill(this.labels.gridHeaderFilter,{column:column.title}):column.title+": "+this.labels.gridFilterColumn);menu.setAttribute("aria-label",fill(this.labels.gridColumnMenu,{column:column.title}));menu.setAttribute("aria-haspopup","menu");menu.setAttribute("aria-expanded","false");filter.dataset.cxFiltered=String(gridColumnFiltered(this.acceptedQuery,id));filter.hidden=filter.dataset.cxFiltered!=="true";menu.addEventListener("keydown",event=>{if(event.key==="ArrowDown"){event.preventDefault();this.openColumnMenu(id,menu)}},{signal});cell.insertBefore(filter,cell.querySelector(".cx-resize"));if(this.tools.columnMenus!==false)cell.insertBefore(menu,cell.querySelector(".cx-resize"))}
1009
+ Object.assign(DataGrid.prototype,{syncColumnMenuRoom(){for(const cell of this.headCells){const menu=cell.querySelector(".cx-grid-column-menu"),text=cell.querySelector(".cx-htext");if(!menu||!text)continue;const range=document.createRange();range.selectNodeContents(text);const box=menu.getBoundingClientRect(),caption=range.getBoundingClientRect();cell.classList.toggle("cx-menu-room",cell.matches(":dir(rtl)")?caption.left>=box.right+1:caption.right<=box.left-1)}},closeGridPopover(focus=true){const open=this.gridPopover;if(!open)return;this.gridPopover=null;open.controller.abort();open.panel.remove();open.anchor?.setAttribute("aria-expanded","false");if(focus){const anchor=open.anchor?.isConnected&&open.anchor.checkVisibility()?open.anchor:this.headRow.querySelector('[data-cx-column-menu="'+CSS.escape(open.columnId||"")+'"]');(anchor||this.grid).focus({preventScroll:true})}},buildColumnMenus(){this.headerMenusLifetime?.abort();this.headerMenusLifetime=new AbortController();const signal=this.headerMenusLifetime.signal;this.headRow.addEventListener("pointerenter",()=>this.syncColumnMenuRoom(),{signal});const clearTouch=()=>this.headCells.forEach(cell=>cell.classList.remove("cx-menu-touched"));document.addEventListener("pointerdown",clearTouch,{capture:true,signal});for(const cell of this.headCells){const id=cell.dataset.cxColumn,column=this.columns.find(item=>item.id===id);const filter=gridDecorateButton(gridButton("",()=>this.openColumnFilter(id,filter)),"filter",true),menu=gridDecorateButton(gridButton("",()=>this.openColumnMenu(id,menu)),"more",true);filter.classList.add("cx-grid-header-filter","icon");menu.classList.add("cx-grid-column-menu","icon");filter.dataset.cxFilterColumn=id;menu.dataset.cxColumnMenu=id;filter.setAttribute("aria-label",this.labels.gridHeaderFilter?fill(this.labels.gridHeaderFilter,{column:column.title}):column.title+": "+this.labels.gridFilterColumn);menu.setAttribute("aria-label",fill(this.labels.gridColumnMenu,{column:column.title}));menu.setAttribute("aria-haspopup","menu");menu.setAttribute("aria-expanded","false");filter.hidden=!gridColumnFiltered(this.acceptedQuery,id);filter.dataset.cxFiltered=String(!filter.hidden);menu.addEventListener("keydown",event=>{if(event.key==="ArrowDown"){event.preventDefault();this.openColumnMenu(id,menu)}},{signal});cell.insertBefore(filter,cell.querySelector(".cx-resize"));if(this.tools.columnMenus!==false)cell.insertBefore(menu,cell.querySelector(".cx-resize"));if(this.tools.columnMenus!==false){let press,timer,held=false;const cancel=()=>{global.clearTimeout(timer);press=null};document.addEventListener("pointerdown",cancel,{capture:true,signal});const open=event=>{event.preventDefault();event.stopPropagation();if(press)held=true;cancel();if(this.gridPopover?.columnId!==id||!this.gridPopover.panel.classList.contains("cx-column-menu"))this.openColumnMenu(id,menu)};cell.addEventListener("pointerdown",event=>{cancel();held=false;if(event.pointerType!=="touch")return;cell.classList.add("cx-menu-touched");if(!event.isPrimary||event.button||event.target.closest(".cx-resize,.cx-grid-column-menu,.cx-grid-header-filter,.cx-column-move"))return;press={id:event.pointerId,x:event.clientX,y:event.clientY};timer=global.setTimeout(()=>{press=null;held=true;this.openColumnMenu(id,menu)},550)},{signal});global.addEventListener("pointermove",event=>{if(press?.id===event.pointerId&&Math.hypot(event.clientX-press.x,event.clientY-press.y)>8)cancel()},{signal});for(const type of["pointerup","pointercancel"])global.addEventListener(type,event=>{if(press?.id===event.pointerId)cancel()},{signal});global.addEventListener("scroll",cancel,{capture:true,signal});cell.addEventListener("mousedown",event=>{if(held)event.preventDefault()},{signal});cell.addEventListener("click",event=>{if(held){held=false;event.preventDefault();event.stopImmediatePropagation()}},{capture:true,signal});signal.addEventListener("abort",cancel,{once:true});cell.addEventListener("contextmenu",open,{signal});cell.addEventListener("keydown",event=>{held=false;cancel();if(event.key==="ContextMenu"||event.shiftKey&&event.key==="F10")open(event)},{signal})}}
1008
1010
  if(this.gridPopover)this.gridPopover.position()}});const GRID_PIN_PREPARE=DataGrid.prototype.prepareState,GRID_PIN_WIDTHS=DataGrid.prototype.applyWidths,GRID_PIN_CELL=DataGrid.prototype.newCell;function gridPinGeometry(grid){const width=column=>column.renderWidth??column.width;const budget=Math.max(0,grid.grid.clientWidth-(grid.view.reporting?.minimumCenterWidth||128));for(const column of grid.columns)column.effectivePin="none";const pinned=grid.cols.filter(column=>column.pin==="left"),identity=grid.layoutMode==="scroll"&&grid.cols[pinned.length];const left=identity?.identity&&identity.pin==="none"?[...pinned,identity]:pinned,right=grid.cols.filter(column=>column.pin==="right").reverse();const pinOf=column=>left.includes(column)?"left":column.pin;let used=0;const stopped=[false,false];for(let index=0;index<Math.max(left.length,right.length);index++)for(const[side,column]of[left[index],right[index]].entries())if(column&&!stopped[side]){if(used+width(column)>budget)stopped[side]=true;else{used+=width(column);column.effectivePin=pinOf(column)}}
1009
1011
  let start=0,end=0;for(const column of grid.cols){column.pinOffset=column.effectivePin==="left"?start:0;if(column.effectivePin==="left")start+=width(column)}
1010
1012
  for(const column of[...grid.cols].reverse())if(column.effectivePin==="right"){column.pinOffset=end;end+=width(column)}
@@ -445,12 +445,13 @@ body .cx-host.cx-chrome{padding:0;}
445
445
  .cx-data-grid .cx-grid-chip{max-width:100%;height:var(--cx-size-24px);min-height:var(--cx-size-24px);padding:0 var(--cx-size-9px);border-radius:var(--cx-size-12px);background:var(--cx-accent-soft);font-size:var(--cx-size-13px);border:0;overflow:hidden;}
446
446
  .cx-data-grid .cx-link{height:auto;min-height:0;border:0;background:transparent;color:var(--cx-accent);font-size:var(--cx-size-13px);font-weight:600;padding:0;}
447
447
  .cx-data-grid .cx-link:hover{text-decoration:underline;}
448
- .cx-data-grid .cx-hcell[data-cx-sort="asc"] .cx-sort::after{content:"↑";font-size:var(--cx-size-14px);color:var(--cx-accent);order:1;}
449
- .cx-data-grid .cx-hcell[data-cx-sort="desc"] .cx-sort::after{content:"↓";font-size:var(--cx-size-14px);color:var(--cx-accent);order:1;}
448
+ .cx-data-grid .cx-hcell[data-cx-sort="asc"] .cx-sort::after{content:"↑";font-size:var(--cx-size-14px);color:var(--cx-accent);order:-2;}
449
+ .cx-data-grid .cx-hcell[data-cx-sort="desc"] .cx-sort::after{content:"↓";font-size:var(--cx-size-14px);color:var(--cx-accent);order:-2;}
450
450
  .cx-data-grid .cx-hcell[aria-sort="other"] .cx-sort::before{content:none;}
451
451
  .cx-data-grid .cx-hcell :is(.cx-sort,.cx-htext){min-width:0;text-overflow:ellipsis;white-space:nowrap;}
452
- .cx-data-grid .cx-hcell .cx-sort{display:flex;align-items:center;gap:4px;min-width:24px;text-align:inherit;}
453
- .cx-sort-priority{font-size:var(--cx-size-10px);color:var(--cx-accent);order:2;align-self:start;}
452
+ .cx-data-grid .cx-hcell .cx-sort{display:flex;flex:1;align-items:center;gap:4px;min-width:24px;text-align:inherit;}
453
+ .cx-data-grid .cx-hcell.cx-kind-number .cx-htext{text-align:end;}
454
+ .cx-sort-priority{font-size:var(--cx-size-10px);color:var(--cx-accent);order:-1;align-self:start;}
454
455
  .cx-data-grid .cx-auto-row{min-height:var(--cx-row-h);contain:layout style paint;}
455
456
  .cx-pins .cx-row{contain:layout style paint;}
456
457
  .cx-data-grid .cx-auto-row > .cx-cell{padding-block:var(--cx-size-7px);}
@@ -458,10 +459,7 @@ body .cx-host.cx-chrome{padding:0;}
458
459
  .cx-data-grid .cx-row[data-cx-tone]{color:var(--cx-text);}
459
460
  .cx-data-grid.cx-row-accents .cx-row[data-cx-tone] > .cx-cell:first-child::after{content:"";position:absolute;inset:0 auto 0 0;width:var(--cx-size-3px);background:var(--cx-row-tone);pointer-events:none;z-index:4;}
460
461
  .cx-data-grid.cx-row-accents .cx-row[data-cx-tone][aria-selected="true"] > .cx-cell:first-child::after{left:var(--cx-size-2px);}
461
- .cx-data-grid .cx-hcell.cx-kind-number > .cx-grid-header-filter{order:-1;}
462
- .cx-data-grid .cx-hcell.cx-kind-number > .cx-grid-column-menu{order:-2;margin-right:auto;}
463
- .cx-data-grid .cx-hcell.cx-kind-number .cx-sort::after{order:-1;}
464
- .cx-data-grid.cx-phone .cx-hcell.cx-kind-number > :is(.cx-grid-column-menu,.cx-grid-header-filter){order:0;margin-right:0;}
462
+ .cx-data-grid .cx-hcell > .cx-grid-header-filter{order:-1;}
465
463
  .cx-data-grid .cx-grid-pager{flex:none;display:flex;align-items:center;gap:var(--cx-size-12px) var(--cx-size-20px);padding:var(--cx-size-8px) var(--cx-size-12px);border-top:var(--cx-size-1px) solid var(--cx-line);font-size:var(--cx-size-13d5px);color:var(--cx-muted);}
466
464
  .cx-data-grid .cx-grid-page-range{font-variant-numeric:tabular-nums;}
467
465
  .cx-data-grid .cx-grid-pager .cx-grid-field{flex:none;flex-direction:row;align-items:center;gap:var(--cx-size-8px);white-space:nowrap;}
@@ -539,19 +537,25 @@ body .cx-host.cx-chrome{padding:0;}
539
537
  .cx-data-grid .cx-list-cell{display:flex;align-items:center;gap:var(--cx-size-6px);}
540
538
  .cx-data-grid .cx-tag-list{flex:1;min-width:0;overflow:hidden;white-space:nowrap;}
541
539
  .cx-data-grid .cx-list-cell .cx-presenter-expand{flex:none;align-self:center;}
542
- .cx-data-grid .cx-grid-column-menu{width:var(--cx-size-24px);height:var(--cx-size-24px);min-height:0;padding:0;opacity:0;border:0;background:transparent;color:var(--cx-muted);}
543
- .cx-data-grid .cx-hcell:hover .cx-grid-column-menu,.cx-data-grid .cx-hcell:focus-within .cx-grid-column-menu,.cx-data-grid.cx-phone .cx-grid-column-menu{opacity:1;}
540
+ .cx-data-grid .cx-grid-column-menu{position:absolute;inset-inline-end:var(--cx-size-4px);top:50%;transform:translateY(-50%);z-index:2;width:var(--cx-size-24px);height:var(--cx-size-24px);min-height:0;padding:0;opacity:var(--cx-menu-opacity,0);border:0;border-radius:var(--cx-size-6px);background:var(--cx-head-bg);color:var(--cx-muted);}
541
+ .cx-data-grid .cx-grid-column-menu::before{content:"";position:absolute;inset-block:0;inset-inline-end:100%;width:12px;background:var(--cx-menu-fade,none);pointer-events:none;}
542
+ @media (hover:hover){
543
+ .cx-data-grid :where(.cx-hrow:hover) .cx-hcell.cx-menu-room{--cx-menu-opacity:.4;}
544
+ .cx-data-grid .cx-hrow .cx-hcell:hover{--cx-menu-opacity:1;--cx-menu-fade:var(--cx-menu-gradient);}
545
+ }
546
+ .cx-data-grid .cx-hcell:is(:focus-within,.cx-menu-touched){--cx-menu-opacity:1;--cx-menu-fade:var(--cx-menu-gradient);}
544
547
  .cx-data-grid .cx-grid-header-filter{width:var(--cx-size-20px);height:var(--cx-size-24px);min-height:0;padding:0;border:0;background:transparent;color:var(--cx-accent);}
545
548
  .cx-grid-header-filter svg{fill:currentColor;}
546
549
  .cx-grid-column-menu svg{rotate:90deg;}
547
- .cx-data-grid [data-cx-pin]{position:sticky;z-index:2;background:var(--cx-surface);}
550
+ .cx-data-grid [data-cx-pin]{z-index:2;background:var(--cx-surface);}
551
+ .cx-data-grid.cx-scroll-x [data-cx-pin]{position:sticky;}
552
+ .cx-data-grid:not(.cx-scroll-x) [data-cx-pin]{inset:auto!important;}
548
553
  .cx-data-grid .cx-hcell[data-cx-pin]{z-index:5;background:var(--cx-head-bg);}
549
- .cx-data-grid .cx-row[aria-selected="true"] [data-cx-pin]{background:var(--cx-selected-bg);}
550
- .cx-data-grid .cx-row:hover:not([aria-selected="true"]) [data-cx-pin]{background:var(--cx-hover-bg);}
554
+ .cx-data-grid .cx-row[aria-selected="true"] [data-cx-pin]{background:linear-gradient(var(--cx-selected-bg),var(--cx-selected-bg)),var(--cx-surface);}
555
+ .cx-data-grid .cx-row:hover:not([aria-selected="true"]) [data-cx-pin]{background:linear-gradient(var(--cx-hover-bg),var(--cx-hover-bg)),var(--cx-surface);}
551
556
  .cx-data-grid .cx-cell[data-cx-pin]{box-shadow:none;}
552
557
  .cx-data-grid.cx-scroll-left [data-cx-pin="left"].cx-pin-edge{box-shadow:var(--cx-size-4px) 0 var(--cx-size-8px) color-mix(in srgb,var(--cx-shadow-ink) 8%,transparent);}
553
558
  .cx-data-grid.cx-scroll-right [data-cx-pin="right"].cx-pin-edge{box-shadow:var(--cx-size-neg-4px) 0 var(--cx-size-8px) color-mix(in srgb,var(--cx-shadow-ink) 8%,transparent);}
554
- @media (any-pointer:coarse){.cx-data-grid .cx-grid-column-menu{opacity:1;}.cx-data-grid .cx-hcell.cx-kind-number > :is(.cx-grid-column-menu,.cx-grid-header-filter){order:0;margin-right:0;}}
555
559
  .cx-state{display:grid;justify-items:center;gap:var(--cx-size-6px);padding:var(--cx-size-44px) var(--cx-size-16px);text-align:center;}
556
560
  .cx-state h4{margin:0;font-size:var(--cx-size-16px);}
557
561
  .cx-state p{color:var(--cx-muted);font-size:var(--cx-size-14px);max-width:var(--cx-size-46ch);}
@@ -589,7 +593,8 @@ body .cx-host.cx-chrome{padding:0;}
589
593
  .cx-grid-overlay :focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-2px);}
590
594
  .cx-grid-overlay [data-cx-pointer-focus]:focus-visible{outline:none;}
591
595
  .cx-data-grid .cx-hrow{height:auto;min-height:var(--cx-head-h);align-items:stretch;}
592
- .cx-data-grid .cx-hcell{padding-block:6px;}
596
+ .cx-data-grid .cx-hcell{padding-block:6px;--cx-menu-gradient:linear-gradient(to right,transparent,var(--cx-head-bg));}
597
+ .cx-data-grid .cx-hcell:dir(rtl){--cx-menu-gradient:linear-gradient(to left,transparent,var(--cx-head-bg));}
593
598
  .cx-data-grid .cx-hcell .cx-htext{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;white-space:normal;line-height:1.25;text-wrap:balance;overflow:hidden;max-height:2.5em;}
594
599
  .cx-data-grid .cx-htext{flex:1;min-width:0;}
595
600
  .cx-data-grid.cx-phone .cx-phone-primary{align-items:flex-start;}