@evotecit/canopyx 0.3.11 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CanopyX.Html/Assets/canopyx-export.js +8 -4
- package/CanopyX.Html/Assets/canopyx-facets.js +6 -6
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +10 -8
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +48 -34
- package/CanopyX.Html/Assets/canopyx-grid.js +48 -34
- package/CanopyX.Html/Assets/canopyx-grouping.js +2 -2
- package/CanopyX.Html/Assets/canopyx-interactive.js +27 -12
- package/CanopyX.Html/Assets/canopyx-layouts.css +1 -1
- package/CanopyX.Html/Assets/canopyx-layouts.js +3 -3
- package/CanopyX.Html/Assets/canopyx-module.mjs +27 -12
- package/CanopyX.Html/Assets/canopyx-presenters.js +11 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.js +12 -10
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +52 -38
- package/CanopyX.Html/Assets/canopyx-reporting.js +52 -38
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +1 -0
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +3 -2
- package/CanopyX.Html/Assets/canopyx.js +27 -12
- package/JavaScript/grid.d.ts +3 -1
- package/JavaScript/hosts.d.ts +11 -0
- package/JavaScript/protocol.d.ts +13 -0
- package/JavaScript/records.d.ts +2 -0
- package/README.md +2 -2
- package/package.json +3 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"9203882f58fa0155",install(context){if(installed.has(context.EXPORT_IMPL))return;const{DataGrid,EXPORT_IMPL,h,setText,gridButton,gridOption,fill,numberFormat,gridOperationActive,formatting,gridQuery,validateGridCursorPage,validateGridPage,GRID_REPORTING,gridFreeze,cellValue,cellText,isCellObject,exportTimeout,exportFormat,EXPORT_FORMATS,gridExportField}=context;function saveExport(blob,name){const url=URL.createObjectURL(blob),link=h("a");link.href=url;link.download=String(name).replace(/[\\/:*?"<>|\x00-\x1f\x7f\u200e\u200f\u202a-\u202e\u2066-\u2069]/g, "_").replace(/^[. ]+|[. ]+$/g, "_");
|
|
2
2
|
document.body.appendChild(link);link.click();link.remove();setTimeout(()=>URL.revokeObjectURL(url),30000)}
|
|
3
3
|
Object.assign(EXPORT_IMPL,{async run(grid,id,options,capture,format){if(!format)throw new Error("CanopyX: export format '"+id+"' is not available.");const total=capture.request.recordCount,onProgress=options.onProgress;if(onProgress!==undefined&&typeof onProgress!=="function"||options.download!==undefined&&typeof options.download!=="boolean")
|
|
4
4
|
throw new Error("CanopyX: export progress is a callback and download is a boolean.");const timer=new AbortController(),clock=setTimeout(()=>timer.abort(new DOMException("Export timed out.","TimeoutError")),exportTimeout(grid,options));const signal=AbortSignal.any([grid.lifetime.signal,timer.signal,options.signal].filter(Boolean));const failure=()=>signal.reason?.name==="TimeoutError"?new Error("CanopyX: export timed out."):new DOMException("Export cancelled.","AbortError");const phases=["reading","generating","ready"];let phase=-1,done=0,read=0,stop;const report=(name,completed)=>{const next=phases.indexOf(name),count=total===null?completed:Math.min(completed,total);if(signal.aborted||next<phase||!Number.isSafeInteger(completed)||completed<0||next===phase&&count<=done)return;phase=next;done=Math.max(done,count);onProgress?.(Object.freeze({phase:name,completed:done,total}))};const stopped=new Promise((resolve,reject)=>{stop=()=>reject(failure())});signal.addEventListener("abort",stop,{once:true});try{if(signal.aborted)throw failure();const counted=Object.freeze({request:capture.request,rows:async function*(more){read=0;for await(const row of capture.rows({signal:AbortSignal.any([signal,more?.signal].filter(Boolean))})){yield row;if(++read%100===0)report("reading",read)}
|
|
@@ -11,8 +11,12 @@ throw new Error("CanopyX: incomplete cursor export.");expected.matched=page.matc
|
|
|
11
11
|
offset +=this.cursor?page.items.length:request.query.limit;if(this.cursor){cursor=page.nextCursor;if(cursor===undefined)break;if(tokens.has(cursor))throw new Error("CanopyX: cursor export repeated a token.");tokens.add(cursor)}}
|
|
12
12
|
gridOperationActive(this,signal);if(remaining.size)throw new Error("CanopyX: selected IDs absent from revision.")},async exportText(exported,maxRows=50000,delimiter,signal){if(!Number.isInteger(maxRows)||maxRows<1||maxRows>1000000)throw new Error("CanopyX: export row limit is 1 to 1000000.");const request=exported.request;if(request.recordCount>maxRows)throw new Error("CanopyX: client row limit exceeded.");const lines=[request.columns.map(column=>gridExportField(column.title,delimiter)).join(delimiter)];let count=0;for await(const row of exported.rows()){if(++count>maxRows)throw new Error("CanopyX: client row limit exceeded.");lines.push(request.columns.map(column=>{const value=request.values==="raw"?row.cells[column.id]?.value:row.cells[column.id]?.text;return gridExportField(row.level>1&&column.id===this.columns[0].id?" ".repeat(row.level-1)+(value??""):value,delimiter)}).join(delimiter))}
|
|
13
13
|
gridOperationActive(this,signal);return lines.join("\r\n")+ "\r\n"},toCsv(capture,options){return this.exportText(capture,options.maxRows,",",options.signal)},async copy(capture,options){const text=await this.exportText(capture,options.maxRows===undefined?10000:options.maxRows,"\t",options.signal);await gridWriteClipboard(this,text,options.signal);return text},copyFocused(row,cell){if(this.selected.size)return this.copy({scope:"selected"});const columns=this.visibleColumns(),element=this.rendered.get(row),index=cell&&element?this.rowCells(element).indexOf(cell):-1;const text=index>=0?gridExportField(cellText(row.h.cells[columns[index].id],columns[index],this.fmt),"\t"):
|
|
14
|
-
columns.map(column=>gridExportField(cellText(row.h.cells[column.id],column,this.fmt),"\t")).join("\t");return gridWriteClipboard(this,text)},exportToHost(capture,format,options){if(typeof format!=="string"||!format.trim()||typeof this.opts.onExport!=="function")throw new Error("CanopyX: invalid host export.");return this.runGridHook(signal=>this.opts.onExport({format,request:capture.request,capture,signal}),options.signal,exportTimeout(this,options))}});Object.assign(EXPORT_IMPL,{exportFromMenu(action){const{details,panel}=this.exportControl;this.renderGridExport(panel);details.open=true;if(!this.phone&&this.overflow)this.overflow.details.open=false;panel.cxRun(action)}});const exportMenu=function(panel){if(panel.cxRun)return panel.cxFormats();panel.replaceChildren();const reporting=!!this.view.reporting,scope=h("select"),labels=this.labels;
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
columns.map(column=>gridExportField(cellText(row.h.cells[column.id],column,this.fmt),"\t")).join("\t");return gridWriteClipboard(this,text)},exportToHost(capture,format,options){if(typeof format!=="string"||!format.trim()||typeof this.opts.onExport!=="function")throw new Error("CanopyX: invalid host export.");return this.runGridHook(signal=>this.opts.onExport({format,request:capture.request,capture,signal}),options.signal,exportTimeout(this,options))}});Object.assign(EXPORT_IMPL,{exportFromMenu(action){const{details,panel}=this.exportControl;this.renderGridExport(panel);details.open=true;if(!this.phone&&this.overflow)this.overflow.details.open=false;panel.cxRun(action)}});const exportMenu=function(panel){if(panel.cxRun)return panel.cxFormats();panel.replaceChildren();const reporting=!!this.view.reporting,scope=h("select"),labels=this.labels;const menu=this.opts.exportMenu??{};if(!menu||typeof menu!=="object"||Array.isArray(menu)||
|
|
15
|
+
Object.keys(menu).some(key=>!["csv","copy","values"].includes(key))||
|
|
16
|
+
["csv","copy"].some(key=>menu[key]!==undefined&&typeof menu[key]!=="boolean")||
|
|
17
|
+
menu.values!==undefined&&!["raw","display"].includes(menu.values))
|
|
18
|
+
throw new Error("CanopyX: exportMenu supports csv/copy booleans and raw/display values.");scope.setAttribute("aria-label",labels.gridExport);for(const[value,label]of this.exportScopes||[["filtered","gridFilteredResults"],["selected","gridSelectedRows"],["all","gridAllResults"]])
|
|
19
|
+
scope.appendChild(gridOption(value,labels[label]));const status=h("p","cx-grid-delivery-status");status.setAttribute("role","status");const meter=h("progress");meter.setAttribute("aria-label",labels.gridExport);meter.hidden=true;let operation=null,formats=[];panel.cxExportBusy=()=>operation!==null;const cancel=gridButton(labels.gridCancelExport,()=>operation?.abort());cancel.hidden=true;const progress=value=>{if(this.destroyed||!operation||operation.signal.aborted)return;setText(status,fill(value.total===null?labels.gridExportReading:labels.gridExportProgress,{completed:numberFormat(this.lang).format(value.completed),total:value.total===null?"":numberFormat(this.lang).format(value.total)}));if(value.total===null)meter.removeAttribute("value");else{meter.max=Math.max(1,value.total);meter.value=value.completed}};const canExport=()=>this.view.type!=="grid"||this.defaultExportColumns().length>0;const busy=state=>{scope.disabled=state;cancel.hidden=meter.hidden=!state;for(const button of[csv,...formats,copy,this.printButton])if(button)button.disabled=state||!canExport()};const traced=(options,onProgress)=>reporting?{...options,onProgress}:options;panel.cxRun=action=>{if(operation)return;const controller=operation=new AbortController();busy(true);meter.removeAttribute("value");setText(status,labels.loading);Promise.resolve().then(()=>action({scope:scope.value,signal:controller.signal,...(menu.values?{values:menu.values}:{})},progress)).then(()=>{if(!this.destroyed)setText(status,"")},error=>{if(!this.destroyed)setText(status,error.name==="AbortError"?labels.gridExportCancelled:error.message);if(error.name!=="AbortError")this.emit("error",{error})}).finally(()=>{if(operation===controller)operation=null;if(!this.destroyed){const returnFocus=document.activeElement===cancel;busy(false);if(returnFocus)scope.focus()}})};const csv=gridButton(labels.gridDownloadCsv,()=>panel.cxRun(async(options,onProgress)=>{const exported=this.prepareExport(traced(options,onProgress));const text=await this.exportText(exported,50000,",",options.signal);gridOperationActive(this,options.signal);saveExport(new Blob([text],{type:"text/csv;charset=utf-8"}),(exported.request.fileName||this.view.id.replace(/[^a-z0-9_-]/gi, "_")) + ".csv");
|
|
20
|
+
}));const copy=this.copy?gridButton(labels.gridCopy,()=>panel.cxRun((options,onProgress)=>this.copy(traced(options,onProgress)))):h("span");csv.hidden=menu.csv===false;copy.hidden=menu.copy===false;panel.cxFormats=()=>{if(operation)return;formats.forEach(button=>button.remove());try{formats=EXPORT_IMPL.formatsOf(this).filter(format=>format.showInMenu).map(format=>Object.assign(gridButton(format.label,()=>
|
|
17
21
|
panel.cxRun((options,onProgress)=>this.exportAs(format.id,{...options,onProgress}))),{value:format.id}))}catch(error){formats=[];this.emit("error",{error})}
|
|
18
22
|
copy.before(...formats);busy(false);if(!canExport())setText(status,labels.gridNoExportColumns);else if(status.textContent===labels.gridNoExportColumns)setText(status,"")};panel.append(scope,csv,copy,cancel,meter,status);panel.cxFormats()};DataGrid.prototype.renderGridExport=exportMenu;installed.add(context.EXPORT_IMPL)}};(global.CanopyXParts||=[]).push(["export",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"b46aac5ddb8be693",install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,fill,gridButton,gridIcon,gridQueryStart,gridQueryRows,gridColumnProjection,gridScalar,gridOrder,gridKeyCompare,gridFacetKey,cellText,foldText,numberFormat,gridCellRenderer,gridFreeze}=context;function gridColumnGroup(operator,items){const filters=[],groups=[];for(const item of items){if(typeof item==="boolean"){if(item===(operator==="or"))return item;continue}
|
|
2
2
|
if(item.operator===operator){filters.push(...item.filters);groups.push(...item.groups)}
|
|
3
3
|
else(item.groups?groups:filters).push(item)}
|
|
4
4
|
return!filters.length&&!groups.length?operator==="and":!filters.length&&groups.length===1?groups[0]:{operator,filters,groups}}
|
|
@@ -17,8 +17,8 @@ merged.label!==undefined&&(typeof merged.label!=="string"||!merged.label.trim()|
|
|
|
17
17
|
merged.target!==undefined&&!(merged.target instanceof HTMLElement))
|
|
18
18
|
throw new Error("CanopyX: invalid facet panel options.");const hosted=grid.view.source.kind!=="inline"||!!grid.opts.source;if(hosted&&typeof grid.getFacets!=="function")throw new Error("CanopyX: a hosted grid's facet panel needs the reporting runtime.");if(hosted&&facets.some(facet=>!grid.view.reporting?.facetColumns?.includes(facet.column)))
|
|
19
19
|
throw new Error("CanopyX: a hosted grid's facets must be declared reporting facet columns.");return{facets,hosted,position:merged.position||"side",open:merged.open!==false,collapsible:merged.collapsible!==false,width:merged.width||260,label:merged.label||null,target:merged.target||null}}
|
|
20
|
-
function facetDeclaredOrder(grid,column){const presenter=column.presenter,values=grid.view.reporting?.ordering?.[column.id]?.categories||
|
|
21
|
-
(presenter&&(presenter.kind==="enum"||presenter.kind==="state")&&presenter.tones?Object.keys(presenter.tones):null);return values&&values.length?new Map(values.map((value,index)=>[
|
|
20
|
+
function facetDeclaredOrder(grid,column){const presenter=column.presenter,values=column.valueOrder||grid.view.reporting?.ordering?.[column.id]?.categories||
|
|
21
|
+
(presenter&&(presenter.kind==="enum"||presenter.kind==="state")&&presenter.tones?Object.keys(presenter.tones):null);return values&&values.length?new Map(values.map((value,index)=>[gridFacetKey(value,column),index])):null}
|
|
22
22
|
function facetSelection(query,facet){let clauses;try{({clauses}=gridColumnClauses(query,facet.column))}catch(_){return{custom:true,locked:true}}
|
|
23
23
|
if(!clauses.length)return{none:true};if(facet.kind==="list"){const listed=clause=>["in","eq","isNull"].includes(clause.operator)&&!clause.groups;const items=clauses.length!==1?null:clauses[0].groups?clauses[0].operator==="or"&&!clauses[0].groups.length&&clauses[0].filters.every(listed)?clauses[0].filters:null:listed(clauses[0])?clauses:null;return items?{values:items.flatMap(clause=>clause.operator==="isNull"?[null]:clause.values)}:{custom:true}}
|
|
24
24
|
let low=null,high=null,lowOpen=false,open=false;for(const clause of clauses){if(clause.groups||clauses.length>2)return{custom:true};if((clause.operator==="ge"||clause.operator==="gt")&&low===null){low=clause.values[0];lowOpen=clause.operator==="gt"}
|
|
@@ -27,17 +27,17 @@ else return{custom:true}}
|
|
|
27
27
|
return{low,high,lowOpen,open}}
|
|
28
28
|
function facetQuery(query,facet,choice){const predicate=(operator,values=[])=>({column:facet.column,operator,values});try{if(facet.kind==="range"){const base=gridColumnClauses(query,facet.column).query;const bounds=[choice.low!=null&&predicate(choice.lowOpen?"gt":"ge",[choice.low]),choice.high!=null&&predicate(choice.open?"lt":"le",[choice.high])].filter(Boolean);return gridQueryStart(base,{filters:[...base.filters,...bounds]})}
|
|
29
29
|
const raw=choice.filter(value=>value!==null),empty=raw.length<choice.length;const items=[raw.length&&predicate("in",raw),empty&&predicate("isNull")].filter(Boolean);return gridInstallColumnClause(query,facet.column,!items.length?null:items.length===1?items[0]:{operator:"or",filters:items,groups:[]})}catch(_){return query}}
|
|
30
|
-
const facetShape=query=>query?JSON.stringify([query.search,query.searchMode,query.filters,query.filterGroup,query.revision]):"";const facetKey=
|
|
30
|
+
const facetShape=query=>query?JSON.stringify([query.search,query.searchMode,query.filters,query.filterGroup,query.revision]):"";const facetKey=gridFacetKey;function facetInlineCounts(grid,facet,query){const projection=gridColumnProjection(query,facet.column),columns=new Map(grid.view.columns.map(column=>[column.id,column]));const rows=gridQueryRows(grid.view,projection,columns,false),column=facet.def;if(facet.kind==="range"){const values=[];for(const row of rows){const value=gridScalar(row.cells[column.id],column);if(value!==null)values.push(value)}
|
|
31
31
|
return{matched:rows.length,values,complete:true}}
|
|
32
32
|
const buckets=new Map();for(const row of rows){const raw=gridScalar(row.cells[column.id],column),value=column.kind==="datetime"&&raw!==null?new Date(raw).toISOString():raw,key=facetKey(value,column);const bucket=buckets.get(key);if(bucket){bucket.count++;if(typeof value==="string"&&value<bucket.value)bucket.value=value}else buckets.set(key,{value,count:1})}
|
|
33
33
|
const items=[...buckets.values()];return{matched:rows.length,items,totalValues:items.length,truncated:false}}
|
|
34
34
|
async function facetHostedCounts(grid,facet,search,signal){const page=await grid.getFacets(facet.column,{search:search||"",includeCurrentFilter:false,limit:FACET_VALUES,signal});const column=facet.def;if(facet.kind==="range")
|
|
35
35
|
return{matched:page.matched,buckets:page.items.filter(item=>item.value!==null).map(item=>({value:gridScalar(item.value,column),count:item.count})),complete:!page.truncated};return{matched:page.matched,items:page.items.map(item=>({value:item.value,count:item.count})),totalValues:page.totalValues,truncated:page.truncated}}
|
|
36
|
-
const FACET_SEARCH_FROM=12;function facetListBody(panel,facet,body){const grid=panel.grid,search=h("input","cx-input cx-facet-search"),list=h("ul","cx-facet-values"),more=gridButton("",()=>{state.expanded=!state.expanded;draw()});const note=h("p","cx-facet-note"),state={expanded:false,search:"",counts:null,timer:0};search.type="search";search.placeholder=grid.labels.gridFacetSearch;search.setAttribute("aria-label",fill(grid.labels.gridFacetSearch,{})+ ": "+facet.label);search.hidden=true;more.classList.add("cx-facet-more");more.hidden=true;note.hidden=true;list.setAttribute("aria-label",facet.label);body.append(search,list,more,note);search.addEventListener("input",()=>{state.search=search.value;clearTimeout(state.timer);state.timer=setTimeout(()=>facet.hosted?panel.refresh([facet]):draw(),facet.hosted?250:0)});list.addEventListener("keydown",event=>{const boxes=[...list.querySelectorAll("input")],at=boxes.indexOf(document.activeElement);const next={ArrowDown:at+1,ArrowUp:at-1,Home:0,End:boxes.length-1}[event.key];if(at<0||next===undefined||!boxes[next])return;event.preventDefault();boxes.forEach(box=>{box.tabIndex=-1});boxes[next].tabIndex=0;boxes[next].focus()});const choose=(item,checked)=>{const chosen=new Map((state.chosen||[]).map(value=>[facetKey(value,facet.def),value]));if(checked)chosen.set(facetKey(item.value,facet.def),item.value);else chosen.delete(facetKey(item.value,facet.def));state.chosen=[...chosen.values()];panel.apply(facet,state.chosen)};function draw(){const counts=state.counts,selection=panel.selection(facet);if(!counts)return;state.chosen=selection.values||[];const chosen=new Set(state.chosen.map(value=>facetKey(value,facet.def))),focused=list.contains(document.activeElement)?document.activeElement:null;const focusKey=focused?.getAttribute("data-cx-key"),focusPosition=focused?[...list.querySelectorAll("input")].indexOf(focused):0;const needle=facet.hosted?"":foldText(state.search),locked=!!selection.locked;let items=counts.items.filter(item=>!needle||item.value!==null&&foldText(
|
|
36
|
+
const FACET_SEARCH_FROM=12;function facetListBody(panel,facet,body){const grid=panel.grid,search=h("input","cx-input cx-facet-search"),list=h("ul","cx-facet-values"),more=gridButton("",()=>{state.expanded=!state.expanded;draw()});const note=h("p","cx-facet-note"),state={expanded:false,search:"",counts:null,timer:0};search.type="search";search.placeholder=grid.labels.gridFacetSearch;search.setAttribute("aria-label",fill(grid.labels.gridFacetSearch,{})+ ": "+facet.label);search.hidden=true;more.classList.add("cx-facet-more");more.hidden=true;note.hidden=true;list.setAttribute("aria-label",facet.label);body.append(search,list,more,note);search.addEventListener("input",()=>{state.search=search.value;clearTimeout(state.timer);state.timer=setTimeout(()=>facet.hosted?panel.refresh([facet]):draw(),facet.hosted?250:0)});list.addEventListener("keydown",event=>{const boxes=[...list.querySelectorAll("input")],at=boxes.indexOf(document.activeElement);const next={ArrowDown:at+1,ArrowUp:at-1,Home:0,End:boxes.length-1}[event.key];if(at<0||next===undefined||!boxes[next])return;event.preventDefault();boxes.forEach(box=>{box.tabIndex=-1});boxes[next].tabIndex=0;boxes[next].focus()});const choose=(item,checked)=>{const chosen=new Map((state.chosen||[]).map(value=>[facetKey(value,facet.def),value]));if(checked)chosen.set(facetKey(item.value,facet.def),item.value);else chosen.delete(facetKey(item.value,facet.def));state.chosen=[...chosen.values()];panel.apply(facet,state.chosen)};function draw(){const counts=state.counts,selection=panel.selection(facet);if(!counts)return;state.chosen=selection.values||[];const chosen=new Set(state.chosen.map(value=>facetKey(value,facet.def))),focused=list.contains(document.activeElement)?document.activeElement:null;const focusKey=focused?.getAttribute("data-cx-key"),focusPosition=focused?[...list.querySelectorAll("input")].indexOf(focused):0;const needle=facet.hosted?"":foldText(state.search),locked=!!selection.locked;let items=counts.items.filter(item=>!needle||item.value!==null&&foldText(cellText(item.value,facet.def,grid.fmt)).includes(needle));if(!(facet.hosted&&state.search))for(const value of state.chosen)if(!items.some(item=>facetKey(item.value,facet.def)===facetKey(value,facet.def)))items.push({value,count:0});items.sort(facet.sort==="count"?(a,b)=>b.count-a.count||facetValueOrder(a.value,b.value,facet):(a,b)=>facetValueOrder(a.value,b.value,facet));const shown=state.expanded?items.filter((item,index)=>index<FACET_VALUES||chosen.has(facetKey(item.value,facet.def))):items.filter((item,index)=>index<facet.limit||chosen.has(facetKey(item.value,facet.def)));const retainedIndex=shown.findIndex(item=>facetKey(item.value,facet.def)===focusKey);const focusIndex=retainedIndex>=0?retainedIndex:Math.min(Math.max(0,focusPosition),Math.max(0,shown.length-1));const numbers=numberFormat(grid.lang);list.replaceChildren(...shown.map((item,index)=>{const row=h("li"),label=h("label","cx-facet-val"),box=h("input"),text=h("span","cx-facet-text"),count=h("span","cx-facet-n"),key=facetKey(item.value,facet.def);box.type="checkbox";box.checked=chosen.has(key);box.disabled=locked;box.setAttribute("data-cx-key",key);box.tabIndex=index===focusIndex?0:-1;const empty=item.value===null||item.value==="",display=empty?grid.labels.gridFacetEmptyValue:facetValueText(grid,facet,item.value,text);if(empty){setText(text,display);text.classList.add("cx-facet-empty")}
|
|
37
37
|
box.setAttribute("aria-label",fill(grid.labels.gridFacetValueCount,{value:display,count:numbers.format(item.count)}));setText(count,numbers.format(item.count));count.setAttribute("aria-hidden","true");if(!item.count)label.classList.add("cx-facet-zero");box.addEventListener("change",()=>choose(item,box.checked));label.append(box,text,count);row.appendChild(label);return row}));if(focusKey){const target=!locked&&list.querySelector('input[tabindex="0"]')||body.closest(".cx-facet")?.querySelector(".cx-facet-toggle");target?.focus({preventScroll:!locked&&retainedIndex>=0})}
|
|
38
38
|
const hidden=items.length-shown.length,capped=state.expanded&&hidden>0;more.hidden=!hidden&&!state.expanded||items.length<=facet.limit;setText(more,state.expanded?grid.labels.gridFacetShowFewer:fill(grid.labels.gridFacetShowMore,{count:numbers.format(Math.min(hidden,Math.max(1,FACET_VALUES-shown.length)))}));search.hidden=!state.search&&document.activeElement!==search&&counts.totalValues<=FACET_SEARCH_FROM;search.disabled=locked;note.hidden=!counts.truncated&&!capped;if(!note.hidden)setText(note,fill(grid.labels.gridFacetCounts,{count:numbers.format(counts.matched),shown:numbers.format(counts.truncated?counts.items.length:shown.length),total:numbers.format(counts.totalValues)}))}
|
|
39
39
|
return{draw,search:()=>state.search,update(counts){state.counts=counts;draw()}}}
|
|
40
|
-
function facetValueOrder(a,b,facet){const column=facet.def;if(a===null||b===null)return a===b?0:a===null?1:-1;if(facet.order){const at=facet.order.get(
|
|
40
|
+
function facetValueOrder(a,b,facet){const column=facet.def;if(column.valueOrder?.length)return gridKeyCompare(a,b,column,"asc");if(a===null||b===null)return a===b?0:a===null?1:-1;if(facet.order){const at=facet.order.get(facetKey(a,column))??Infinity,bt=facet.order.get(facetKey(b,column))??Infinity;if(at!==bt)return at<bt?-1:1}
|
|
41
41
|
if(column.kind!=="text")return gridOrder(gridScalar(a,column),gridScalar(b,column));if(typeof a!==typeof b)return typeof a==="boolean"?-1:1;return gridOrder(typeof a==="string"?foldText(a):a,typeof b==="string"?foldText(b):b)}
|
|
42
42
|
function facetValueText(grid,facet,value,element){const column=facet.def,options=column.presenter,text=cellText(value,column,grid.fmt)||String(value);if(options&&!["statusStrip","sparklineBars","sparklineLine","change","identifier","longText","list","tags","structured"].includes(options.kind)){try{gridCellRenderer(grid,column,options)({id:"facet",cells:{[column.id]:value}},element);return text}catch(_){element.replaceChildren()}}
|
|
43
43
|
setText(element,text);return text}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"ad3c3d19c0c13c6d",requires:["presenters"],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,gridKeyCompare,gridFacetKey,columnNumericTone,columnValueTone,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})}
|
|
@@ -12,7 +12,7 @@ const moment=gridDateInputMoment(raw,grid.local);if(!moment)throw new Error(grid
|
|
|
12
12
|
gridScalar(text,column);return text}
|
|
13
13
|
if(type==="boolean"){if(!["true","false"].includes(raw))throw new Error(grid.labels.gridInvalidFilter);return raw==="true"}
|
|
14
14
|
if(type==="mixed")throw new Error(grid.labels.gridInvalidFilter);return raw}
|
|
15
|
-
function gridMultiSelect(grid,columnOf,typeOf){const box=h("details","cx-ms"),summary=h("summary","cx-input sel"),text=h("span"),list=h("div","cx-ms-list"),search=h("input","cx-input"),values=h("div","cx-val-list"),selected=new Map(),facets=new Map(),key=value=>
|
|
15
|
+
function gridMultiSelect(grid,columnOf,typeOf){const box=h("details","cx-ms"),summary=h("summary","cx-input sel"),text=h("span"),list=h("div","cx-ms-list"),search=h("input","cx-input"),values=h("div","cx-val-list"),selected=new Map(),facets=new Map(),key=value=>gridFacetKey(value,columnOf()),name=value=>cellText(value,columnOf(),grid.fmt);let loaded;search.type="search";search.placeholder=grid.labels.gridFacetSearch;search.setAttribute("aria-label",search.placeholder);summary.appendChild(text);list.append(search,values);box.append(summary,list);const sync=()=>{setText(text,[...selected.values()].map(name).join(", ")||grid.labels.gridFacetChoose);text.classList.toggle("ph",!selected.size)};const render=()=>{const all=new Map(facets);values.replaceChildren();for(const[id,value]of selected)if(!all.has(id))all.set(id,{value});for(const[id,item]of all){const label=h("label","cx-val"),check=h("input"),count=h("span","cx-val-n"),title=name(item.value);check.type="checkbox";check.checked=selected.has(id);if(item.count)setText(count,numberFormat(grid.lang).format(item.count));label.append(check,title,count);label.hidden=!foldText(title).includes(foldText(search.value));values.appendChild(label);check.addEventListener("change",()=>{if(check.checked)selected.set(id,item.value);else selected.delete(id);sync()})}};box.addEventListener("toggle",async()=>{if(box.open&&!loaded){const column=columnOf();loaded=true;try{for(const item of(await grid.columnFacetItems(column,"")).items)if(item.value!=null&&column===columnOf())facets.set(key(item.value),item)}catch(_){}}
|
|
16
16
|
render();if(box.open)list.scrollIntoView({block:"nearest"})});search.addEventListener("input",render);search.addEventListener("keydown",event=>{if(event.key!=="Enter")return;event.preventDefault();try{box._add(gridFilterValue(grid,columnOf(),typeOf(),search.value));search.value="";render();box.dispatchEvent(new Event("change",{bubbles:true}))}catch(_){}});return Object.assign(box,{_values:selected,_sync:sync,_add(value){selected.set(key(value),value);sync()},_reset(){selected.clear();facets.clear();loaded=box.open=false;sync()}})}
|
|
17
17
|
Object.assign(DataGrid.prototype,{addGridFilter(parent,predicate){if(parent.children.length>=64)return;const row=h("fieldset","cx-grid-filter"),column=h("select"),operator=h("select"),type=h("select"),multiple=gridMultiSelect(this,()=>this.columns.find(item=>item.id===column.value),()=>type.value),multipleField=h("div","cx-grid-field cx-condition-value");multipleField.setAttribute("role","group");multipleField.setAttribute("aria-label",this.labels.gridConditionValue);let remove,input=h("input","cx-grid-filter-value"),current;const legend=h("legend","cx-sr-only");setText(legend,this.labels.gridFilters);row.appendChild(legend);for(const item of this.columns)if(item.filterable!==false)column.appendChild(gridOption(item.id,item.title));if(!column.options.length)return;if(predicate)column.value=predicate.column;for(const[value,name]of[["string","gridText"],["boolean","gridBoolean"]]){type.appendChild(gridOption(value,this.labels[name]))}
|
|
18
18
|
if(predicate&&predicate.values.length&&predicate.values.some(value=>typeof value==="boolean")){if(predicate.values.every(value=>typeof value==="boolean"))type.value="boolean";else{type.appendChild(gridOption("mixed",this.labels.gridText+" / "+this.labels.gridBoolean));type.value="mixed"}}
|
|
@@ -31,10 +31,10 @@ return!filters.length&&!groups.length?operator==="and":!filters.length&&groups.l
|
|
|
31
31
|
function gridColumnClauses(query,id){const clauses=[],has=group=>group.filters.some(item=>item.column===id)||group.groups.some(has),only=group=>group.filters.every(item=>item.column===id)&&group.groups.every(only);const remove=group=>{if(!group)return undefined;if(only(group)){clauses.push(group);return undefined}
|
|
32
32
|
if(group.operator==="or"&&has(group))throw new Error("complex");const filters=group.filters.filter(item=>{if(item.column!==id)return true;clauses.push(item);return false}),groups=group.groups.map(remove).filter(Boolean);if(!filters.length&&!groups.length)return undefined;return gridColumnGroup(group.operator,[...filters,...groups])};const filters=(query.filters||[]).filter(item=>{if(item.column!==id)return true;clauses.push(item);return false}),filterGroup=remove(query.filterGroup);return{clauses,query:{...query,filters,filterGroup}}}
|
|
33
33
|
function gridInstallColumnClause(query,id,clause){const base=gridColumnClauses(query,id).query;if(!clause)return gridQueryStart(base);if(!clause.groups)return gridQueryStart(base,{filters:[...base.filters,clause]});return gridQueryStart(base,{filterGroup:base.filterGroup?gridColumnGroup("and",[base.filterGroup,clause]):clause})}
|
|
34
|
-
Object.assign(DataGrid.prototype,{columnFacetItems(column,search="",signal){if(!column||column.filterable===false)throw new Error("CanopyX: facets require a filterable column.");if(this.view.source.kind==="host")return this.getFacets(column.id,{search,includeCurrentFilter:false,limit:200,signal});const query=gridColumnProjection(this.queryForChange(false,true),column.id),columns=new Map(this.view.columns.map(item=>[item.id,item])),rows=gridQueryRows(this.view,query,columns,false),buckets=new Map();for(const row of rows){const value=cellValue(row.cells[column.id])??null,key=
|
|
35
|
-
const items=[...buckets.values()].filter(item=>foldText(item.value).includes(foldText(search)));items.sort((a,b)=>a.value===null||b.value===null?(a.value===b.value?0:a.value===null?1:-1):
|
|
36
|
-
gridOrder(typeof a.value,typeof b.value)||gridOrder(foldText(a.value),foldText(b.value)));return{items:items.slice(0,200),matched:rows.length,totalValues:items.length,truncated:items.length>200}},openColumnFilter(id,anchor){if(!this.acceptedQuery||this.pendingQuery)return;const column=this.columns.find(item=>item.id===id);if(!column||column.filterable===false)throw new Error("CanopyX: column filters require a filterable column.");const panel=this.openGridPopover(anchor,"cx-column-filter",column.title+": "+this.labels.gridFilterColumn,id);const head=h("div","cx-pop-h"),body=h("div","cx-pop-b"),footer=h("div","cx-pop-f"),error=h("p","cx-grid-control-error");setText(head,column.title);error.setAttribute("role","status");panel.append(head,body,error,footer);let timer,clauses,draft;const signal=this.gridPopover.controller.signal,filters=this.reportingFilters;const complex=()=>{setText(body,this.labels.gridComplexFilter);if(filters)body.appendChild(gridButton(this.labels.gridEditAsText,()=>{this.closeGridPopover(false);filters.details.open=true}))};try{({clauses}=gridColumnClauses(this.queryForChange(),id))}catch(_){complex();return}
|
|
37
|
-
const flush=()=>{clearTimeout(timer);timer=null;if(signal.aborted||draft===undefined)return;try{const promise=this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,draft));draft=undefined;this.reportingFilterSubmitEpoch=this.queryEpoch;promise.then(()=>setText(error,""),failure=>setText(error,failure.message))}catch(failure){setText(error,failure.message)}};const apply=clause=>{draft=clause??null;clearTimeout(timer);timer=setTimeout(flush,200)};apply.cancel=()=>{clearTimeout(timer);draft=undefined};signal.addEventListener("abort",()=>clearTimeout(timer),{once:true});footer.append(gridButton(this.labels.gridClearColumnFilter,()=>{clearTimeout(timer);this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,null)).catch(failure=>this.emit("error",{error:failure}));this.closeGridPopover()}),gridButton(this.labels.gridDone,()=>{flush();this.closeGridPopover()}));const faceted=column.kind==="text"&&(this.view.source.kind==="inline"||this.view.reporting?.facetColumns?.includes(id)&&typeof this.source.facet==="function");if(!faceted&&clauses.some(item=>item.groups&&(item.groups.length||item.filters.length>2))||!faceted&&clauses.length>2)complex();else if(faceted)this.renderColumnValues(column,body,clauses,apply,error,signal);else this.renderColumnConditions(column,body,clauses,apply,error);this.gridPopover.position()},renderColumnValues(column,body,clauses,apply,error,signal){const search=h("input","cx-input"),all=h("input"),list=h("div","cx-val-list"),status=h("p","cx-muted");search.type="search";search.setAttribute("aria-label",this.labels.gridFilterValues);search.placeholder=this.labels.gridFilterValues;all.type="checkbox";all.checked=!clauses.length;const allLabel=h("label","cx-val-all"),allCount=h("span","cx-val-n");allCount.setAttribute("aria-hidden","true");allLabel.append(all,this.labels.gridSelectAllValues,allCount);body.append(search,allLabel,list,status);const criteria=()=>JSON.stringify([gridResultShape(gridColumnProjection(this.getQuery(),column.id)),this.snapshot.revision]),originalCriteria=criteria();this.host.addEventListener("canopyx:query",()=>{if(criteria()!==originalCriteria)this.closeGridPopover(false)},{signal});let baseline=gridColumnGroup("and",clauses),items=[],selected=new Map(),request=0,facetController;signal.addEventListener("abort",()=>facetController?.abort(),{once:true});const key=value=>
|
|
34
|
+
Object.assign(DataGrid.prototype,{columnFacetItems(column,search="",signal){if(!column||column.filterable===false)throw new Error("CanopyX: facets require a filterable column.");if(this.view.source.kind==="host")return this.getFacets(column.id,{search,includeCurrentFilter:false,limit:200,signal});const query=gridColumnProjection(this.queryForChange(false,true),column.id),columns=new Map(this.view.columns.map(item=>[item.id,item])),rows=gridQueryRows(this.view,query,columns,false),buckets=new Map();for(const row of rows){const value=cellValue(row.cells[column.id])??null,key=gridFacetKey(value,column),item=buckets.get(key);if(item)item.count++;else buckets.set(key,{value,count:1})}
|
|
35
|
+
const items=[...buckets.values()].filter(item=>foldText(cellText(item.value,column,this.fmt)).includes(foldText(search)));items.sort((a,b)=>a.value===null||b.value===null?(a.value===b.value?0:a.value===null?1:-1):
|
|
36
|
+
column.valueOrder?.length?gridKeyCompare(a.value,b.value,column,"asc"):gridOrder(typeof a.value,typeof b.value)||gridOrder(foldText(a.value),foldText(b.value)));return{items:items.slice(0,200),matched:rows.length,totalValues:items.length,truncated:items.length>200}},openColumnFilter(id,anchor){if(!this.acceptedQuery||this.pendingQuery)return;const column=this.columns.find(item=>item.id===id);if(!column||column.filterable===false)throw new Error("CanopyX: column filters require a filterable column.");const panel=this.openGridPopover(anchor,"cx-column-filter",column.title+": "+this.labels.gridFilterColumn,id);const head=h("div","cx-pop-h"),body=h("div","cx-pop-b"),footer=h("div","cx-pop-f"),error=h("p","cx-grid-control-error");setText(head,column.title);error.setAttribute("role","status");panel.append(head,body,error,footer);let timer,clauses,draft;const signal=this.gridPopover.controller.signal,filters=this.reportingFilters;const complex=()=>{setText(body,this.labels.gridComplexFilter);if(filters)body.appendChild(gridButton(this.labels.gridEditAsText,()=>{this.closeGridPopover(false);filters.details.open=true}))};try{({clauses}=gridColumnClauses(this.queryForChange(),id))}catch(_){complex();return}
|
|
37
|
+
const flush=()=>{clearTimeout(timer);timer=null;if(signal.aborted||draft===undefined)return;try{const promise=this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,draft));draft=undefined;this.reportingFilterSubmitEpoch=this.queryEpoch;promise.then(()=>setText(error,""),failure=>setText(error,failure.message))}catch(failure){setText(error,failure.message)}};const apply=clause=>{draft=clause??null;clearTimeout(timer);timer=setTimeout(flush,200)};apply.cancel=()=>{clearTimeout(timer);draft=undefined};signal.addEventListener("abort",()=>clearTimeout(timer),{once:true});footer.append(gridButton(this.labels.gridClearColumnFilter,()=>{clearTimeout(timer);this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,null)).catch(failure=>this.emit("error",{error:failure}));this.closeGridPopover()}),gridButton(this.labels.gridDone,()=>{flush();this.closeGridPopover()}));const faceted=column.kind==="text"&&(this.view.source.kind==="inline"||this.view.reporting?.facetColumns?.includes(id)&&typeof this.source.facet==="function");if(!faceted&&clauses.some(item=>item.groups&&(item.groups.length||item.filters.length>2))||!faceted&&clauses.length>2)complex();else if(faceted)this.renderColumnValues(column,body,clauses,apply,error,signal);else this.renderColumnConditions(column,body,clauses,apply,error);this.gridPopover.position()},renderColumnValues(column,body,clauses,apply,error,signal){const search=h("input","cx-input"),all=h("input"),list=h("div","cx-val-list"),status=h("p","cx-muted");search.type="search";search.setAttribute("aria-label",this.labels.gridFilterValues);search.placeholder=this.labels.gridFilterValues;all.type="checkbox";all.checked=!clauses.length;const allLabel=h("label","cx-val-all"),allCount=h("span","cx-val-n");allCount.setAttribute("aria-hidden","true");allLabel.append(all,this.labels.gridSelectAllValues,allCount);body.append(search,allLabel,list,status);const criteria=()=>JSON.stringify([gridResultShape(gridColumnProjection(this.getQuery(),column.id)),this.snapshot.revision]),originalCriteria=criteria();this.host.addEventListener("canopyx:query",()=>{if(criteria()!==originalCriteria)this.closeGridPopover(false)},{signal});let baseline=gridColumnGroup("and",clauses),items=[],selected=new Map(),request=0,facetController;signal.addEventListener("abort",()=>facetController?.abort(),{once:true});const key=value=>gridFacetKey(value,column),columns=new Map([[column.id,column]]),matchesClause=(value,clause)=>typeof clause==="boolean"?clause:gridMatchesGroup({cells:{[column.id]:value}},clause,columns),predicate=(operator,values=[])=>({column:column.id,operator,values}),matches=value=>matchesClause(value,baseline),chosen=value=>selected.get(key(value))?.checked??matches(value);const syncAll=()=>{all.checked=items.length>0&&items.every(item=>chosen(item.value));all.indeterminate=!all.checked&&items.some(item=>chosen(item.value))};const commit=()=>{const withoutEdited=clause=>{if(clause.groups)return gridColumnGroup(clause.operator,[...clause.filters,...clause.groups].map(withoutEdited));if(clause.operator==="in"){const values=clause.values.filter(value=>!selected.has(key(value)));return values.length?{...clause,values}:false}
|
|
38
38
|
if(["eq","ne","isNull","isNotNull"].includes(clause.operator)&&selected.has(key(clause.values[0]??null)))return["ne","isNotNull"].includes(clause.operator);return clause};let clause=typeof baseline==="boolean"?baseline:withoutEdited(baseline);const included=[],excluded=[];for(const item of selected.values())if(item.checked!==matchesClause(item.value,clause))(item.checked?included:excluded).push(item.value);clause=gridColumnGroup("and",[clause,...excluded.map(value=>predicate(value==null?"isNotNull":"ne",value==null?[]:[value]))]);const additions=[],raw=included.filter(value=>value!=null);if(raw.length<included.length)additions.push(predicate("isNull"));if(raw.length)additions.push(predicate("in",raw));clause=gridColumnGroup("or",[clause,...additions]);apply(clause===true?undefined:clause===false?gridColumnGroup("and",[predicate("isNull"),predicate("isNotNull")]):clause)};const render=()=>{list.replaceChildren();for(const item of items){const label=h("label","cx-val"),check=h("input"),value=h("span","cx-facet-value"),count=h("span","cx-val-n");check.type="checkbox";check.checked=chosen(item.value);const options=column.presenter;if(options&&!['statusStrip','sparklineBars','sparklineLine','change','identifier','longText','list','tags'].includes(options.kind))gridCellRenderer(this,column,options)({id:"facet",cells:{[column.id]:item.value}},value);else setText(value,cellText(item.value,column,this.fmt)||"—");setText(count,numberFormat(this.lang).format(item.count));label.append(check,value,count);list.appendChild(label);check.addEventListener("change",()=>{if(check.checked===matches(item.value))selected.delete(key(item.value));else selected.set(key(item.value),{value:item.value,checked:check.checked});syncAll();commit()})}
|
|
39
39
|
syncAll()};const load=async()=>{const generation=++request;facetController?.abort();facetController=new AbortController();setText(status,this.labels.loading);try{const page=await this.columnFacetItems(column,search.value,facetController.signal);if(signal.aborted||generation!==request)return;const previous=new Map(items.map(item=>[key(item.value),item]));for(const item of page.items)previous.set(key(item.value),item);items=[...previous.values()];render();for(const row of list.children)row.hidden=!foldText(row.querySelector('.cx-facet-value').textContent).includes(foldText(search.value));if(!search.value){search.hidden=page.totalValues<=12;setText(allCount,numberFormat(this.lang).format(page.totalValues))}
|
|
40
40
|
setText(status,page.truncated?fill(this.labels.gridFacetCounts,{count:page.matched,shown:page.items.length,total:page.totalValues}):"");this.gridPopover?.position()}catch(failure){if(!signal.aborted&&generation===request&&failure.name!=="AbortError")setText(error,failure.message)}};all.addEventListener("change",()=>{baseline=all.checked;selected.clear();render();commit()});search.addEventListener("input",load);load()}});function gridDateInput(value,local){const date=new Date(value);return Number.isFinite(date.getTime())?new Date(date.getTime()-(local?date.getTimezoneOffset()*60000:0)).toISOString().slice(0,-1):""}
|
|
@@ -62,8 +62,10 @@ finally{dialog._navigating=false;if(dialog.isConnected)steps()}};dialog._cxPaint
|
|
|
62
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)}
|
|
63
63
|
const label=h("dt"),value=h("dd");setText(label,column.title);label.setAttribute("data-cx-field",column.id);value.setAttribute("data-cx-field",column.id);this.paintDrawerValue(column,row,value,context);sections.get(name).append(label,value)}},paintDrawerValue(column,row,value,context){const cell=row.cells[column.id],object=isCellObject(cell),presenter=column.presenter||(column.wrap?{kind:"longText"}:null);if(column.render&&column.hostRenderer!==false){try{if(column.render(row,value,{column:column.id,index:this.columns.indexOf(column),signal:context.signal,onDispose:cleanup=>{if(context.signal.aborted)cleanup();else context.signal.addEventListener("abort",cleanup,{once:true})}})===true)return}
|
|
64
64
|
catch(error){this.emit("error",{error})}}
|
|
65
|
-
if(presenter){gridCellRenderer(this,{...column,renderWidth:context.width||260},presenter)(row,value);
|
|
66
|
-
|
|
65
|
+
if(presenter){gridCellRenderer(this,{...column,renderWidth:context.width||260},presenter,true,this.columns.includes(column))(row,value);const rule=columnNumericTone(column,cellValue(cell));if(rule){const label=h("span","p-sub");setText(label,rule.label);value.appendChild(label)}
|
|
66
|
+
return}
|
|
67
|
+
const text=cellText(cell,column,this.fmt),blank=object&&cellValue(cell)==null&&cell.text==="",span=h("span");applyTone(span,"cx-drawer-text"+(text||blank?"":" p-missing"),toneOf(columnValueTone(column,cell)||(object?cell.tone:null)));setText(span,text||blank?text:"—");if(object&&cell.title)span.title=cell.title;value.appendChild(span);const rule=columnNumericTone(column,cellValue(cell));if(rule){span.title=rule.label;const label=h("span","p-sub");setText(label,rule.label);value.appendChild(label)}
|
|
68
|
+
if(object)for(const badge of cell.badges||[])value.appendChild(badgeElement(badge))},drawerFields(dialog=this.recordDrawer){return dialog?[...dialog.querySelectorAll("dd[data-cx-field],.cx-record-block-b[data-cx-field]")].filter(value=>value.closest(".cx-drawer")===dialog).map(value=>{const id=value.getAttribute("data-cx-field");return{id,column:this.columns.find(column=>column.id===id)||null,term:value.previousElementSibling,value}}):[]}});DataGrid.prototype.showReportingText=function(column,text,returnFocus,rowId,mono=false){if(this.destroyed||this.pendingQuery||!this.acceptedQuery)return;this.reportingText?.close();const dialog=h("dialog","cx-host cx-grid-overlay cx-text-dialog cx-reporting-text"),head=h("div","cx-drawer-h"),title=h("h4"),content=h("pre",mono?"p-mono":"");gridOverlayTheme(this,dialog);title.id=this.id+"-text-title";title.setAttribute("aria-level","2");setText(title,column.title);dialog.setAttribute("aria-labelledby",title.id);const copy=gridDecorateButton(gridButton(this.labels.gridCopy,()=>this.writeClipboard(text).catch(error=>this.emit("error",{error}))),"copy",true);const close=gridDecorateButton(gridButton("",()=>dialog.close()),"close",true);close.classList.add("icon");close.setAttribute("aria-label",this.labels.gridCloseCell);setText(content,text);content.tabIndex=0;head.append(title,copy,close);dialog.append(head,content);document.body.appendChild(dialog);this.reportingText=dialog;const signal=this.dataLifetime.signal,abort=()=>dialog.close();signal.addEventListener("abort",abort,{once:true});dialog.addEventListener("keydown",event=>{if(event.key!=="Tab"||event.altKey||event.ctrlKey||event.metaKey)return;const controls=[content,copy,close],index=controls.indexOf(document.activeElement);event.preventDefault();controls[(index+(event.shiftKey?-1:1)+controls.length)%controls.length].focus({preventScroll:true})});dialog.addEventListener("close",()=>{signal.removeEventListener("abort",abort);dialog.remove();if(this.reportingText===dialog)this.reportingText=null;if(!this.reportingText&&!signal.aborted)gridRestoreFocus(this,returnFocus,rowId,column)},{once:true});dialog.showModal();content.focus()};DataGrid.prototype.calculateGridAggregates=async function(columns){const controller=this.statusAggregateController=new AbortController(),signal=controller.signal,owner=this.dataLifetime,abort=()=>controller.abort();owner.signal.addEventListener("abort",abort,{once:true});setText(this.statusAggregates,this.labels.loading);try{const totals=new Map(columns.map(column=>[column.id,{count:0,sum:0,min:Infinity,max:-Infinity}]));let read=0;const selected=this.prepareExport({scope:"selected",columns:columns.map(column=>column.id),signal}).rows();for await(const row of selected){if(++read>50000)throw new Error(this.labels.gridUnknownCount);for(const column of columns){const value=cellValue(row.cells[column.id]);if(typeof value!=="number")continue;const total=totals.get(column.id);total.count++;total.sum+=value;total.min=Math.min(total.min,value);total.max=Math.max(total.max,value)}}
|
|
67
69
|
if(signal.aborted||this.destroyed)return;this.statusAggregates.replaceChildren();for(const column of columns){const total=totals.get(column.id),item=h("span"),number={format:value=>numberText(value,this.lang,column.format)};setText(item,column.title+": "+(total.count?number.format(total.sum):"—"));item.title=fill(this.labels.gridSelectionAggregate,{count:total.count,sum:number.format(total.sum),average:total.count?number.format(total.sum/total.count):"—",minimum:total.count?number.format(total.min):"—",maximum:total.count?number.format(total.max):"—"});this.statusAggregates.appendChild(item);}
|
|
68
70
|
}catch(error){if(!signal.aborted&&!this.destroyed)setText(this.statusAggregates,this.labels.gridNoData)}
|
|
69
71
|
finally{owner.signal.removeEventListener("abort",abort)}};Object.assign(DataGrid.prototype,COLUMNS_MENU,{buildGridFilters:buildFilters});context.GRID_REPORTING?.installFilters?.({gridDateInput});installed.add(context.DataGrid.prototype)}};(global.CanopyXParts||=[]).push(["filter-editor",part])})(typeof window!=="undefined"?window:globalThis);
|