@evotecit/canopyx 0.3.7 → 0.3.8
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-changes.css +240 -0
- package/CanopyX.Html/Assets/canopyx-changes.js +224 -0
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +11 -6
- package/CanopyX.Html/Assets/canopyx-grid.css +2 -0
- package/CanopyX.Html/Assets/canopyx-grid.js +11 -6
- package/CanopyX.Html/Assets/canopyx-interactive.js +3 -3
- package/CanopyX.Html/Assets/canopyx-labels-de.js +74 -2
- package/CanopyX.Html/Assets/canopyx-labels-es.js +74 -2
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +74 -2
- package/CanopyX.Html/Assets/canopyx-labels-it.js +74 -2
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +74 -2
- package/CanopyX.Html/Assets/canopyx-matrix.css +16 -3
- package/CanopyX.Html/Assets/canopyx-matrix.js +21 -13
- package/CanopyX.Html/Assets/canopyx-module.mjs +3 -3
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +11 -6
- package/CanopyX.Html/Assets/canopyx-reporting.css +2 -0
- package/CanopyX.Html/Assets/canopyx-reporting.js +11 -6
- package/CanopyX.Html/Assets/canopyx.js +3 -3
- package/JavaScript/changes.d.ts +252 -0
- package/JavaScript/grid.d.ts +9 -5
- package/JavaScript/locales/de.mjs +74 -2
- package/JavaScript/locales/es.mjs +74 -2
- package/JavaScript/locales/fr.mjs +74 -2
- package/JavaScript/locales/it.mjs +74 -2
- package/JavaScript/locales/pl.mjs +74 -2
- package/JavaScript/matrix.d.ts +2 -0
- package/README.md +3 -2
- package/package.json +5 -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:"16ab7faa98c96b46",install(context){if(installed.has(context.MATRIX_IMPL))return;const{MATRIX_IMPL,h,setText,fill,plural,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}=context;const MATRIX_LABELS={matrixRows:"Rows",matrixColumns:"Columns",matrixSearch:"Find rows and columns",matrixSortBy:"Sort by",matrixGroupBy:"Group by",matrixByLabel:"Name",matrixByTotal:"Total",matrixAsListed:"As listed",matrixNoGrouping:"No groups",matrixDescending:"Descending",matrixOnlyProblems:"Only problems",matrixHideEmpty:"Hide empty rows and columns",matrixSize:"{rows} × {columns}",matrixShown:"Rows: {rows} of {totalRows}, columns: {columns} of {totalColumns}",matrixAttention:"Need attention: {count}",matrixLegend:"States",matrixFilter:"Filter",matrixClearFilters:"Clear filters",matrixNoMatches:"No rows or columns match.",matrixSelf:"Same item",matrixNoData:"No data",matrixCell:"{row} and {column}: {state}",matrixTotal:"Total",matrixItemTotal:"{item}: {count}",matrixExpandGroup:"Expand {group}",matrixCollapseGroup:"Collapse {group}",matrixGroupCount:"{count}",matrixCellCount:"Cells: {count}",matrixDetails:"Details",matrixClose:"Close",matrixValue:"Value",matrixState:"State",matrixAllClear:"Nothing needs attention",matrixShowMore:"Show more"};function matrixLabels(...sources){const labels={...MATRIX_LABELS};for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))matrixFail("labels must be an object of strings");for(const[name,text]of Object.entries(source)){if(!Object.hasOwn(labels,name)){if(/^matrix[A-Z]/.test(name)) matrixFail("there is no matrix label '" + name + "'"); continue; }
|
|
2
2
|
if(typeof text!=="string"||!/\S/.test(text)) matrixFail("label '" + name + "' must be a string with visible text");
|
|
3
3
|
labels[name]=text}}
|
|
4
4
|
return Object.freeze(labels)}
|
|
@@ -16,12 +16,14 @@ function matrixHref(value){if(typeof value!=="string"||!value.length||value.leng
|
|
|
16
16
|
const colon=value.indexOf(":"),boundary=value.search(/[/?#]/);
|
|
17
17
|
return colon<0||boundary>=0&&boundary<colon||/^(?:https?|mailto)$/i.test(value.slice(0, colon));
|
|
18
18
|
}
|
|
19
|
-
function
|
|
19
|
+
function matrixPluralText(text){if(!text.startsWith("["))return text.includes("{count}");const forms=[...text.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)];
|
|
20
|
+
return forms.reduce((sum,form)=>sum+form[0].length,0)===text.length&&forms.some(form=>form[1]==="other")&&forms.every(form=>form[2].includes("{count}"))}
|
|
21
|
+
function matrixAxis(input,what){const axis=matrixKeys(input,["title","noun","groupCount","attributes","items","groupBy","sort"],what);const attributes=[],byId=new Map();if(axis.attributes!==undefined&&(!Array.isArray(axis.attributes)||axis.attributes.length>32))matrixFail(what+" has at most 32 attributes");for(const entry of axis.attributes||[]){const attribute=matrixKeys(entry,["id","title","kind","facet"],what+" attribute");const id=matrixId(attribute.id,"an attribute id");if(id[0]==="#"||byId.has(id))matrixFail("the attribute '"+id+"' must be unique and not start with #");const kind=attribute.kind===undefined?"text":attribute.kind;if(!["text","number","datetime"].includes(kind)||attribute.facet!==undefined&&typeof attribute.facet!=="boolean")matrixFail("the attribute '"+id+"' has an unknown kind or facet");const item=Object.freeze({id,title:matrixText(attribute.title,"the title of attribute '"+id+"'",200),kind,facet:attribute.facet===true});attributes.push(item);byId.set(id,item)}
|
|
20
22
|
if(!Array.isArray(axis.items)||!axis.items.length||axis.items.length>10000)matrixFail(what+" needs 1 to 10000 items");const ids=new Map(),items=axis.items.map((entry,index)=>{const item=matrixKeys(entry,["id","label","secondary","href","values"],what+" item");const id=matrixId(item.id,"an item id");if(ids.has(id))matrixFail("the item '"+id+"' appears twice on "+what);if(item.href!==undefined&&!matrixHref(item.href))matrixFail("the link of '"+id+"' is not an http, https, mailto or relative address");const values=Object.create(null);if(item.values!==undefined){if(!matrixObject(item.values))matrixFail("the values of '"+id+"' must be an object");for(const[key,raw]of Object.entries(item.values)){const attribute=byId.get(key);if(!attribute)matrixFail("'"+id+"' has a value for the undeclared attribute '"+key+"'");const cell=matrixObject(raw)?matrixKeys(raw,["value","text"],"a value"):{value:raw};const value=cell.value??null;const fits=value===null||(attribute.kind==="number"?typeof value==="number"&&Number.isFinite(value):attribute.kind==="datetime"?
|
|
21
23
|
typeof value==="string"&&/^\d{4}-\d\d-\d\d(?:T\d\d:\d\d(?::\d\d(?:\.\d{1,7})?)?(?:Z|[+-]\d\d:\d\d)?)?$/.test(value) && Number.isFinite(matrixMoment(value)) : typeof value === "string" || typeof value === "boolean");
|
|
22
24
|
if(!fits||cell.text!==undefined&&typeof cell.text!=="string")matrixFail("the value of '"+key+"' of '"+id+"' does not fit its kind");values[key]={value,text:cell.text??null}}}
|
|
23
25
|
const result=Object.freeze({id,index,label:matrixText(item.label,"the label of '"+id+"'",200),secondary:matrixText(item.secondary,"the secondary text of '"+id+"'",200,true),href:item.href??null,values:Object.freeze(values)});ids.set(id,result);return result});if(axis.groupBy!==undefined&&!byId.has(axis.groupBy))matrixFail(what+" groups by an undeclared attribute");let sort=null;if(axis.sort!==undefined){const value=matrixKeys(axis.sort,["by","direction"],what+" sort");if(!["#label","#total"].includes(value.by)&&!byId.has(value.by)||![undefined,"asc","desc"].includes(value.direction))matrixFail(what+" sorts by an unknown key");sort={by:value.by,direction:value.direction||"asc"}}
|
|
24
|
-
if(axis.noun!==undefined)matrixText(axis.noun,what+" noun",64);return Object.freeze({title:matrixText(axis.title,what+" title",200,true),noun:axis.noun??null,attributes:Object.freeze(attributes),attributeById:byId,items:Object.freeze(items),byId:ids,groupBy:axis.groupBy??null,sort})}
|
|
26
|
+
if(axis.noun!==undefined)matrixText(axis.noun,what+" noun",64);const groupCount=matrixText(axis.groupCount,what+" group count",200,true);if(groupCount!==null&&!matrixPluralText(groupCount))matrixFail(what+" group count needs {count} in every form, and plural forms that end with [other]");return Object.freeze({title:matrixText(axis.title,what+" title",200,true),noun:axis.noun??null,groupCount,attributes:Object.freeze(attributes),attributeById:byId,items:Object.freeze(items),byId:ids,groupBy:axis.groupBy??null,sort})}
|
|
25
27
|
function matrixDocument(input){const doc=matrixKeys(input,MATRIX_KEYS,"the document");if(doc.protocol!==PROTOCOL||doc.type!=="matrix")matrixFail("it needs protocol "+PROTOCOL+" and type \"matrix\"");const id=matrixId(doc.id,"the matrix id"),label=matrixText(doc.label,"the label",200);if(doc.square!==undefined&&typeof doc.square!=="boolean")matrixFail("square must be true or false");const square=doc.square===true,rows=matrixAxis(doc.rows,"rows");if(square&&doc.columns!==undefined||!square&&(doc.columns===undefined||doc.columnTitle!==undefined))matrixFail("a matrix has columns, or is square and has none (and may have a columnTitle)");const columns=square?rows:matrixAxis(doc.columns,"columns");if(![undefined,"self","data"].includes(doc.diagonal)||doc.diagonal!==undefined&&!square)matrixFail("only a square matrix has a diagonal, self or data");if(rows.items.length*columns.items.length>1000000)matrixFail("a matrix holds at most 1000000 cells");if(!Array.isArray(doc.states)||!doc.states.length||doc.states.length>36)matrixFail("it needs 1 to 36 states");const stateIds=new Set(),states=doc.states.map((entry,index)=>{const state=matrixKeys(entry,["id","label","tone","symbol","attention"],"a state");if(typeof state.id!=="string"||!/^[A-Za-z][\w-]{0,63}$/.test(state.id) || stateIds.has(state.id)) matrixFail("states need unique ids");
|
|
26
28
|
stateIds.add(state.id);if(state.tone!==undefined&&(typeof state.tone!=="string"||!/^[a-z][a-z0-9-]{0,31}$/.test(state.tone) || /-bg$/.test(state.tone))) matrixFail("the state '" + state.id + "' has an invalid tone");
|
|
27
29
|
if(!MATRIX_SYMBOLS.includes(state.symbol)||state.attention!==undefined&&typeof state.attention!=="boolean")matrixFail("the state '"+state.id+"' needs one of the symbols");return Object.freeze({id:state.id,index,label:matrixText(state.label,"the label of state '"+state.id+"'",200),tone:state.tone||null,symbol:state.symbol,attention:state.attention===true})});const R=rows.items.length,C=columns.items.length,grid=new Uint8Array(R*C).fill(MATRIX_NONE);if(!Array.isArray(doc.cells)||doc.cells.length!==R)matrixFail("cells needs one string per row");doc.cells.forEach((line,r)=>{if(typeof line!=="string"||line.length!==C)matrixFail("each cells string needs one character per column");for(let c=0;c<C;c++){const ch=line.charCodeAt(c);if(ch===46)continue;const index=MATRIX_DIGITS.indexOf(line[c]);if(index<0||index>=states.length)matrixFail("cells name an undeclared state");grid[r*C+c]=index}});const diagonal=doc.diagonal||"self";if(square&&diagonal==="self")for(let r=0;r<R;r++)grid[r*C+r]=MATRIX_SELF;const notes=new Map();if(doc.notes!==undefined&&!Array.isArray(doc.notes))matrixFail("notes must be a list");for(const note of doc.notes||[]){if(!Array.isArray(note)||note.length<3||note.length>6||!Number.isInteger(note[0])||!Number.isInteger(note[1])||note[0]<0||note[1]<0||note[0]>=R||note[1]>=C)matrixFail("a note names no cell");const at=note[0]*C+note[1];if(grid[at]>=MATRIX_SELF||notes.has(at))matrixFail("a note names a cell without a state, or twice");const[,,value=null,text=null,title=null,details=null]=note;if(value!==null&&(typeof value!=="number"||!Number.isFinite(value)||Math.abs(value)>Number.MAX_SAFE_INTEGER))matrixFail("a note value must be a finite number");if(text!==null)matrixText(text,"a note text",64);if(title!==null)matrixText(title,"a note title",1000);if(details!==null&&(!Array.isArray(details)||details.length>16||details.some(pair=>!Array.isArray(pair)||pair.length!==2||
|
|
@@ -71,16 +73,16 @@ fitNow(){const host=this.host,style=host.style;if(this.fitInline===undefined){co
|
|
|
71
73
|
if(this.doc.autoHeight===false||Number.isNaN(this.fitMax)){if(style.maxHeight!==this.fitInline)style.maxHeight=this.fitInline;return}
|
|
72
74
|
if(!host.offsetHeight)return;const parts=[this.bar,this.legend,this.scroll,this.empty,this.cards].filter(part=>!part.hidden),hostStyle=getComputedStyle(host);let content=(parts.length-1)*(parseFloat(getComputedStyle(this.root).rowGap)||0);for(const part of parts){let height=part.getBoundingClientRect().height;if(part===this.scroll||part===this.cards)height=Math.min(height+part.scrollHeight-part.clientHeight,parseFloat(getComputedStyle(part).maxHeight)||Infinity);content +=height}
|
|
73
75
|
const chrome=["paddingTop","paddingBottom","borderTopWidth","borderBottomWidth"].reduce((sum,name)=>sum +(parseFloat(hostStyle[name])||0),0);const value=Math.min(this.fitMax,Math.ceil(chrome+content))+ "px";if(style.maxHeight!==value)style.maxHeight=value}}
|
|
74
|
-
Object.assign(MatrixView.prototype,{scheduleRender(){if(this.destroyed||this.frame)return;this.frame=requestAnimationFrame(()=>{this.frame=0;this.render()})},recycleAll(){this.lookCache=null;for(const row of this.rowsMounted.values())this.releaseRow(row);this.rowsMounted.clear();for(const map of[this.headMounted,this.footMounted,this.bandMounted]){for(const element of map.values())element.remove();map.clear()}},releaseRow(row){row.remove();row._key=null;if(this.rowPool.length<200)this.rowPool.push(row)},windows(){const scroll=this.scroll,viewH=Math.max(this.rowH,scroll.clientHeight-this.headH-this.bandH-this.footH),viewW=Math.max(this.cellW,scroll.clientWidth-this.rowHeadW-this.totalW);const rows=this.rowWindow.window(scroll.scrollTop,viewH,MATRIX_OVERSCAN),columns=this.columnWindow.window(Math.abs(scroll.scrollLeft),viewW,MATRIX_OVERSCAN);return{rows,columns,viewH,viewW}},render(){if(this.destroyed||this.scroll.hidden)return;const{rows,columns}=this.windows(),model=this.model,focus=this.focus,scroll=this.scroll,top=scroll.scrollTop;const below=scroll.scrollHeight-scroll.clientHeight-top>1;this.head.classList.toggle("cx-mx-raised",top>0);this.foot.classList.toggle("cx-mx-raised",below);const columnList=[];for(let c=columns.first;c<=columns.last;c++)columnList.push(c);if(focus.column>=0&&focus.column<model.columns.length&&(focus.column<columns.first||focus.column>columns.last))columnList.push(focus.column);const rowList=[];for(let r=rows.first;r<=rows.last;r++)rowList.push(r);if(focus.row>=0&&focus.row<model.rows.length&&(focus.row<rows.first||focus.row>rows.last))rowList.push(focus.row);this.paintHeader(columnList);this.paintBand(columns);this.placeBands();this.paintFoot(columnList);const keep=new Set();for(const r of rowList){const entry=model.rows[r];if(!entry)continue;keep.add(entry.key);let row=this.rowsMounted.get(entry.key);if(!row){row=this.rowPool.pop()||this.newRow();this.rowsMounted.set(entry.key,row);this.fillRow(row,entry,r);this.body.appendChild(row)}
|
|
76
|
+
Object.assign(MatrixView.prototype,{groupCount(axis,count){const template=(axis==="columns"?this.doc.columns:this.doc.rows).groupCount||this.labels.matrixGroupCount;return fill(plural(template,count,this.lang),{count:this.format.format(count)})},scheduleRender(){if(this.destroyed||this.frame)return;this.frame=requestAnimationFrame(()=>{this.frame=0;this.render()})},recycleAll(){this.lookCache=null;for(const row of this.rowsMounted.values())this.releaseRow(row);this.rowsMounted.clear();for(const map of[this.headMounted,this.footMounted,this.bandMounted]){for(const element of map.values())element.remove();map.clear()}},releaseRow(row){row.remove();row._key=null;if(this.rowPool.length<200)this.rowPool.push(row)},windows(){const scroll=this.scroll,viewH=Math.max(this.rowH,scroll.clientHeight-this.headH-this.bandH-this.footH),viewW=Math.max(this.cellW,scroll.clientWidth-this.rowHeadW-this.totalW);const rows=this.rowWindow.window(scroll.scrollTop,viewH,MATRIX_OVERSCAN),columns=this.columnWindow.window(Math.abs(scroll.scrollLeft),viewW,MATRIX_OVERSCAN);return{rows,columns,viewH,viewW}},render(){if(this.destroyed||this.scroll.hidden)return;const{rows,columns}=this.windows(),model=this.model,focus=this.focus,scroll=this.scroll,top=scroll.scrollTop;const below=scroll.scrollHeight-scroll.clientHeight-top>1;this.head.classList.toggle("cx-mx-raised",top>0);this.foot.classList.toggle("cx-mx-raised",below);const columnList=[];for(let c=columns.first;c<=columns.last;c++)columnList.push(c);if(focus.column>=0&&focus.column<model.columns.length&&(focus.column<columns.first||focus.column>columns.last))columnList.push(focus.column);const rowList=[];for(let r=rows.first;r<=rows.last;r++)rowList.push(r);if(focus.row>=0&&focus.row<model.rows.length&&(focus.row<rows.first||focus.row>rows.last))rowList.push(focus.row);this.paintHeader(columnList);this.paintBand(columns);this.placeBands();this.paintFoot(columnList);const keep=new Set();for(const r of rowList){const entry=model.rows[r];if(!entry)continue;keep.add(entry.key);let row=this.rowsMounted.get(entry.key);if(!row){row=this.rowPool.pop()||this.newRow();this.rowsMounted.set(entry.key,row);this.fillRow(row,entry,r);this.body.appendChild(row)}
|
|
75
77
|
else if(row._index!==r)this.placeRow(row,r);this.drawRow(row,entry,columns.first,entry.kind==="heading"?-1:columns.last)}
|
|
76
78
|
for(const[key,row]of this.rowsMounted)if(!keep.has(key)){this.releaseRow(row);this.rowsMounted.delete(key)}
|
|
77
79
|
this.syncTabStop()},newRow(){const row=h("div","cx-mx-row"),head=h("div","cx-mx-rowhead"),spacer=h("div","cx-mx-spacer"),total=h("div","cx-mx-total");row.setAttribute("role","row");head.setAttribute("role","rowheader");head.setAttribute("aria-colindex","1");total.setAttribute("role","gridcell");row.append(head,spacer,total);row._head=head;row._total=total;return row},placeRow(row,r){row._index=r;row.style.transform="translateY("+this.rowWindow.offset(r)+ "px)";row.setAttribute("aria-rowindex",String(r +(this.bandH?3:2)));row._head._r=r;row._total._r=r},fillRow(row,entry,r){row._key=entry.key;row._entry=entry;this.placeRow(row,r);row.className="cx-mx-row" +(entry.kind==="heading"?" cx-mx-heading":entry.kind==="rollup"?" cx-mx-rolledrow":entry.band?" cx-mx-member":"");const head=row._head,labels=this.labels;head.replaceChildren();head._c=-1;head.tabIndex=-1;if(entry.kind==="item"){const item=entry.item,text=item.href?h("a","cx-mx-label cx-link"):h("span","cx-mx-label");if(item.href){text.href=item.href;text.tabIndex=-1}
|
|
78
80
|
setText(text,item.label);head.appendChild(text);if(item.secondary){const sub=h("span","cx-mx-sub");setText(sub,item.secondary);head.appendChild(sub)}
|
|
79
|
-
head.title=item.secondary?item.label+" — "+item.secondary:item.label}else{const toggle=h("button","cx-mx-toggle"),open=entry.kind==="heading";toggle.type="button";toggle.tabIndex=-1;toggle.setAttribute("aria-expanded",String(open));toggle.setAttribute("aria-label",fill(open?labels.matrixCollapseGroup:labels.matrixExpandGroup,{group:entry.label}));toggle._group={axis:"rows",key:entry.group.key};const label=h("span","cx-mx-label"),count=h("span","cx-mx-sub");setText(label,entry.label);setText(count,
|
|
81
|
+
head.title=item.secondary?item.label+" — "+item.secondary:item.label}else{const toggle=h("button","cx-mx-toggle"),open=entry.kind==="heading";toggle.type="button";toggle.tabIndex=-1;toggle.setAttribute("aria-expanded",String(open));toggle.setAttribute("aria-label",fill(open?labels.matrixCollapseGroup:labels.matrixExpandGroup,{group:entry.label}));toggle._group={axis:"rows",key:entry.group.key};const label=h("span","cx-mx-label"),count=h("span","cx-mx-sub");setText(label,entry.label);setText(count,this.groupCount("rows",entry.members.length));toggle.append(label,count);head.appendChild(toggle);head.removeAttribute("title")}
|
|
80
82
|
const total=row._total;total.hidden=!this.totalW;if(this.totalW)this.paintTotal(total,entry,r,this.model.columns.length)},paintTotal(element,entry,r,c){const value=entry.total||0;setText(element,this.format.format(value));element.classList.toggle("cx-mx-zero",!value);element.setAttribute("aria-label",fill(this.labels.matrixItemTotal,{item:entry.label,count:this.format.format(value)}));element._r=r;element._c=c;element.tabIndex=-1;element.setAttribute("aria-colindex",String(this.model.columns.length+2))},paintHeader(columnList){const wanted=new Set(columnList),mounted=this.headMounted,model=this.model;for(const[c,element]of mounted)if(!wanted.has(c)||element._key!==model.columns[c]?.key){element.remove();mounted.delete(c)}
|
|
81
83
|
for(const c of columnList){const entry=model.columns[c];if(!entry||mounted.has(c))continue;const element=h("div","cx-mx-hcell" +(entry.kind==="rollup"?" cx-mx-rolledcol":""));element.setAttribute("role","columnheader");element.setAttribute("aria-colindex",String(c+2));element.style.insetInlineStart=this.rowHeadW+this.columnWindow.offset(c)+ "px";element._r=-1;element._c=c;element._key=entry.key;element.tabIndex=-1;if(entry.kind==="rollup"){const toggle=h("button","cx-mx-toggle");toggle.type="button";toggle.tabIndex=-1;toggle.setAttribute("aria-expanded","false");toggle.setAttribute("aria-label",fill(this.labels.matrixExpandGroup,{group:entry.label}));toggle._group={axis:"columns",key:entry.group.key};const text=h("span","cx-mx-vlabel");setText(text,entry.label);toggle.appendChild(text);element.appendChild(toggle)}else{const item=entry.item,text=h(item.href?"a":"span","cx-mx-vlabel" +(item.href?" cx-link":""));if(item.href){text.href=item.href;text.tabIndex=-1}
|
|
82
84
|
setText(text,item.label);element.appendChild(text);element.title=item.secondary?item.label+" — "+item.secondary:item.label}
|
|
83
|
-
mounted.set(c,element);this.headRow.appendChild(element)}},paintBand(columns){const mounted=this.bandMounted,model=this.model;if(!this.bandH)return;const seen=new Set();for(let c=columns.first;c<=columns.last&&c>=0;c++){const entry=model.columns[c];if(!entry||!entry.band||seen.has(entry.band.key))continue;seen.add(entry.band.key);if(mounted.has(entry.band.key))continue;const band=entry.band,first=model.columns.findIndex(item=>item.band===band),element=h("div","cx-mx-bcell");element._from=this.columnWindow.offset(first);element._width=band.members.length*this.cellW;element.style.insetInlineStart=this.rowHeadW+element._from+"px";element.style.width=element._width+"px";element.setAttribute("role","columnheader");element.setAttribute("aria-colindex",String(first+2));element.setAttribute("aria-colspan",String(band.members.length));const toggle=h("button","cx-mx-toggle");toggle.type="button";toggle.tabIndex=-1;toggle.setAttribute("aria-expanded","true");toggle.setAttribute("aria-label",fill(this.labels.matrixCollapseGroup,{group:band.label}));toggle._group={axis:"columns",key:band.key};const text=h("span","cx-mx-label");setText(text,band.label);toggle.appendChild(text);element.appendChild(toggle);element.title=band.label;mounted.set(band.key,element);this.band.appendChild(element)}
|
|
85
|
+
mounted.set(c,element);this.headRow.appendChild(element)}},paintBand(columns){const mounted=this.bandMounted,model=this.model;if(!this.bandH)return;const seen=new Set();for(let c=columns.first;c<=columns.last&&c>=0;c++){const entry=model.columns[c];if(!entry||!entry.band||seen.has(entry.band.key))continue;seen.add(entry.band.key);if(mounted.has(entry.band.key))continue;const band=entry.band,first=model.columns.findIndex(item=>item.band===band),element=h("div","cx-mx-bcell");element._from=this.columnWindow.offset(first);element._width=band.members.length*this.cellW;element.style.insetInlineStart=this.rowHeadW+element._from+"px";element.style.width=element._width+"px";element.setAttribute("role","columnheader");element.setAttribute("aria-colindex",String(first+2));element.setAttribute("aria-colspan",String(band.members.length));const toggle=h("button","cx-mx-toggle");toggle.type="button";toggle.tabIndex=-1;toggle.setAttribute("aria-expanded","true");toggle.setAttribute("aria-label",fill(this.labels.matrixCollapseGroup,{group:band.label}));toggle._group={axis:"columns",key:band.key};const text=h("span","cx-mx-label");setText(text,band.label);toggle.appendChild(text);element.appendChild(toggle);element.title=band.label+" · "+this.groupCount("columns",band.members.length);mounted.set(band.key,element);this.band.appendChild(element)}
|
|
84
86
|
for(const[key,element]of mounted)if(!seen.has(key)){element.remove();mounted.delete(key)}},placeBands(){if(!this.bandH)return;const start=Math.abs(this.scroll.scrollLeft),end=start+Math.max(0,this.scroll.clientWidth-this.rowHeadW-this.totalW);for(const element of this.bandMounted.values()){const from=element._from,shown=Math.min(end,from+element._width)- Math.max(start,from),toggle=element.firstChild;toggle.style.marginInlineStart=Math.max(0,start-from)+ "px";toggle.style.maxWidth=Math.max(0,shown-8)+ "px";element.classList.toggle("cx-mx-bclip",shown<Math.min(40,element._width))}},paintFoot(columnList){if(!this.footH)return;const wanted=new Set(columnList),mounted=this.footMounted,model=this.model,rows=model.rows.length +(this.bandH?3:2);this.footRow.setAttribute("aria-rowindex",String(rows));for(const[c,element]of mounted)if(!wanted.has(c)||element._key!==model.columns[c]?.key){element.remove();mounted.delete(c)}
|
|
85
87
|
for(const c of columnList){const entry=model.columns[c];if(!entry||mounted.has(c))continue;const element=h("div","cx-mx-fcell");element.setAttribute("role","gridcell");element.style.insetInlineStart=this.rowHeadW+this.columnWindow.offset(c)+ "px";this.paintTotal(element,entry,model.rows.length,c);element.setAttribute("aria-colindex",String(c+2));element._key=entry.key;mounted.set(c,element);this.footRow.appendChild(element)}
|
|
86
88
|
if(this.totalW)this.paintTotal(this.footGrand,{label:this.labels.matrixTotal,total:model.grandTotal},model.rows.length,model.columns.length);this.footHeader._r=model.rows.length;this.footHeader._c=-1}});const MATRIX_PATHS=new Map(),MATRIX_TILE=16;function matrixPath(name){if(!MATRIX_PATHS.has(name))MATRIX_PATHS.set(name,name==="dot"?null:new Path2D(MATRIX_SYMBOL_PATHS[name]));return MATRIX_PATHS.get(name)}
|
|
@@ -120,7 +122,7 @@ this.legend.replaceChildren(...items)},togglePanel(axis){if(!this.panel.hidden&&
|
|
|
120
122
|
this.panelAxis=axis;this.fillPanel(axis);this.panel.hidden=false;for(const name of MATRIX_AXES)this.axisButtons[name].setAttribute("aria-expanded",String(name===axis));this.panel.querySelector("select,input")?.focus()},closePanel(returnFocus){if(this.panel.hidden)return;this.panel.hidden=true;for(const name of MATRIX_AXES)this.axisButtons[name].setAttribute("aria-expanded","false");if(returnFocus)this.axisButtons[this.panelAxis].focus()},fillPanel(axis){const labels=this.labels,doc=this.doc,data=doc[axis==="rows"?"rows":"columns"],query=this.query,panel=this.panel,signal=this.lifetime.signal;panel.setAttribute("aria-label",this.axisTitle(axis));const focused=panel.contains(document.activeElement)?document.activeElement.dataset.cxControl:null;const field=(text,control)=>{const label=h("label","cx-mx-field"),name=h("span");setText(name,text);label.append(name,control);return label};const select=(options,value,change,key)=>{const element=h("select","cx-mx-input");element.dataset.cxControl=key;for(const[optionValue,text]of options){const option=h("option");option.value=optionValue;setText(option,text);element.appendChild(option)}
|
|
121
123
|
element.value=value;element.addEventListener("change",()=>change(element.value),{signal});return element};const sort=query.sort[axis];const sortBy=select([["",labels.matrixAsListed],["#label",labels.matrixByLabel],["#total",labels.matrixByTotal],...data.attributes.map(attribute=>[attribute.id,attribute.title])],sort?sort.by:"",value=>this.sort(axis,value||null,value==="#total"?"desc":query.sort[axis]?.direction||"asc"),"sort");const descending=h("input","cx-mx-check");descending.type="checkbox";descending.checked=!!sort&&sort.direction==="desc";descending.disabled=!sort;descending.dataset.cxControl="direction";descending.addEventListener("change",()=>this.sort(axis,query.sort[axis]?.by||null,descending.checked?"desc":"asc"),{signal});const descendingLabel=h("label","cx-mx-switch"),descendingText=h("span");setText(descendingText,labels.matrixDescending);descendingLabel.append(descending,descendingText);const groupBy=select([["",labels.matrixNoGrouping],...data.attributes.map(attribute=>[attribute.id,attribute.title])],query.group[axis]||"",value=>this.group(axis,value||null),"group");const children=[field(labels.matrixSortBy,sortBy),descendingLabel];if(data.attributes.length)children.push(field(labels.matrixGroupBy,groupBy));for(const attribute of data.attributes.filter(item=>item.facet))children.push(this.facetList(axis,data,attribute));const close=h("button","cx-mx-button");close.type="button";setText(close,labels.matrixClose);close.dataset.cxControl="close";close.addEventListener("click",()=>this.closePanel(true),{signal});children.push(close);panel.replaceChildren(...children);if(focused)panel.querySelector('[data-cx-control="'+CSS.escape(focused)+ '"]')?.focus()},facetList(axis,data,attribute){const set=h("fieldset","cx-mx-facet"),legend=h("legend"),counts=new Map(),chosen=new Set(this.query.filters[axis][attribute.id]||[]),signal=this.lifetime.signal;setText(legend,attribute.title);set.appendChild(legend);for(const item of data.items){const key=matrixValueKey(item.values[attribute.id]);if(!counts.has(key))counts.set(key,{key,text:matrixValueText(item.values[attribute.id],attribute,this.format)||"—",count:0});counts.get(key).count++}
|
|
122
124
|
for(const value of[...counts.values()].sort((a,b)=>matrixNatural(a.text,b.text)).slice(0,200)){const label=h("label","cx-mx-switch"),box=h("input","cx-mx-check"),text=h("span"),count=h("span","cx-mx-keycount");box.type="checkbox";box.checked=chosen.has(value.key);box.dataset.cxControl="facet:"+attribute.id+":"+value.key;box.addEventListener("change",()=>{const next=new Set(this.query.filters[axis][attribute.id]||[]);if(box.checked)next.add(value.key);else next.delete(value.key);this.filter(axis,attribute.id,[...next])},{signal});setText(text,value.text);setText(count,this.format.format(value.count));label.append(box,text,count);set.appendChild(label)}
|
|
123
|
-
return set}});Object.assign(MatrixView.prototype,{cellInfo(cell){const row=this.model.rows[cell._r],column=this.model.columns[cell._c];if(!row||!column)return null;const info=this.model.cell(row,column),state=info.state<MATRIX_SELF?this.doc.states[info.state]:null;return{row,column,info,state}},cellLines(data){const labels=this.labels,lines=[],note=data.info.note;const stateText=data.state?data.state.label:data.info.state===MATRIX_SELF?labels.matrixSelf:labels.matrixNoData;lines.push([labels.matrixState,stateText]);if(note&¬e.value!=null)lines.push([labels.matrixValue,this.format.format(note.value)]);if(note&¬e.text)lines.push([note.value!=null?"":labels.matrixValue,note.text]);if(data.info.rolled){lines.push(["",fill(labels.
|
|
125
|
+
return set}});Object.assign(MatrixView.prototype,{cellInfo(cell){const row=this.model.rows[cell._r],column=this.model.columns[cell._c];if(!row||!column)return null;const info=this.model.cell(row,column),state=info.state<MATRIX_SELF?this.doc.states[info.state]:null;return{row,column,info,state}},cellLines(data){const labels=this.labels,lines=[],note=data.info.note;const stateText=data.state?data.state.label:data.info.state===MATRIX_SELF?labels.matrixSelf:labels.matrixNoData;lines.push([labels.matrixState,stateText]);if(note&¬e.value!=null)lines.push([labels.matrixValue,this.format.format(note.value)]);if(note&¬e.text)lines.push([note.value!=null?"":labels.matrixValue,note.text]);if(data.info.rolled){lines.push(["",fill(labels.matrixCellCount,{count:this.format.format(data.info.members)})]);if(data.info.attention)lines.push(["",fill(labels.matrixAttention,{count:this.format.format(data.info.attention)})])}
|
|
124
126
|
if(note&¬e.title)lines.push(["",note.title]);for(const[label,value]of note&¬e.details||[])lines.push([label,value]);return lines},onPointer(event){const target=this.cellAt(event);if(target&&this.pointerCell&&target._r===this.pointerCell._r&&target._c===this.pointerCell._c)return;this.pointerCell=target;this.hoverCell(target);clearTimeout(this.tipTimer);if(!target){if(!this.tipKeyboard)this.hideTip();return}
|
|
125
127
|
this.tipTimer=setTimeout(()=>{if(!this.destroyed&&this.pointerCell===target)this.showTip(target,false)},250)},showTip(cell,keyboard){const data=this.cellInfo(cell);if(!data)return;this.tipKeyboard=keyboard;const tip=this.tip,title=h("div","cx-mx-tiptitle"),list=h("dl","cx-mx-tiplist");setText(title,data.row.label+" · "+data.column.label);for(const[label,value]of this.cellLines(data).slice(0,8)){const term=h("dt"),text=h("dd");setText(term,label);setText(text,value);list.append(term,text)}
|
|
126
128
|
tip.replaceChildren(title,list);tip.hidden=false;const box=this.cellRect(cell._r,cell._c),frame=this.root.getBoundingClientRect(),width=tip.offsetWidth,height=tip.offsetHeight;if(!box){this.hideTip();return}
|
|
@@ -133,14 +135,20 @@ const cells=this.attentionCells(entry),items=h("ul","cx-mx-cardcells");for(const
|
|
|
133
135
|
if(cells.length>12){const more=h("li","cx-mx-sub");setText(more,"+"+this.format.format(cells.length-12));items.appendChild(more)}
|
|
134
136
|
if(!cells.length){const clear=h("div","cx-mx-sub cx-mx-clear-text");setText(clear,labels.matrixAllClear);card.appendChild(clear)}else card.appendChild(items);list.appendChild(card)}
|
|
135
137
|
const children=[list];if(rows.length>limit){const more=h("button","cx-mx-button");more.type="button";setText(more,labels.matrixShowMore);more.addEventListener("click",()=>{this.cardLimit +=100;this.renderCards()},{signal:this.lifetime.signal});children.push(more)}
|
|
136
|
-
this.cards.replaceChildren(...children)},stateGlyph(info){if(info.state===MATRIX_SELF)return "";if(info.state===MATRIX_NONE)return "";const state=this.doc.states[info.state];return(MATRIX_GLYPHS[state.symbol]||"")+(info.note&&info.note.text?" "+info.note.text:info.note&&info.note.value!=null?" "+this.format.format(info.note.value):"")},
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
this.cards.replaceChildren(...children)},stateGlyph(info){if(info.state===MATRIX_SELF)return "";if(info.state===MATRIX_NONE)return "";const state=this.doc.states[info.state];return(MATRIX_GLYPHS[state.symbol]||"")+(info.note&&info.note.text?" "+info.note.text:info.note&&info.note.value!=null?" "+this.format.format(info.note.value):"")},printCell(info){const td=h("td"),state=info.state<MATRIX_SELF?this.doc.states[info.state]:null,labels=this.labels;setText(td,info.state===MATRIX_NONE?"·":this.stateGlyph(info)+(info.rolled&&info.attention?" "+this.format.format(info.attention):""));td.title=state?state.label:info.state===MATRIX_SELF?labels.matrixSelf:labels.matrixNoData;if(state)applyTone(td,"cx-mx-printcell" +(state.attention?" cx-mx-attn":""),toneOf(state.tone));else td.className=info.state===MATRIX_SELF?"cx-mx-printself":"cx-mx-printnone";return td},printHead(table,columns){const head=h("thead"),colgroup=span=>{const group=h("colgroup");group.span=span;table.appendChild(group)};if(columns.some(entry=>entry.band)){const band=h("tr");band.appendChild(h("td"));colgroup(1);for(let c=0;c<columns.length;){const group=columns[c].band,th=h(group?"th":"td");let span=1;if(group){while(c+span<columns.length&&columns[c+span].band===group)span++;const count=h("span","cx-mx-printcount");th.scope="colgroup";setText(th,group.label);setText(count," · "+this.groupCount("columns",group.members.length));th.appendChild(count)}
|
|
139
|
+
th.colSpan=span;band.appendChild(th);colgroup(span);c +=span}
|
|
140
|
+
if(this.totalW){band.appendChild(h("td"));colgroup(1)}
|
|
141
|
+
head.appendChild(band)}
|
|
142
|
+
const row=h("tr"),corner=h("th");corner.scope="col";setText(corner,this.axisTitle("rows"));row.appendChild(corner);for(const column of columns){const th=h("th");th.scope="col";setText(th,column.label);row.appendChild(th)}
|
|
143
|
+
if(this.totalW){const th=h("th");th.scope="col";setText(th,this.labels.matrixTotal);row.appendChild(th)}
|
|
144
|
+
head.appendChild(row);table.appendChild(head)},renderPrint(){if(this.destroyed)return;const model=this.model,labels=this.labels,table=h("table","cx-mx-printtable"),caption=h("caption");setText(caption,this.doc.label+" — "+this.summaryText());table.appendChild(caption);const columns=model.columns,rows=model.rows.filter(entry=>entry.kind!=="heading");if(rows.length*columns.length<=2500){this.printHead(table,columns);let body=h("tbody");for(const entry of model.rows){if(entry.kind!=="item"&&body.childElementCount){table.appendChild(body);body=h("tbody")}
|
|
145
|
+
const tr=h("tr"),th=h("th"),total=h("td");setText(total,this.format.format(entry.total||0));setText(th,entry.label);if(entry.kind!=="item"){const count=h("span","cx-mx-printcount");setText(count," · "+this.groupCount("rows",entry.members.length));th.appendChild(count);tr.className=entry.kind==="heading"?"cx-mx-printgroup":"cx-mx-printrolled"}
|
|
146
|
+
th.scope=entry.kind==="heading"?"rowgroup":"row";tr.appendChild(th);if(entry.kind==="heading")th.colSpan=columns.length+1;else{if(entry.band)th.className="cx-mx-printmember";for(const column of columns)tr.appendChild(this.printCell(model.cell(entry,column)))}
|
|
147
|
+
if(this.totalW)tr.appendChild(total);body.appendChild(tr)}
|
|
148
|
+
table.appendChild(body)}else{const head=h("tr");for(const text of[this.axisTitle("rows"),this.axisTitle("columns"),labels.matrixState,labels.matrixValue]){const th=h("th");th.scope="col";setText(th,text);head.appendChild(th)}
|
|
141
149
|
table.appendChild(head);let written=0,left=0;for(const row of rows){for(const{column,info,state}of this.attentionCells(row)){if(written>=5000){left++;continue}
|
|
142
150
|
written++;const tr=h("tr");for(const text of[row.label,column.label,state.label,info.note&&(info.note.text||(info.note.value!=null?this.format.format(info.note.value):""))||""]){const td=h("td");setText(td,text);tr.appendChild(td)}
|
|
143
|
-
table.appendChild(tr)}}
|
|
151
|
+
const stateCell=tr.children[2];applyTone(stateCell,"cx-mx-printcell cx-mx-attn",toneOf(state.tone));setText(stateCell,(MATRIX_GLYPHS[state.symbol]||"")+ " "+state.label);table.appendChild(tr)}}
|
|
144
152
|
if(left){const tr=h("tr"),td=h("td");td.colSpan=4;setText(td,"+"+this.format.format(left));tr.appendChild(td);table.appendChild(tr)}}
|
|
145
153
|
this.print.replaceChildren(table)}});function matrixAxisName(axis){if(!MATRIX_AXES.includes(axis))throw new Error("CanopyX: a matrix axis is \"rows\" or \"columns\".");return axis}
|
|
146
154
|
Object.assign(MatrixView.prototype,{axisData(axis){return matrixAxisName(axis)==="rows"?this.doc.rows:this.doc.columns},checkSort(axis,sort){if(sort==null)return null;if(typeof sort!=="object"||(sort.by!=="#label"&&sort.by!=="#total"&&!this.axisData(axis).attributeById.has(sort.by))||![undefined,"asc","desc"].includes(sort.direction))
|
|
@@ -62,7 +62,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
62
62
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
63
63
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
64
64
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
65
|
-
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
65
|
+
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
66
66
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
67
67
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
68
68
|
return Object.freeze(labels)}
|
|
@@ -742,5 +742,5 @@ watcher.observe(host)}
|
|
|
742
742
|
function mount(root,automatic){const scope=root||document;const created=[];const showError=(host,err,api,view)=>{if(api){api.destroy();if(host.canopyx===api)delete host.canopyx}
|
|
743
743
|
const message=err&&err.message?err.message:String(err);let labels=DEFAULT_LABELS;for(const attempt of[()=>labelsFor(view&&view.labels,view&&configured.has(view.id)?configured.get(view.id).labels:null),()=>labelsFor(view&&view.labels)]){try{labels=attempt();break}catch(e){labels=DEFAULT_LABELS}}
|
|
744
744
|
const notice=document.createElement("div");notice.className="cx-mount-error";notice.setAttribute("role","alert");setText(notice,fill(labels.mountError,{error:message}));host.classList.add("cx-host");host.setAttribute("data-canopyx-mounted","true");host.setAttribute("data-cx-error",message);host.appendChild(notice);if(global.console)global.console.error(err)};const selector="[data-canopyx-host]:not([data-canopyx-mounted])";(scope.matches?.(selector)?[scope]:scope.querySelectorAll(selector)).forEach((host)=>{const config=host.querySelector("script.cx-config"),mode=host.getAttribute("data-cx-mount");if(!config||(automatic===true&&mode==="manual")){return}
|
|
745
|
-
if(mode==="visible"&&host!==scope&&global.IntersectionObserver)return mountWhenVisible(host);watcher?.unobserve(host);host.setAttribute("data-canopyx-mounted","true");let view=null;try{view=JSON.parse(config.textContent);if(view===Object(view))parsedViews.add(view);const flow=view&&view.kind==="flow"&&typeof FLOW_API==="object",matrix=view&&view.type==="matrix"&&typeof MATRIX_API==="object";const create=flow?FLOW_API.createFlow:matrix?MATRIX_API.createMatrix:view&&view.type==="grid"&&typeof createDataGrid==="function"?createDataGrid:createTreeGrid;const api=create(host,Object.assign({},view&&configured.get(view.id),flow?{flow:view}:{view}));created.push(api);api.ready.catch((err)=>{if(view.type!=="grid"&&!matrix&&activeGrids.get(host)===api&&host.canopyx===api)showError(host,err,api,view)})}catch(err){showError(host,err,null,view)}});return created}
|
|
746
|
-
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{}));if(typeof document!=="undefined"){const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}}})(runtimeHost);const CanopyX=runtimeHost.CanopyX;const{protocol,createTreeGrid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce}=CanopyX;export{protocol,createTreeGrid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce};export default CanopyX;
|
|
745
|
+
if(mode==="visible"&&host!==scope&&global.IntersectionObserver)return mountWhenVisible(host);watcher?.unobserve(host);host.setAttribute("data-canopyx-mounted","true");let view=null;try{view=JSON.parse(config.textContent);if(view===Object(view))parsedViews.add(view);const flow=view&&view.kind==="flow"&&typeof FLOW_API==="object",matrix=view&&view.type==="matrix"&&typeof MATRIX_API==="object";const change=view&&typeof CHANGE_VIEW_TYPES==="object"&&Object.hasOwn(CHANGE_VIEW_TYPES,view.type)?CHANGE_VIEW_TYPES[view.type]:null;const create=flow?FLOW_API.createFlow:matrix?MATRIX_API.createMatrix:change?change:view&&view.type==="grid"&&typeof createDataGrid==="function"?createDataGrid:createTreeGrid;const api=create(host,Object.assign({},view&&configured.get(view.id),flow?{flow:view}:{view}));created.push(api);api.ready.catch((err)=>{if(view.type!=="grid"&&!matrix&&!change&&activeGrids.get(host)===api&&host.canopyx===api)showError(host,err,api,view)})}catch(err){showError(host,err,null,view)}});return created}
|
|
746
|
+
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{},typeof CHANGES_API==="object"?CHANGES_API:{}));if(typeof document!=="undefined"){const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}}})(runtimeHost);const CanopyX=runtimeHost.CanopyX;const{protocol,createTreeGrid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce}=CanopyX;export{protocol,createTreeGrid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce};export default CanopyX;
|
|
@@ -62,7 +62,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
62
62
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
63
63
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
64
64
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
65
|
-
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
65
|
+
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
66
66
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
67
67
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
68
68
|
return Object.freeze(labels)}
|
|
@@ -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":["
|
|
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);
|
|
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}}
|
|
@@ -973,9 +973,14 @@ return applied},initializeState(){if(this.initialState?.facets)this.facetOpen=th
|
|
|
973
973
|
!!row&&Object.values(row.cells).some(cell=>isCellObject(cell)&&RECORD_STRUCTURE.some(name=>cell[name]!==undefined))};const GRID_RECORD_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_RECORD_INIT.call(this);return this.columns.some(column=>column.presenter?.kind==="structured")?Promise.all([ready,this.loadRecordPanel()]).then(([result])=>result):ready};const GRID_DATA_IMPL={},GRID_DATA=definePart(DataGrid,"data","row data",()=>({GRID_DATA_IMPL,PROTOCOL,validateGridRows,inlineGridSource,loadSidecar,gridIdOrder}));function rowDataSource(grid){let inner=null;const source={reset:()=>{inner=null},query:(query,options)=>
|
|
974
974
|
(inner||=loadPart(GRID_DATA).then(()=>GRID_DATA_IMPL.source(grid,source)).catch(error=>{inner=null;throw error})).then(rows=>rows.query(query,options))};return source}
|
|
975
975
|
class MatrixHost{}
|
|
976
|
-
const MATRIX_IMPL={},activeMatrices=new WeakMap();const MATRIX_PART=definePart(MatrixHost,"matrix","matrix view",()=>({MATRIX_IMPL,h,setText,fill,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}));const MATRIX_METHODS=["sort","group","filter","setSearch","setAttentionOnly","getState","setState","getVisible","focusCell","update"];function createMatrix(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: createMatrix needs a host element and a matrix document.");const existing=activeMatrices.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-matrix-host"].filter(name=>!host.classList.contains(name)),hadClass=host.hasAttribute("class");const previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null;const cancelled=()=>new DOMException("Matrix was destroyed.","AbortError");const ready=loadPart(MATRIX_PART).then(()=>{if(destroyed)throw cancelled();impl=MATRIX_IMPL.create(host,options);return impl.ready});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():options.view});for(const name of MATRIX_METHODS)api[name]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();return impl[name](...args)};if(destroyed)throw cancelled();return impl?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeMatrices.get(host)===api)activeMatrices.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");notice?.remove();if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
976
|
+
const MATRIX_IMPL={},activeMatrices=new WeakMap();const MATRIX_PART=definePart(MatrixHost,"matrix","matrix view",()=>({MATRIX_IMPL,h,setText,fill,plural,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}));const MATRIX_METHODS=["sort","group","filter","setSearch","setAttentionOnly","getState","setState","getVisible","focusCell","update"];function createMatrix(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: createMatrix needs a host element and a matrix document.");const existing=activeMatrices.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-matrix-host"].filter(name=>!host.classList.contains(name)),hadClass=host.hasAttribute("class");const previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null;const cancelled=()=>new DOMException("Matrix was destroyed.","AbortError");const ready=loadPart(MATRIX_PART).then(()=>{if(destroyed)throw cancelled();impl=MATRIX_IMPL.create(host,options);return impl.ready});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():options.view});for(const name of MATRIX_METHODS)api[name]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();return impl[name](...args)};if(destroyed)throw cancelled();return impl?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeMatrices.get(host)===api)activeMatrices.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");notice?.remove();if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
977
977
|
for(const name of addedClasses)host.classList.remove(name);if(!hadClass&&!host.classList.length)host.removeAttribute("class")};ready.catch(error=>{if(destroyed)return;notice=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);errorText=notice.textContent;host.setAttribute("data-cx-error",errorText);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeMatrices.set(host,api);host.classList.add("cx-host","cx-matrix-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
978
|
-
const MATRIX_API={createMatrix};
|
|
978
|
+
const MATRIX_API={createMatrix};class ChangesHost{}
|
|
979
|
+
const CHANGES_IMPL={},activeChangeViews=new WeakMap();const CHANGES_PART=definePart(ChangesHost,"changes","change views",()=>({CHANGES_IMPL,h,setText,fill,plural,numberFormat,gridFreeze,toneOf,applyTone,svgIcon,PROTOCOL}));const CHANGE_VIEW_METHODS={diff:["getLayout","setLayout","next","previous","expandAll","copy","getHunks","update"],changes:["getState","setState","toggle","focusItem","update"],propagation:["update"]};function changeViewFactory(kind,name){return function(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: "+name+" needs a host element and a "+kind+" document.");const existing=activeChangeViews.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-change-host"].filter(className=>!host.classList.contains(className)),hadClass=host.hasAttribute("class"),previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null,failure=null,loaded=false,currentView=options.view;const cancelled=()=>new DOMException("Change view was destroyed.","AbortError");const clearError=()=>{notice?.remove();notice=null;if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
980
|
+
errorText=null};const showError=error=>{if(destroyed)return;impl?.destroy();impl=null;failure=error;clearError();notice=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);errorText=notice.textContent;host.setAttribute("data-cx-error",errorText);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))};const mount=view=>{clearError();impl=CHANGES_IMPL[kind](host,{...options,view});failure=null;return impl.ready};const ready=loadPart(CHANGES_PART).then(()=>{if(destroyed)throw cancelled();loaded=true;return mount(currentView)});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():currentView});for(const method of CHANGE_VIEW_METHODS[kind])api[method]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();if(method==="update"){currentView=args[0];try{return impl?impl.update(...args):mount(currentView)}
|
|
981
|
+
catch(error){showError(error);throw error}}
|
|
982
|
+
if(failure)throw failure;return impl[method](...args)};if(destroyed)throw cancelled();return loaded?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeChangeViews.get(host)===api)activeChangeViews.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");clearError();for(const className of addedClasses)host.classList.remove(className);if(!hadClass&&!host.classList.length)host.removeAttribute("class")};ready.catch(showError);Object.freeze(api);activeChangeViews.set(host,api);host.classList.add("cx-host","cx-change-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}}
|
|
983
|
+
const CHANGES_API={createDiff:changeViewFactory("diff","createDiff"),createChangeList:changeViewFactory("changes","createChangeList"),createPropagation:changeViewFactory("propagation","createPropagation")};const CHANGE_VIEW_TYPES={diff:CHANGES_API.createDiff,changes:CHANGES_API.createChangeList,propagation:CHANGES_API.createPropagation};DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridCellRangeSelected:"{rows} rows × {columns} columns selected",gridCellRangesSelected:"{ranges} ranges selected, {cells} cells",gridCellRangeCleared:"Cell selection cleared",gridCopyCells:"Copy cells",gridCopyCellsWithHeaders:"Copy cells with headers",gridPasteCells:"Paste",gridSelectAllCells:"Select all cells",gridCellsCopied:"Copied {rows} rows × {columns} columns",gridCellsPasted:"Pasted {count} cells",gridPasteRefused:"{count} cells were not pasted",gridPasteReadOnly:"This cell cannot be changed.",gridPasteType:"“{value}” is not a valid value for {column}.",gridPasteReport:"Paste report",gridPasteCell:"Row {row}, {column}: {reason}",gridFillHandle:"Drag to fill the cells below",gridCellsFilled:"Filled {count} cells",gridCellMenu:"Cell actions",gridClearCellRanges:"Clear cell selection"}));const GRID_PART_CONTEXT=()=>({DataGrid,h,setText,fill,columnWidth,foldText,gridButton,gridIcon,gridDecorateButton,cellText,cellValue,isCellObject,numberFormat,gridFreeze,gridMomentFromParts,requireIdentifier,loadGridFilterEditor,CELL_CONTROLS,reachable,gridExportField});const GRID_COLUMN_GROUPS=definePart(DataGrid,"column-groups","column groups",GRID_PART_CONTEXT);const GRID_CELL_RANGE=definePart(DataGrid,"cell-range","cell ranges",GRID_PART_CONTEXT);const GRID_PART_API=[["column-groups","getColumnGroups","setColumnGroupVisible"],["cell-range","getCellRanges","setCellRanges","clearCellRanges","selectAllCells","copyCellRanges","getCellRangeText","pasteCells"]];const gridPartLoader=(part,start)=>function(){return(this.partLoads||={})[start]||=loadPart(part).then(()=>this.destroyed||this["start"+start]()).catch(error=>{this.partLoads[start]=null;throw error})};DataGrid.prototype.loadColumnGroups=gridPartLoader(GRID_COLUMN_GROUPS,"ColumnGroups");DataGrid.prototype.loadCellRanges=gridPartLoader(GRID_CELL_RANGE,"CellRanges");for(const[part,read,...actions]of GRID_PART_API){const load=part==="cell-range"?"loadCellRanges":"loadColumnGroups";DataGrid.prototype[read]=()=>[];for(const name of actions){const stub=DataGrid.prototype[name]=function(...args){return this[load]().then(()=>{if(DataGrid.prototype[name]===stub)throw new Error("CanopyX: the "+part+" part did not install "+name+".");return this[name](...args)})}}}
|
|
979
984
|
const GRID_PARTS_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_PARTS_INIT.call(this),range=this.opts.rangeSelection??this.view.rangeSelection;const parts=[this.view.columnGroups?.length&&this.loadColumnGroups(),range&&range.enabled!==false&&this.loadCellRanges()].filter(Boolean);return parts.length?Promise.all([ready,...parts.map(part=>part.catch(error=>this.emit("error",{error})))]).then(([result])=>result):ready};function gridButton(text,run){const button=h("button","cx-button");button.type="button";setText(button,text);button.onclick=event=>{button.focus({preventScroll:true});run(event)};return button}
|
|
980
985
|
let keyboardInput=false;if(typeof document!=="undefined"){document.addEventListener("keydown",()=>{keyboardInput=true},true);document.addEventListener("pointerdown",()=>{keyboardInput=false},true)}
|
|
981
986
|
const focusDrawerTitle=title=>{if(keyboardInput&&title===document.activeElement&&!title.matches(":focus-visible"))title.blur();title.toggleAttribute("data-cx-pointer-focus",!keyboardInput);if(!keyboardInput)title.addEventListener("blur",()=>title.removeAttribute("data-cx-pointer-focus"),{once:true});title.focus({preventScroll:true,focusVisible:keyboardInput})};function gridInputLabel(text,input){const label=h("label","cx-grid-field");label.appendChild(document.createTextNode(text));label.appendChild(input);return label}
|
|
@@ -1385,5 +1390,5 @@ watcher.observe(host)}
|
|
|
1385
1390
|
function mount(root,automatic){const scope=root||document;const created=[];const showError=(host,err,api,view)=>{if(api){api.destroy();if(host.canopyx===api)delete host.canopyx}
|
|
1386
1391
|
const message=err&&err.message?err.message:String(err);let labels=DEFAULT_LABELS;for(const attempt of[()=>labelsFor(view&&view.labels,view&&configured.has(view.id)?configured.get(view.id).labels:null),()=>labelsFor(view&&view.labels)]){try{labels=attempt();break}catch(e){labels=DEFAULT_LABELS}}
|
|
1387
1392
|
const notice=document.createElement("div");notice.className="cx-mount-error";notice.setAttribute("role","alert");setText(notice,fill(labels.mountError,{error:message}));host.classList.add("cx-host");host.setAttribute("data-canopyx-mounted","true");host.setAttribute("data-cx-error",message);host.appendChild(notice);if(global.console)global.console.error(err)};const selector="[data-canopyx-host]:not([data-canopyx-mounted])";(scope.matches?.(selector)?[scope]:scope.querySelectorAll(selector)).forEach((host)=>{const config=host.querySelector("script.cx-config"),mode=host.getAttribute("data-cx-mount");if(!config||(automatic===true&&mode==="manual")){return}
|
|
1388
|
-
if(mode==="visible"&&host!==scope&&global.IntersectionObserver)return mountWhenVisible(host);watcher?.unobserve(host);host.setAttribute("data-canopyx-mounted","true");let view=null;try{view=JSON.parse(config.textContent);if(view===Object(view))parsedViews.add(view);const flow=view&&view.kind==="flow"&&typeof FLOW_API==="object",matrix=view&&view.type==="matrix"&&typeof MATRIX_API==="object";const create=flow?FLOW_API.createFlow:matrix?MATRIX_API.createMatrix:view&&view.type==="grid"&&typeof createDataGrid==="function"?createDataGrid:createTreeGrid;const api=create(host,Object.assign({},view&&configured.get(view.id),flow?{flow:view}:{view}));created.push(api);api.ready.catch((err)=>{if(view.type!=="grid"&&!matrix&&activeGrids.get(host)===api&&host.canopyx===api)showError(host,err,api,view)})}catch(err){showError(host,err,null,view)}});return created}
|
|
1389
|
-
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{}));if(typeof document!=="undefined"){const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}}})(runtimeHost);const CanopyX=runtimeHost.CanopyX;const{protocol,createTreeGrid,createDataGrid,createCalendar,createFlow,createMatrix,enhance,grid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce}=CanopyX;export{protocol,createTreeGrid,createDataGrid,createCalendar,createFlow,createMatrix,enhance,grid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce};export default CanopyX;
|
|
1393
|
+
if(mode==="visible"&&host!==scope&&global.IntersectionObserver)return mountWhenVisible(host);watcher?.unobserve(host);host.setAttribute("data-canopyx-mounted","true");let view=null;try{view=JSON.parse(config.textContent);if(view===Object(view))parsedViews.add(view);const flow=view&&view.kind==="flow"&&typeof FLOW_API==="object",matrix=view&&view.type==="matrix"&&typeof MATRIX_API==="object";const change=view&&typeof CHANGE_VIEW_TYPES==="object"&&Object.hasOwn(CHANGE_VIEW_TYPES,view.type)?CHANGE_VIEW_TYPES[view.type]:null;const create=flow?FLOW_API.createFlow:matrix?MATRIX_API.createMatrix:change?change:view&&view.type==="grid"&&typeof createDataGrid==="function"?createDataGrid:createTreeGrid;const api=create(host,Object.assign({},view&&configured.get(view.id),flow?{flow:view}:{view}));created.push(api);api.ready.catch((err)=>{if(view.type!=="grid"&&!matrix&&!change&&activeGrids.get(host)===api&&host.canopyx===api)showError(host,err,api,view)})}catch(err){showError(host,err,null,view)}});return created}
|
|
1394
|
+
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{},typeof CHANGES_API==="object"?CHANGES_API:{}));if(typeof document!=="undefined"){const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}}})(runtimeHost);const CanopyX=runtimeHost.CanopyX;const{protocol,createTreeGrid,createDataGrid,createCalendar,createFlow,createMatrix,createDiff,createChangeList,createPropagation,enhance,grid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce}=CanopyX;export{protocol,createTreeGrid,createDataGrid,createCalendar,createFlow,createMatrix,createDiff,createChangeList,createPropagation,enhance,grid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce};export default CanopyX;
|
|
@@ -596,6 +596,8 @@ body .cx-host.cx-chrome{padding:0;}
|
|
|
596
596
|
.cx-data-grid.cx-phone .cx-phone-primary > .cx-content{flex:1;}
|
|
597
597
|
.cx-data-grid.cx-phone:not([data-cx-layout="scroll"]) .cx-phone-primary :is(.cx-text,.p-mono,.cx-presenter-text){display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;white-space:normal;overflow-wrap:anywhere;line-height:1.25;max-height:2.5em;}
|
|
598
598
|
.cx-data-grid.cx-phone .cx-phone-fields > .cx-hidden-fields{margin-left:auto;flex:none;}
|
|
599
|
+
.cx-host.cx-change-host{min-height:0;display:block;}
|
|
600
|
+
.cx-host:where(.cx-change-host:not([data-cx-height])){height:auto;}
|
|
599
601
|
.cx-column-move{flex:none;border:0;background:transparent;color:var(--cx-muted);padding:0 var(--cx-size-4px);cursor:grab;font:inherit;touch-action:none;min-width:var(--cx-size-24px);min-height:var(--cx-size-24px);}
|
|
600
602
|
.cx-column-move:hover{color:var(--cx-text);background:var(--cx-hover-bg);}
|
|
601
603
|
.cx-column-move:focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-neg-2px);}
|
|
@@ -60,7 +60,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
60
60
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
61
61
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
62
62
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
63
|
-
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
63
|
+
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
64
64
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
65
65
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
66
66
|
return Object.freeze(labels)}
|
|
@@ -504,7 +504,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
|
|
|
504
504
|
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=""}
|
|
505
505
|
close()}else{return}
|
|
506
506
|
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)}}}
|
|
507
|
-
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":["
|
|
507
|
+
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);
|
|
508
508
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
509
509
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
510
510
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -971,9 +971,14 @@ return applied},initializeState(){if(this.initialState?.facets)this.facetOpen=th
|
|
|
971
971
|
!!row&&Object.values(row.cells).some(cell=>isCellObject(cell)&&RECORD_STRUCTURE.some(name=>cell[name]!==undefined))};const GRID_RECORD_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_RECORD_INIT.call(this);return this.columns.some(column=>column.presenter?.kind==="structured")?Promise.all([ready,this.loadRecordPanel()]).then(([result])=>result):ready};const GRID_DATA_IMPL={},GRID_DATA=definePart(DataGrid,"data","row data",()=>({GRID_DATA_IMPL,PROTOCOL,validateGridRows,inlineGridSource,loadSidecar,gridIdOrder}));function rowDataSource(grid){let inner=null;const source={reset:()=>{inner=null},query:(query,options)=>
|
|
972
972
|
(inner||=loadPart(GRID_DATA).then(()=>GRID_DATA_IMPL.source(grid,source)).catch(error=>{inner=null;throw error})).then(rows=>rows.query(query,options))};return source}
|
|
973
973
|
class MatrixHost{}
|
|
974
|
-
const MATRIX_IMPL={},activeMatrices=new WeakMap();const MATRIX_PART=definePart(MatrixHost,"matrix","matrix view",()=>({MATRIX_IMPL,h,setText,fill,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}));const MATRIX_METHODS=["sort","group","filter","setSearch","setAttentionOnly","getState","setState","getVisible","focusCell","update"];function createMatrix(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: createMatrix needs a host element and a matrix document.");const existing=activeMatrices.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-matrix-host"].filter(name=>!host.classList.contains(name)),hadClass=host.hasAttribute("class");const previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null;const cancelled=()=>new DOMException("Matrix was destroyed.","AbortError");const ready=loadPart(MATRIX_PART).then(()=>{if(destroyed)throw cancelled();impl=MATRIX_IMPL.create(host,options);return impl.ready});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():options.view});for(const name of MATRIX_METHODS)api[name]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();return impl[name](...args)};if(destroyed)throw cancelled();return impl?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeMatrices.get(host)===api)activeMatrices.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");notice?.remove();if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
974
|
+
const MATRIX_IMPL={},activeMatrices=new WeakMap();const MATRIX_PART=definePart(MatrixHost,"matrix","matrix view",()=>({MATRIX_IMPL,h,setText,fill,plural,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}));const MATRIX_METHODS=["sort","group","filter","setSearch","setAttentionOnly","getState","setState","getVisible","focusCell","update"];function createMatrix(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: createMatrix needs a host element and a matrix document.");const existing=activeMatrices.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-matrix-host"].filter(name=>!host.classList.contains(name)),hadClass=host.hasAttribute("class");const previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null;const cancelled=()=>new DOMException("Matrix was destroyed.","AbortError");const ready=loadPart(MATRIX_PART).then(()=>{if(destroyed)throw cancelled();impl=MATRIX_IMPL.create(host,options);return impl.ready});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():options.view});for(const name of MATRIX_METHODS)api[name]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();return impl[name](...args)};if(destroyed)throw cancelled();return impl?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeMatrices.get(host)===api)activeMatrices.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");notice?.remove();if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
975
975
|
for(const name of addedClasses)host.classList.remove(name);if(!hadClass&&!host.classList.length)host.removeAttribute("class")};ready.catch(error=>{if(destroyed)return;notice=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);errorText=notice.textContent;host.setAttribute("data-cx-error",errorText);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeMatrices.set(host,api);host.classList.add("cx-host","cx-matrix-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
976
|
-
const MATRIX_API={createMatrix};
|
|
976
|
+
const MATRIX_API={createMatrix};class ChangesHost{}
|
|
977
|
+
const CHANGES_IMPL={},activeChangeViews=new WeakMap();const CHANGES_PART=definePart(ChangesHost,"changes","change views",()=>({CHANGES_IMPL,h,setText,fill,plural,numberFormat,gridFreeze,toneOf,applyTone,svgIcon,PROTOCOL}));const CHANGE_VIEW_METHODS={diff:["getLayout","setLayout","next","previous","expandAll","copy","getHunks","update"],changes:["getState","setState","toggle","focusItem","update"],propagation:["update"]};function changeViewFactory(kind,name){return function(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: "+name+" needs a host element and a "+kind+" document.");const existing=activeChangeViews.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-change-host"].filter(className=>!host.classList.contains(className)),hadClass=host.hasAttribute("class"),previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null,failure=null,loaded=false,currentView=options.view;const cancelled=()=>new DOMException("Change view was destroyed.","AbortError");const clearError=()=>{notice?.remove();notice=null;if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
978
|
+
errorText=null};const showError=error=>{if(destroyed)return;impl?.destroy();impl=null;failure=error;clearError();notice=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);errorText=notice.textContent;host.setAttribute("data-cx-error",errorText);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))};const mount=view=>{clearError();impl=CHANGES_IMPL[kind](host,{...options,view});failure=null;return impl.ready};const ready=loadPart(CHANGES_PART).then(()=>{if(destroyed)throw cancelled();loaded=true;return mount(currentView)});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():currentView});for(const method of CHANGE_VIEW_METHODS[kind])api[method]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();if(method==="update"){currentView=args[0];try{return impl?impl.update(...args):mount(currentView)}
|
|
979
|
+
catch(error){showError(error);throw error}}
|
|
980
|
+
if(failure)throw failure;return impl[method](...args)};if(destroyed)throw cancelled();return loaded?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeChangeViews.get(host)===api)activeChangeViews.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");clearError();for(const className of addedClasses)host.classList.remove(className);if(!hadClass&&!host.classList.length)host.removeAttribute("class")};ready.catch(showError);Object.freeze(api);activeChangeViews.set(host,api);host.classList.add("cx-host","cx-change-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}}
|
|
981
|
+
const CHANGES_API={createDiff:changeViewFactory("diff","createDiff"),createChangeList:changeViewFactory("changes","createChangeList"),createPropagation:changeViewFactory("propagation","createPropagation")};const CHANGE_VIEW_TYPES={diff:CHANGES_API.createDiff,changes:CHANGES_API.createChangeList,propagation:CHANGES_API.createPropagation};DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridCellRangeSelected:"{rows} rows × {columns} columns selected",gridCellRangesSelected:"{ranges} ranges selected, {cells} cells",gridCellRangeCleared:"Cell selection cleared",gridCopyCells:"Copy cells",gridCopyCellsWithHeaders:"Copy cells with headers",gridPasteCells:"Paste",gridSelectAllCells:"Select all cells",gridCellsCopied:"Copied {rows} rows × {columns} columns",gridCellsPasted:"Pasted {count} cells",gridPasteRefused:"{count} cells were not pasted",gridPasteReadOnly:"This cell cannot be changed.",gridPasteType:"“{value}” is not a valid value for {column}.",gridPasteReport:"Paste report",gridPasteCell:"Row {row}, {column}: {reason}",gridFillHandle:"Drag to fill the cells below",gridCellsFilled:"Filled {count} cells",gridCellMenu:"Cell actions",gridClearCellRanges:"Clear cell selection"}));const GRID_PART_CONTEXT=()=>({DataGrid,h,setText,fill,columnWidth,foldText,gridButton,gridIcon,gridDecorateButton,cellText,cellValue,isCellObject,numberFormat,gridFreeze,gridMomentFromParts,requireIdentifier,loadGridFilterEditor,CELL_CONTROLS,reachable,gridExportField});const GRID_COLUMN_GROUPS=definePart(DataGrid,"column-groups","column groups",GRID_PART_CONTEXT);const GRID_CELL_RANGE=definePart(DataGrid,"cell-range","cell ranges",GRID_PART_CONTEXT);const GRID_PART_API=[["column-groups","getColumnGroups","setColumnGroupVisible"],["cell-range","getCellRanges","setCellRanges","clearCellRanges","selectAllCells","copyCellRanges","getCellRangeText","pasteCells"]];const gridPartLoader=(part,start)=>function(){return(this.partLoads||={})[start]||=loadPart(part).then(()=>this.destroyed||this["start"+start]()).catch(error=>{this.partLoads[start]=null;throw error})};DataGrid.prototype.loadColumnGroups=gridPartLoader(GRID_COLUMN_GROUPS,"ColumnGroups");DataGrid.prototype.loadCellRanges=gridPartLoader(GRID_CELL_RANGE,"CellRanges");for(const[part,read,...actions]of GRID_PART_API){const load=part==="cell-range"?"loadCellRanges":"loadColumnGroups";DataGrid.prototype[read]=()=>[];for(const name of actions){const stub=DataGrid.prototype[name]=function(...args){return this[load]().then(()=>{if(DataGrid.prototype[name]===stub)throw new Error("CanopyX: the "+part+" part did not install "+name+".");return this[name](...args)})}}}
|
|
977
982
|
const GRID_PARTS_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_PARTS_INIT.call(this),range=this.opts.rangeSelection??this.view.rangeSelection;const parts=[this.view.columnGroups?.length&&this.loadColumnGroups(),range&&range.enabled!==false&&this.loadCellRanges()].filter(Boolean);return parts.length?Promise.all([ready,...parts.map(part=>part.catch(error=>this.emit("error",{error})))]).then(([result])=>result):ready};function gridButton(text,run){const button=h("button","cx-button");button.type="button";setText(button,text);button.onclick=event=>{button.focus({preventScroll:true});run(event)};return button}
|
|
978
983
|
let keyboardInput=false;if(typeof document!=="undefined"){document.addEventListener("keydown",()=>{keyboardInput=true},true);document.addEventListener("pointerdown",()=>{keyboardInput=false},true)}
|
|
979
984
|
const focusDrawerTitle=title=>{if(keyboardInput&&title===document.activeElement&&!title.matches(":focus-visible"))title.blur();title.toggleAttribute("data-cx-pointer-focus",!keyboardInput);if(!keyboardInput)title.addEventListener("blur",()=>title.removeAttribute("data-cx-pointer-focus"),{once:true});title.focus({preventScroll:true,focusVisible:keyboardInput})};function gridInputLabel(text,input){const label=h("label","cx-grid-field");label.appendChild(document.createTextNode(text));label.appendChild(input);return label}
|
|
@@ -1383,5 +1388,5 @@ watcher.observe(host)}
|
|
|
1383
1388
|
function mount(root,automatic){const scope=root||document;const created=[];const showError=(host,err,api,view)=>{if(api){api.destroy();if(host.canopyx===api)delete host.canopyx}
|
|
1384
1389
|
const message=err&&err.message?err.message:String(err);let labels=DEFAULT_LABELS;for(const attempt of[()=>labelsFor(view&&view.labels,view&&configured.has(view.id)?configured.get(view.id).labels:null),()=>labelsFor(view&&view.labels)]){try{labels=attempt();break}catch(e){labels=DEFAULT_LABELS}}
|
|
1385
1390
|
const notice=document.createElement("div");notice.className="cx-mount-error";notice.setAttribute("role","alert");setText(notice,fill(labels.mountError,{error:message}));host.classList.add("cx-host");host.setAttribute("data-canopyx-mounted","true");host.setAttribute("data-cx-error",message);host.appendChild(notice);if(global.console)global.console.error(err)};const selector="[data-canopyx-host]:not([data-canopyx-mounted])";(scope.matches?.(selector)?[scope]:scope.querySelectorAll(selector)).forEach((host)=>{const config=host.querySelector("script.cx-config"),mode=host.getAttribute("data-cx-mount");if(!config||(automatic===true&&mode==="manual")){return}
|
|
1386
|
-
if(mode==="visible"&&host!==scope&&global.IntersectionObserver)return mountWhenVisible(host);watcher?.unobserve(host);host.setAttribute("data-canopyx-mounted","true");let view=null;try{view=JSON.parse(config.textContent);if(view===Object(view))parsedViews.add(view);const flow=view&&view.kind==="flow"&&typeof FLOW_API==="object",matrix=view&&view.type==="matrix"&&typeof MATRIX_API==="object";const create=flow?FLOW_API.createFlow:matrix?MATRIX_API.createMatrix:view&&view.type==="grid"&&typeof createDataGrid==="function"?createDataGrid:createTreeGrid;const api=create(host,Object.assign({},view&&configured.get(view.id),flow?{flow:view}:{view}));created.push(api);api.ready.catch((err)=>{if(view.type!=="grid"&&!matrix&&activeGrids.get(host)===api&&host.canopyx===api)showError(host,err,api,view)})}catch(err){showError(host,err,null,view)}});return created}
|
|
1387
|
-
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{}));const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}})(typeof window!=="undefined"?window:this);
|
|
1391
|
+
if(mode==="visible"&&host!==scope&&global.IntersectionObserver)return mountWhenVisible(host);watcher?.unobserve(host);host.setAttribute("data-canopyx-mounted","true");let view=null;try{view=JSON.parse(config.textContent);if(view===Object(view))parsedViews.add(view);const flow=view&&view.kind==="flow"&&typeof FLOW_API==="object",matrix=view&&view.type==="matrix"&&typeof MATRIX_API==="object";const change=view&&typeof CHANGE_VIEW_TYPES==="object"&&Object.hasOwn(CHANGE_VIEW_TYPES,view.type)?CHANGE_VIEW_TYPES[view.type]:null;const create=flow?FLOW_API.createFlow:matrix?MATRIX_API.createMatrix:change?change:view&&view.type==="grid"&&typeof createDataGrid==="function"?createDataGrid:createTreeGrid;const api=create(host,Object.assign({},view&&configured.get(view.id),flow?{flow:view}:{view}));created.push(api);api.ready.catch((err)=>{if(view.type!=="grid"&&!matrix&&!change&&activeGrids.get(host)===api&&host.canopyx===api)showError(host,err,api,view)})}catch(err){showError(host,err,null,view)}});return created}
|
|
1392
|
+
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{},typeof CHANGES_API==="object"?CHANGES_API:{}));const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}})(typeof window!=="undefined"?window:this);
|
|
@@ -60,7 +60,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
60
60
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
61
61
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
62
62
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
63
|
-
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
63
|
+
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
64
64
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
65
65
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
66
66
|
return Object.freeze(labels)}
|
|
@@ -610,5 +610,5 @@ watcher.observe(host)}
|
|
|
610
610
|
function mount(root,automatic){const scope=root||document;const created=[];const showError=(host,err,api,view)=>{if(api){api.destroy();if(host.canopyx===api)delete host.canopyx}
|
|
611
611
|
const message=err&&err.message?err.message:String(err);let labels=DEFAULT_LABELS;for(const attempt of[()=>labelsFor(view&&view.labels,view&&configured.has(view.id)?configured.get(view.id).labels:null),()=>labelsFor(view&&view.labels)]){try{labels=attempt();break}catch(e){labels=DEFAULT_LABELS}}
|
|
612
612
|
const notice=document.createElement("div");notice.className="cx-mount-error";notice.setAttribute("role","alert");setText(notice,fill(labels.mountError,{error:message}));host.classList.add("cx-host");host.setAttribute("data-canopyx-mounted","true");host.setAttribute("data-cx-error",message);host.appendChild(notice);if(global.console)global.console.error(err)};const selector="[data-canopyx-host]:not([data-canopyx-mounted])";(scope.matches?.(selector)?[scope]:scope.querySelectorAll(selector)).forEach((host)=>{const config=host.querySelector("script.cx-config"),mode=host.getAttribute("data-cx-mount");if(!config||(automatic===true&&mode==="manual")){return}
|
|
613
|
-
if(mode==="visible"&&host!==scope&&global.IntersectionObserver)return mountWhenVisible(host);watcher?.unobserve(host);host.setAttribute("data-canopyx-mounted","true");let view=null;try{view=JSON.parse(config.textContent);if(view===Object(view))parsedViews.add(view);const flow=view&&view.kind==="flow"&&typeof FLOW_API==="object",matrix=view&&view.type==="matrix"&&typeof MATRIX_API==="object";const create=flow?FLOW_API.createFlow:matrix?MATRIX_API.createMatrix:view&&view.type==="grid"&&typeof createDataGrid==="function"?createDataGrid:createTreeGrid;const api=create(host,Object.assign({},view&&configured.get(view.id),flow?{flow:view}:{view}));created.push(api);api.ready.catch((err)=>{if(view.type!=="grid"&&!matrix&&activeGrids.get(host)===api&&host.canopyx===api)showError(host,err,api,view)})}catch(err){showError(host,err,null,view)}});return created}
|
|
614
|
-
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{}));const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}})(typeof window!=="undefined"?window:this);
|
|
613
|
+
if(mode==="visible"&&host!==scope&&global.IntersectionObserver)return mountWhenVisible(host);watcher?.unobserve(host);host.setAttribute("data-canopyx-mounted","true");let view=null;try{view=JSON.parse(config.textContent);if(view===Object(view))parsedViews.add(view);const flow=view&&view.kind==="flow"&&typeof FLOW_API==="object",matrix=view&&view.type==="matrix"&&typeof MATRIX_API==="object";const change=view&&typeof CHANGE_VIEW_TYPES==="object"&&Object.hasOwn(CHANGE_VIEW_TYPES,view.type)?CHANGE_VIEW_TYPES[view.type]:null;const create=flow?FLOW_API.createFlow:matrix?MATRIX_API.createMatrix:change?change:view&&view.type==="grid"&&typeof createDataGrid==="function"?createDataGrid:createTreeGrid;const api=create(host,Object.assign({},view&&configured.get(view.id),flow?{flow:view}:{view}));created.push(api);api.ready.catch((err)=>{if(view.type!=="grid"&&!matrix&&!change&&activeGrids.get(host)===api&&host.canopyx===api)showError(host,err,api,view)})}catch(err){showError(host,err,null,view)}});return created}
|
|
614
|
+
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{},typeof CHANGES_API==="object"?CHANGES_API:{}));const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}})(typeof window!=="undefined"?window:this);
|