@evotecit/canopyx 0.3.6 → 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-calendar.js +4 -3
- package/CanopyX.Html/Assets/canopyx-changes.css +240 -0
- package/CanopyX.Html/Assets/canopyx-changes.js +224 -0
- package/CanopyX.Html/Assets/canopyx-detail-rows.js +2 -2
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +2 -1
- package/CanopyX.Html/Assets/canopyx-formatting.js +7 -6
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +71 -44
- package/CanopyX.Html/Assets/canopyx-grid.css +24 -0
- package/CanopyX.Html/Assets/canopyx-grid.js +71 -44
- package/CanopyX.Html/Assets/canopyx-interactive.js +6 -6
- package/CanopyX.Html/Assets/canopyx-labels-de.js +76 -2
- package/CanopyX.Html/Assets/canopyx-labels-es.js +76 -2
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +76 -2
- package/CanopyX.Html/Assets/canopyx-labels-it.js +76 -2
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +76 -2
- package/CanopyX.Html/Assets/canopyx-live.js +4 -3
- package/CanopyX.Html/Assets/canopyx-matrix.css +16 -3
- package/CanopyX.Html/Assets/canopyx-matrix.js +22 -14
- package/CanopyX.Html/Assets/canopyx-module.mjs +6 -6
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +73 -46
- package/CanopyX.Html/Assets/canopyx-reporting.css +24 -0
- package/CanopyX.Html/Assets/canopyx-reporting.js +73 -46
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +7 -6
- package/CanopyX.Html/Assets/canopyx.js +6 -6
- package/JavaScript/changes.d.ts +252 -0
- package/JavaScript/grid.d.ts +15 -5
- package/JavaScript/locales/de.mjs +76 -2
- package/JavaScript/locales/es.mjs +76 -2
- package/JavaScript/locales/fr.mjs +76 -2
- package/JavaScript/locales/it.mjs +76 -2
- package/JavaScript/locales/pl.mjs +76 -2
- package/JavaScript/matrix.d.ts +2 -0
- package/JavaScript/protocol.d.ts +1 -1
- package/README.md +7 -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:"4c6c4101089c4444",install(context){if(installed.has(context.TreeGrid.prototype))return;const{TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,exportTimeout,exportFormatsOf,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField}=context;const EXPORT_IMPL={formatsOf:exportFormatsOf};const GRID_ICONS={search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',filter:'<path d="M4 5h16l-6 7.5V19l-4-2v-4.5z"/>',columns:'<rect x="3.5" y="4.5" width="17" height="15" rx="2"/><path d="M9.5 4.5v15M14.5 4.5v15"/>',views:'<path d="M6 4h12v16l-6-4-6 4z"/>',export:'<path d="M12 4v11M7.5 10.5 12 15l4.5-4.5M5 19h14"/>',more:'<circle cx="5" cy="12" r="1.2"/><circle cx="12" cy="12" r="1.2"/><circle cx="19" cy="12" r="1.2"/>',close:'<path d="M6 6l12 12M18 6 6 18"/>',check:'<path d="m5 12.5 4.5 4.5L19 7.5"/>',chart:'<path d="M4 19h16M7 16V10M12 16V6M17 16v-4"/>',copy:'<rect x="8" y="8" width="11" height="11" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/>',up:'<path d="M12 19V5M6 11l6-6 6 6"/>',down:'<path d="M12 5v14M6 13l6 6 6-6"/>',retry:'<path d="M4 12a8 8 0 1 0 2.4-5.7M4 4v4.5h4.5"/>',previous:'<path d="m14 7-5 5 5 5"/>',next:'<path d="m10 7 5 5-5 5"/>',first:'<path d="m13 7-5 5 5 5M17 7l-5 5 5 5"/>',last:'<path d="m11 7 5 5-5 5M7 7l5 5-5 5"/>'};function gridIcon(name,shapes){return svgIcon(shapes||GRID_ICONS[name]||GRID_ICONS.more)}
|
|
2
2
|
function gridDecorateButton(button,icon,ghost){button.classList.add("cx-btn");if(ghost)button.classList.add("ghost");if(icon)button.prepend(gridIcon(icon));return button}
|
|
3
3
|
function gridFilterCount(query){const count=group=>group?group.filters.length+group.groups.reduce((sum,child)=>sum+count(child),0):0;return(query?.filters?.length||0)+ count(query?.filterGroup)}
|
|
4
4
|
function gridPriority(value){return["essential","normal","optional"].includes(value)||Number.isInteger(value)&&value>=0&&value<=MAX_PROTOCOL_INTEGER}
|
|
@@ -8,7 +8,8 @@ function gridOptions(column){return column.presenter||{}}
|
|
|
8
8
|
const COLUMN_DIGITS=new Map(),COLUMN_NUMERIC_CHARS="0123456789 .,:;+-−/()[]\u00a0\u202f",COLUMN_HAS_NUMERIC=/[0-9\s.,:;+\-−/()\[\]]/;
|
|
9
9
|
function gridNumericVariant(grid){let sample=grid.querySelector(".cx-cell"),owned=!sample;if(owned){sample=document.createElement("span");sample.className="cx-cell";sample.style.display="none";grid.appendChild(sample)}
|
|
10
10
|
const variant=getComputedStyle(sample).fontVariantNumeric;if(owned)sample.remove();return variant}
|
|
11
|
-
function gridClassFont(grid,className){const probe=
|
|
11
|
+
function gridClassFont(grid,className,chrome){const probe=h("span",className);probe.style.cssText="position:absolute;visibility:hidden";grid.appendChild(probe);const style=getComputedStyle(probe),font=[style.fontWeight,style.fontSize,style.fontFamily].join(" ");if(chrome){chrome.extra=probe.getBoundingClientRect().width;chrome.spacing=parseFloat(style.letterSpacing)||0}
|
|
12
|
+
probe.remove();return font}
|
|
12
13
|
function gridMeasureText(context,value,variant="normal"){const text=String(value).slice(0,512),measured=context.measureText(text).width;if(!variant.includes("tabular-nums")||!COLUMN_HAS_NUMERIC.test(text))return measured;const font=context.font;let variants=COLUMN_DIGITS.get(font);if(!variants){if(COLUMN_DIGITS.size===32)COLUMN_DIGITS.delete(COLUMN_DIGITS.keys().next().value);COLUMN_DIGITS.set(font,variants=new Map())}
|
|
13
14
|
if(!variants.has(variant)){const probe=document.createElement("span"),glyphs=[];probe.style.cssText="all:initial;position:absolute;visibility:hidden;display:flex;white-space:pre;padding:0;border:0;max-width:none;";probe.style.font=font;probe.style.fontVariantNumeric=variant;for(const character of COLUMN_NUMERIC_CHARS)for(const numeric of[true,false]){const glyph=document.createElement("span");glyph.textContent=(numeric?"00"+character+"00":character).repeat(10);glyph.style.cssText="flex:none;white-space:pre;";probe.appendChild(glyph);glyphs.push(glyph)}
|
|
14
15
|
document.body.appendChild(probe);const zero=glyphs[0].getBoundingClientRect().width / 50, numeric = new Map(), plain = new Map();
|
|
@@ -30,10 +31,10 @@ return excess},fitSpare(columns,spare){let target,flex=columns.filter(column=>co
|
|
|
30
31
|
flex=flex.filter(column=>column.maxW-column.renderWidth>0.5)}
|
|
31
32
|
const identity=columns.find(column=>column.identity),widest=columns.filter(column=>!column.identity&&
|
|
32
33
|
gridTextual(column)&&gridLevel(column)===1).sort((a,b)=>b.need-a.need)[0];grow(identity,420);if(identity&&widest)grow(widest,widest.renderWidth+spare*widest.need / (widest.need + identity.need));
|
|
33
|
-
grow(identity,Infinity);grow(widest,Infinity);return target},fitHide(shown,width,phone){let total=0,remaining=shown.length;const order=(a,b)=>gridLevel(b)- gridLevel(a)||gridRank(b)- gridRank(a)||shown.indexOf(b)- shown.indexOf(a),identity=phone&&shown.find(column=>column.identity);const hide=(column,pinned)=>!column.sized&&!column.alwaysVisible&&(column.pin==="none")!==pinned&&!(phone&&column.identity)&&gridLevel(column)>!phone;for(const column of this.columns)column.fitHidden=false;if(this.layoutMode&&this.layoutMode!=="fit")return;for(const column of shown)total +=
|
|
34
|
-
if(total>width&&remaining>1){column.fitHidden=true;total -=
|
|
35
|
-
if(identity&&!identity.fixed&&!identity.sized)total +=Math.min(identity.need??identity.width,(identity.indentNeed||0)+ 2*(this.fitCh||88))+(identity.reserve||0)-
|
|
36
|
-
if(total>width){column.fitHidden=true;total -=
|
|
34
|
+
grow(identity,Infinity);grow(widest,Infinity);return target},fitHide(shown,width,phone,size=column=>this.fitSize(column,1)){let total=0,remaining=shown.length;const order=(a,b)=>gridLevel(b)- gridLevel(a)||gridRank(b)- gridRank(a)||shown.indexOf(b)- shown.indexOf(a),identity=phone&&shown.find(column=>column.identity);const hide=(column,pinned)=>!column.sized&&!column.alwaysVisible&&(column.pin==="none")!==pinned&&!(phone&&column.identity)&&gridLevel(column)>!phone;for(const column of this.columns)column.fitHidden=false;if(this.layoutMode&&this.layoutMode!=="fit")return;for(const column of shown)total +=size(column);for(const column of shown.filter(column=>hide(column,false)).sort(order))
|
|
35
|
+
if(total>width&&remaining>1){column.fitHidden=true;total -=size(column);remaining--}
|
|
36
|
+
if(identity&&!identity.fixed&&!identity.sized)total +=Math.min(identity.need??identity.width,(identity.indentNeed||0)+ 2*(this.fitCh||88))+(identity.reserve||0)- size(identity);if(identity)for(const column of shown.filter(column=>hide(column,true)).sort(order))
|
|
37
|
+
if(total>width){column.fitHidden=true;total -=size(column)}}};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}
|
|
37
38
|
let keyboardInput=false;if(typeof document!=="undefined"){document.addEventListener("keydown",()=>{keyboardInput=true},true);document.addEventListener("pointerdown",()=>{keyboardInput=false},true)}
|
|
38
39
|
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}
|
|
39
40
|
function gridOption(value,text){const option=h("option");option.value=value;setText(option,text);return option}
|
|
@@ -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",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)}
|
|
@@ -74,7 +74,7 @@ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.
|
|
|
74
74
|
catch(_){trustPolicy=null}}
|
|
75
75
|
return trustPolicy?trustPolicy["create"+kind](value):value}
|
|
76
76
|
function hostHtml(element,html,sanitize,kind){const text=String(html??""),value=sanitize?sanitize(text,{kind}):text;if(value?.nodeType)element.replaceChildren(value);else if(typeof value==="string")element.innerHTML=trusted("HTML",value);else if(global.trustedTypes?.isHTML?.(value))element.innerHTML=value;else throw new Error("CanopyX: invalid sanitizeHtml result.")}
|
|
77
|
-
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridMore:"More",gridPrint:"Print",gridDetails:"Record details",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close
|
|
77
|
+
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridMore:"More",gridPrint:"Print",gridDetails:"Record details",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close"}));DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{recordBack:"Back",recordBackTo:"Back to {record}",recordTrail:"Record trail",recordShowing:"Showing {record}",recordTabs:"Record views",recordSections:"Jump to a section",recordOtherFields:"Other fields",recordShowEmpty:"Show empty fields ({count})",recordHideEmpty:"Hide empty fields",recordActions:"Record actions",recordCopyValues:"Copy values",recordCopyJson:"Copy as JSON",recordCopyLink:"Copy link",recordCopied:"Copied to the clipboard",recordPrint:"Print record",recordExportCsv:"Export CSV",recordExportJson:"Export JSON",recordOpenAll:"Open all in grid",recordLoadMore:"Load more",recordCount:"{shown} of {total}",recordItems:"{count} items",recordMore:"+{count}",recordShowAll:"Show all {count}",recordRetry:"Retry",recordLoadFailed:"Could not load the record details: {error}",recordUnavailable:"Record {id} is not available here.",recordField:"Field",recordValue:"Value",recordSection:"Section",recordBefore:"Before",recordAfter:"After",recordAdded:"Added",recordRemoved:"Removed",recordChanged:"{count} changed fields"}));function boundedPattern(source,exact=true,whole=false){const bad=()=>{throw new Error("CanopyX: pattern requires literals, character classes and at most one variable repetition anchored at the start; groups, alternatives and backreferences are unsupported.")};if(typeof source!=="string"||source.length>256)bad();let width=0,variable=0;for(let i=0;i<source.length;){const unit=source[i++];if(unit==="^"&&i===1||unit==="$"&&i===source.length)continue;if(unit==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbBnrtfv\\.^$*+?{}\[\]()|/]$/.test(escape)) bad();
|
|
78
78
|
}else if(unit==="["){let closed=false;while(i<source.length){const c=source[i++];if(c==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbnrtfv\\.^$*+?{}\[\]()|/-]$/.test(escape)) bad(); }
|
|
79
79
|
else if(c==="]"){closed=true;break}}
|
|
80
80
|
if(!closed)bad()}else if("()|^$*+?{}]".includes(unit))bad();let count=1;if(i<source.length&&"*+?".includes(source[i])){variable++;i++}
|
|
@@ -334,7 +334,7 @@ function hostRenderers(renderers,columns,plugins){if(![Object.prototype,null].in
|
|
|
334
334
|
Object.keys(renderers).some(id=>typeof renderers[id]!=="function"||!columns.some(column=>column.id===id)))
|
|
335
335
|
throw new Error("CanopyX: invalid column renderers.");const named=Object.assign(Object.create(null),...plugins.map(item=>item.cellRenderers));return Object.assign(Object.create(null),...columns.filter(column=>typeof column.renderer==="string"&&named[column.renderer])
|
|
336
336
|
.map(column=>({[column.id]:named[column.renderer]})),renderers)}
|
|
337
|
-
function disposeHostSlot(slot){const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
|
|
337
|
+
function disposeHostSlot(slot){slot.childSlots?.forEach(disposeHostSlot);const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
|
|
338
338
|
function disposeRowHostCells(row){row._cells?.forEach(disposeHostSlot)}
|
|
339
339
|
class HostCellContext{#controller;#cleanups;constructor(slot,column,level,expanded,index){slot.hostLifetime=this;this.column=column;this.level=level;this.expanded=expanded;this.index=index}
|
|
340
340
|
get signal(){this.#controller||=new AbortController();if(this.#cleanups===null)this.#controller.abort();return this.#controller.signal}
|
|
@@ -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":["
|
|
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"],"export":["8b99c0b7b0ec37c5","canopyx-export.6989ea36f5d6da7b.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.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}}
|
|
@@ -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);
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// Type declarations for the change views (docs/changes.md): a text diff, a change list and a propagation view.
|
|
2
|
+
|
|
3
|
+
/** A note about a change that the lines cannot show, such as changed line endings. */
|
|
4
|
+
export interface ChangeNote {
|
|
5
|
+
text: string;
|
|
6
|
+
/** A CanopyX tone or a host tone; info when left out. */
|
|
7
|
+
tone?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** A run of lines: where it starts on each side and its lines, each beginning with " " (unchanged), "-" (removed) or "+" (added). */
|
|
11
|
+
export interface DiffHunk {
|
|
12
|
+
before: number;
|
|
13
|
+
after: number;
|
|
14
|
+
lines: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** The properties of a diff, as a diff document carries them and as a change list item's diff. */
|
|
18
|
+
export interface DiffBody {
|
|
19
|
+
id: string;
|
|
20
|
+
label: string;
|
|
21
|
+
path?: string;
|
|
22
|
+
previousPath?: string;
|
|
23
|
+
/** Text by default; the other states have no lines and show their message. */
|
|
24
|
+
content?: "binary" | "unavailable" | "identical";
|
|
25
|
+
message?: string;
|
|
26
|
+
beforeTitle?: string;
|
|
27
|
+
afterTitle?: string;
|
|
28
|
+
/** The whole earlier text: the browser compares the texts when there are no hunks (up to 5,000 lines each) and opens folded regions. */
|
|
29
|
+
before?: string;
|
|
30
|
+
after?: string;
|
|
31
|
+
hunks?: DiffHunk[];
|
|
32
|
+
/** Unchanged lines around each change, 0 to 20; 3 by default. */
|
|
33
|
+
context?: number;
|
|
34
|
+
/** Side by side when there is room, by default. */
|
|
35
|
+
layout?: "inline" | "split";
|
|
36
|
+
notes?: ChangeNote[];
|
|
37
|
+
truncated?: boolean;
|
|
38
|
+
/** The host's copy-ready unified diff. */
|
|
39
|
+
unified?: string;
|
|
40
|
+
labels?: Record<string, string>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The diff document: `{ protocol: "canopyx/2", type: "diff" }`. */
|
|
44
|
+
export interface DiffDocument extends DiffBody {
|
|
45
|
+
protocol: "canopyx/2";
|
|
46
|
+
type: "diff";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Options of createDiff and CanopyX.configure for a diff fragment. */
|
|
50
|
+
export interface DiffOptions {
|
|
51
|
+
view: DiffDocument;
|
|
52
|
+
labels?: Record<string, string>;
|
|
53
|
+
onReady?: (detail: { diff: string }) => void;
|
|
54
|
+
onLayout?: (detail: { diff: string; layout: "inline" | "split" }) => void;
|
|
55
|
+
onCopy?: (detail: { diff: string; copied: boolean }) => void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The API of a diff. A call made before the changes part is in waits for it and returns a promise instead. */
|
|
59
|
+
export interface DiffApi {
|
|
60
|
+
readonly element: HTMLElement;
|
|
61
|
+
readonly view: DiffDocument;
|
|
62
|
+
readonly ready: Promise<DiffApi>;
|
|
63
|
+
getLayout(): "inline" | "split";
|
|
64
|
+
setLayout(layout: "inline" | "split"): void;
|
|
65
|
+
/** Moves to the next or previous change; false when there is none. */
|
|
66
|
+
next(): boolean;
|
|
67
|
+
previous(): boolean;
|
|
68
|
+
/** Opens every folded region whose lines the diff has. */
|
|
69
|
+
expandAll(): void;
|
|
70
|
+
/** Copies the unified diff; resolves whether the clipboard took it. */
|
|
71
|
+
copy(): Promise<boolean>;
|
|
72
|
+
/** The hunks in effect: the document's, or those the browser compared. */
|
|
73
|
+
getHunks(): DiffHunk[];
|
|
74
|
+
update(view: DiffDocument): void;
|
|
75
|
+
destroy(): void;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** One side of a change: size in bytes, content hash and time. */
|
|
79
|
+
export interface ChangeVersion {
|
|
80
|
+
size?: number;
|
|
81
|
+
hash?: string;
|
|
82
|
+
/** ISO 8601. */
|
|
83
|
+
time?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** A changed file or item. */
|
|
87
|
+
export interface ChangeItem {
|
|
88
|
+
id: string;
|
|
89
|
+
kind: "added" | "removed" | "modified" | "renamed";
|
|
90
|
+
path: string;
|
|
91
|
+
previousPath?: string;
|
|
92
|
+
kindLabel?: string;
|
|
93
|
+
secondary?: string;
|
|
94
|
+
before?: ChangeVersion;
|
|
95
|
+
after?: ChangeVersion;
|
|
96
|
+
/** Shown side by side; an added item shows only its after, a removed one only its before. `note` is quiet text under the values. */
|
|
97
|
+
facts?: { label: string; before?: string; after?: string; tone?: string; note?: string }[];
|
|
98
|
+
flags?: { id: string; label: string; reason: string; tone?: string }[];
|
|
99
|
+
/** A diff that opens in the item's details. */
|
|
100
|
+
diff?: DiffBody;
|
|
101
|
+
/** The ids of the list's actions this item offers; all of them when left out. */
|
|
102
|
+
actions?: string[];
|
|
103
|
+
/** Values that copy and link actions use by key. */
|
|
104
|
+
values?: Record<string, string>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* An action the items (or the list's bar) offer: a host action, one that asks for a reason first, a copy action ("path",
|
|
109
|
+
* "previousPath" or a value key), a link that opens a value (#, /, ./, ../, http(s):// or mailto: addresses), or one that reveals the
|
|
110
|
+
* item's details or diff. One of copy, link, reveal and reason at most.
|
|
111
|
+
*/
|
|
112
|
+
export interface ChangeAction {
|
|
113
|
+
id: string;
|
|
114
|
+
label: string;
|
|
115
|
+
icon?: "none" | "copy" | "diff" | "check" | "open" | "download" | "compare" | "flag";
|
|
116
|
+
copy?: string;
|
|
117
|
+
link?: string;
|
|
118
|
+
reveal?: "none" | "details" | "diff";
|
|
119
|
+
reason?: boolean;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** The change list document: `{ protocol: "canopyx/2", type: "changes" }`. */
|
|
123
|
+
export interface ChangeListDocument {
|
|
124
|
+
protocol: "canopyx/2";
|
|
125
|
+
type: "changes";
|
|
126
|
+
id: string;
|
|
127
|
+
label: string;
|
|
128
|
+
actions?: ChangeAction[];
|
|
129
|
+
/** The bar's actions: host actions, and copy and link actions on the list's values. */
|
|
130
|
+
toolbar?: ChangeAction[];
|
|
131
|
+
values?: Record<string, string>;
|
|
132
|
+
/** The files the bar offers to download: the items the filters keep. */
|
|
133
|
+
exports?: ("csv" | "json")[];
|
|
134
|
+
items: ChangeItem[];
|
|
135
|
+
groupByFolder?: boolean;
|
|
136
|
+
flaggedOnly?: boolean;
|
|
137
|
+
expandFlagged?: boolean;
|
|
138
|
+
hashLength?: number;
|
|
139
|
+
pageSize?: number;
|
|
140
|
+
timeZone?: "utc" | "local";
|
|
141
|
+
labels?: Record<string, string>;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** The reader's filters and open items. */
|
|
145
|
+
export interface ChangeListState {
|
|
146
|
+
kinds: ChangeItem["kind"][];
|
|
147
|
+
flaggedOnly: boolean;
|
|
148
|
+
open: string[];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** What canopyx:changeAction carries. */
|
|
152
|
+
export interface ChangeActionDetail {
|
|
153
|
+
list: string;
|
|
154
|
+
action: string;
|
|
155
|
+
/** The item, or null for an action of the list's bar. */
|
|
156
|
+
item: string | null;
|
|
157
|
+
kind: ChangeItem["kind"] | null;
|
|
158
|
+
path: string | null;
|
|
159
|
+
previousPath: string | null;
|
|
160
|
+
/** The item's values, or the list's for a bar action. */
|
|
161
|
+
values: Record<string, string>;
|
|
162
|
+
/** For a copy action, whether the clipboard took the value; null otherwise. */
|
|
163
|
+
copied: boolean | null;
|
|
164
|
+
/** The reason the reader gave, for an action that asks for one. */
|
|
165
|
+
reason?: string;
|
|
166
|
+
/** The address a link action opened. */
|
|
167
|
+
href?: string;
|
|
168
|
+
/** What a reveal action opened. */
|
|
169
|
+
reveal?: "details" | "diff";
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** What canopyx:changeExport carries. */
|
|
173
|
+
export interface ChangeExportDetail {
|
|
174
|
+
list: string;
|
|
175
|
+
format: "csv" | "json";
|
|
176
|
+
count: number;
|
|
177
|
+
/** Whether the browser was given the file. */
|
|
178
|
+
saved: boolean;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Options of createChangeList and CanopyX.configure for a change list fragment. */
|
|
182
|
+
export interface ChangeListOptions {
|
|
183
|
+
view: ChangeListDocument;
|
|
184
|
+
labels?: Record<string, string>;
|
|
185
|
+
state?: Partial<ChangeListState>;
|
|
186
|
+
onReady?: (detail: { list: string }) => void;
|
|
187
|
+
/** Receives every action; for a host action, having it claims the action (as cancelling canopyx:changeAction does). */
|
|
188
|
+
onAction?: (detail: ChangeActionDetail, event: CustomEvent<ChangeActionDetail>) => void;
|
|
189
|
+
onExport?: (detail: ChangeExportDetail) => void;
|
|
190
|
+
onToggle?: (detail: { list: string; item: string; open: boolean }) => void;
|
|
191
|
+
onStateChange?: (state: ChangeListState) => void;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** The API of a change list. */
|
|
195
|
+
export interface ChangeListApi {
|
|
196
|
+
readonly element: HTMLElement;
|
|
197
|
+
readonly view: ChangeListDocument;
|
|
198
|
+
readonly ready: Promise<ChangeListApi>;
|
|
199
|
+
getState(): Readonly<ChangeListState>;
|
|
200
|
+
setState(state: Partial<ChangeListState>): void;
|
|
201
|
+
/** Opens, closes or switches an item's details; false for an unknown item. */
|
|
202
|
+
toggle(id: string, open?: boolean): boolean;
|
|
203
|
+
focusItem(id: string): boolean;
|
|
204
|
+
update(view: ChangeListDocument): void;
|
|
205
|
+
destroy(): void;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Where a change stands at a replica. */
|
|
209
|
+
export type PropagationState = "converged" | "propagating" | "fault" | "unknown";
|
|
210
|
+
|
|
211
|
+
/** The propagation document: `{ protocol: "canopyx/2", type: "propagation" }`. */
|
|
212
|
+
export interface PropagationDocument {
|
|
213
|
+
protocol: "canopyx/2";
|
|
214
|
+
type: "propagation";
|
|
215
|
+
id: string;
|
|
216
|
+
label: string;
|
|
217
|
+
/** ISO 8601: when the change happened; the delays count from it. */
|
|
218
|
+
start?: string;
|
|
219
|
+
/** ISO 8601: when the evidence is from. */
|
|
220
|
+
asOf?: string;
|
|
221
|
+
state?: PropagationState;
|
|
222
|
+
summary?: string;
|
|
223
|
+
title?: string;
|
|
224
|
+
/** How a group heading counts its replicas, with {count} and optional plural forms. */
|
|
225
|
+
groupCount?: string;
|
|
226
|
+
witnesses: { id: string; label: string; secondary?: string; state: PropagationState; firstSeen?: string; lastSeen?: string; note?: string; source?: boolean; group?: string }[];
|
|
227
|
+
timeZone?: "utc" | "local";
|
|
228
|
+
labels?: Record<string, string>;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Options of createPropagation and CanopyX.configure for a propagation fragment. */
|
|
232
|
+
export interface PropagationOptions {
|
|
233
|
+
view: PropagationDocument;
|
|
234
|
+
labels?: Record<string, string>;
|
|
235
|
+
onReady?: (detail: { propagation: string }) => void;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** The API of a propagation view. */
|
|
239
|
+
export interface PropagationApi {
|
|
240
|
+
readonly element: HTMLElement;
|
|
241
|
+
readonly view: PropagationDocument;
|
|
242
|
+
readonly ready: Promise<PropagationApi>;
|
|
243
|
+
update(view: PropagationDocument): void;
|
|
244
|
+
destroy(): void;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Creates a text diff in a host element (docs/changes.md). Ships with the grid and reporting entry points. */
|
|
248
|
+
export declare function createDiff(host: HTMLElement, options: DiffOptions): DiffApi;
|
|
249
|
+
/** Creates a change list in a host element (docs/changes.md). Ships with the grid and reporting entry points. */
|
|
250
|
+
export declare function createChangeList(host: HTMLElement, options: ChangeListOptions): ChangeListApi;
|
|
251
|
+
/** Creates a propagation view in a host element (docs/changes.md). Ships with the grid and reporting entry points. */
|
|
252
|
+
export declare function createPropagation(host: HTMLElement, options: PropagationOptions): PropagationApi;
|
package/JavaScript/grid.d.ts
CHANGED
|
@@ -354,6 +354,8 @@ interface GridDefinition<Q extends AcceptedGridQuery = GridQuery, Row extends Gr
|
|
|
354
354
|
/** Pager settings of a paged view, read by the pager part (canopyx-pager.js); absent keeps the built-in pager. */
|
|
355
355
|
pager?: GridPager;
|
|
356
356
|
selection: "none" | "single" | "multiple";
|
|
357
|
+
/** Ordinal IDs are source positions in one snapshot; saved selection replay and keyed live updates are unavailable. Default stableKey. */
|
|
358
|
+
rowIdentity?: "stableKey" | "ordinal";
|
|
357
359
|
search: boolean;
|
|
358
360
|
/** Search-input debounce (0..5000). Absent uses 0 for inline and 300 for host sources. */
|
|
359
361
|
searchDelayMs?: number;
|
|
@@ -378,6 +380,8 @@ interface GridDefinition<Q extends AcceptedGridQuery = GridQuery, Row extends Gr
|
|
|
378
380
|
dragRows?: boolean;
|
|
379
381
|
stateKey?: string;
|
|
380
382
|
timeZone?: TimeZone;
|
|
383
|
+
/** Space-separated host styling classes copied onto body-appended record, text and column overlays when opened. */
|
|
384
|
+
overlayClass?: string;
|
|
381
385
|
labels?: Partial<CanopyLabels>;
|
|
382
386
|
/** Sanitizes trusted host HTML details before insertion; shares the tree host's sanitizer contract. */
|
|
383
387
|
sanitizeHtml?: HostOptions["sanitizeHtml"];
|
|
@@ -695,6 +699,8 @@ interface GridHostBehavior<Q extends AcceptedGridQuery = GridQuery, Row extends
|
|
|
695
699
|
/** Overrides the view's search-input debounce (0..5000); Enter always applies immediately. */
|
|
696
700
|
searchDelayMs?: number;
|
|
697
701
|
source?: Q extends GridCursorQuery ? GridCursorSource<Row> : GridSource<Row>;
|
|
702
|
+
/** Space-separated host styling classes copied onto body-appended record, text and column overlays when opened. */
|
|
703
|
+
overlayClass?: string;
|
|
698
704
|
labels?: Partial<CanopyLabels>;
|
|
699
705
|
renderers?: Record<string, (row: Row, element: HTMLElement, context: GridCellContext) => boolean | void>;
|
|
700
706
|
cachePageLimit?: number;
|
|
@@ -933,14 +939,15 @@ export function createDataGrid<Row extends GridRow = GridRow>(host: HTMLElement,
|
|
|
933
939
|
export function createDataGrid<Row extends GridRow = GridRow>(host: HTMLElement, options: CursorGridOptions<GridNamedRow<Row>>): DataGrid<GridCursorQuery, Row>;
|
|
934
940
|
/** A calendar from a list of events, with no grid schema to write: a preset (basic by default) and options over it (calendar.d.ts). */
|
|
935
941
|
export function createCalendar(host: HTMLElement, options?: CalendarOptions): DataGrid<GridQuery, GridRow>;
|
|
936
|
-
/** Registers options before a tree, flat-grid, flow or
|
|
937
|
-
export function configure(viewId: string, options: HostOptions | GridHostOptions | GridHostOptions<GridCursorQuery> | Partial<Omit<FlowOptions, "flow">> | Partial<Omit<MatrixOptions, "view">>
|
|
942
|
+
/** Registers options before a tree, flat-grid, flow, matrix or change view fragment mounts. */
|
|
943
|
+
export function configure(viewId: string, options: HostOptions | GridHostOptions | GridHostOptions<GridCursorQuery> | Partial<Omit<FlowOptions, "flow">> | Partial<Omit<MatrixOptions, "view">>
|
|
944
|
+
| Partial<Omit<DiffOptions, "view">> | Partial<Omit<ChangeListOptions, "view">> | Partial<Omit<PropagationOptions, "view">>): () => void;
|
|
938
945
|
/**
|
|
939
|
-
* Mounts tree, flat-grid, flow and
|
|
946
|
+
* Mounts tree, flat-grid, flow, matrix and change view fragments below root, or root itself when it is a fragment. Fragments marked
|
|
940
947
|
* `data-cx-mount="visible"` below root wait until they come near the viewport; passing such a fragment as root mounts it at once.
|
|
941
948
|
* Narrow a controller before using view-specific methods.
|
|
942
949
|
*/
|
|
943
|
-
export function mount(root?: ParentNode): Array<TreeGrid | DataGrid<AcceptedGridQuery> | FlowApi | MatrixApi>;
|
|
950
|
+
export function mount(root?: ParentNode): Array<TreeGrid | DataGrid<AcceptedGridQuery> | FlowApi | MatrixApi | DiffApi | ChangeListApi | PropagationApi>;
|
|
944
951
|
|
|
945
952
|
import type { createFlow, FlowApi, FlowOptions } from "./flow.js";
|
|
946
953
|
export { createFlow } from "./flow.js";
|
|
@@ -948,5 +955,8 @@ export type { FlowDocument, FlowField, FlowStep, FlowSection, FlowOption, FlowCo
|
|
|
948
955
|
import type { createMatrix, MatrixOptions, MatrixApi } from "./matrix.js";
|
|
949
956
|
export { createMatrix } from "./matrix.js";
|
|
950
957
|
export type { MatrixDocument, MatrixAxis, MatrixItem, MatrixAttribute, MatrixState, MatrixSort, MatrixNote, MatrixQueryState, MatrixStateInput, MatrixCellDetail, MatrixOptions, MatrixApi } from "./matrix.js";
|
|
951
|
-
|
|
958
|
+
import type { createDiff, createChangeList, createPropagation, DiffOptions, DiffApi, ChangeListOptions, ChangeListApi, PropagationOptions, PropagationApi } from "./changes.js";
|
|
959
|
+
export { createDiff, createChangeList, createPropagation } from "./changes.js";
|
|
960
|
+
export type { ChangeNote, DiffHunk, DiffBody, DiffDocument, DiffOptions, DiffApi, ChangeVersion, ChangeItem, ChangeAction, ChangeListDocument, ChangeListState, ChangeActionDetail, ChangeExportDetail, ChangeListOptions, ChangeListApi, PropagationState, PropagationDocument, PropagationOptions, PropagationApi } from "./changes.js";
|
|
961
|
+
declare const gridRuntime: Omit<typeof CanopyX, "configure" | "mount"> & { createDataGrid: typeof createDataGrid; createCalendar: typeof createCalendar; createFlow: typeof createFlow; createMatrix: typeof createMatrix; createDiff: typeof createDiff; createChangeList: typeof createChangeList; createPropagation: typeof createPropagation; enhance: typeof enhance; grid: typeof grid; configure: typeof configure; mount: typeof mount };
|
|
952
962
|
export default gridRuntime;
|
|
@@ -11,6 +11,7 @@ const labels = Object.freeze({
|
|
|
11
11
|
searchWordTooShort: "Ein Wort mit mindestens {min} Zeichen eingeben",
|
|
12
12
|
searchFailed: "Suche fehlgeschlagen: {error}",
|
|
13
13
|
columns: "Spalten",
|
|
14
|
+
hiddenColumns: "[one]+{count} Spalte[other]+{count} Spalten",
|
|
14
15
|
gridFilters: "Filter",
|
|
15
16
|
gridFitContent: "An Inhalt anpassen",
|
|
16
17
|
gridUnpin: "Fixierung aufheben",
|
|
@@ -243,7 +244,7 @@ const labels = Object.freeze({
|
|
|
243
244
|
gridExportCancelled: "Export abgebrochen",
|
|
244
245
|
gridCancelExport: "Export abbrechen",
|
|
245
246
|
gridPrint: "Drucken",
|
|
246
|
-
gridCloseRecord: "
|
|
247
|
+
gridCloseRecord: "Schließen",
|
|
247
248
|
gridContains: "enthält",
|
|
248
249
|
gridStartsWith: "beginnt mit",
|
|
249
250
|
gridIn: "ist einer der Werte",
|
|
@@ -688,13 +689,86 @@ const labels = Object.freeze({
|
|
|
688
689
|
matrixItemTotal: "{item}: {count}",
|
|
689
690
|
matrixExpandGroup: "{group} aufklappen",
|
|
690
691
|
matrixCollapseGroup: "{group} zuklappen",
|
|
691
|
-
matrixGroupCount: "
|
|
692
|
+
matrixGroupCount: "{count}",
|
|
693
|
+
matrixCellCount: "Zellen: {count}",
|
|
692
694
|
matrixDetails: "Details",
|
|
693
695
|
matrixClose: "Schließen",
|
|
694
696
|
matrixValue: "Wert",
|
|
695
697
|
matrixState: "Zustand",
|
|
696
698
|
matrixAllClear: "Nichts erfordert Aufmerksamkeit",
|
|
697
699
|
matrixShowMore: "Mehr anzeigen",
|
|
700
|
+
changeInline: "Inline",
|
|
701
|
+
changeSplit: "Nebeneinander",
|
|
702
|
+
changeLayout: "Ansicht",
|
|
703
|
+
changeCopyDiff: "Diff kopieren",
|
|
704
|
+
changeCopied: "Kopiert",
|
|
705
|
+
changeCopyFailed: "Kopieren nicht möglich",
|
|
706
|
+
changeNext: "Nächste Änderung",
|
|
707
|
+
changePrevious: "Vorherige Änderung",
|
|
708
|
+
changePosition: "Änderung {index} von {count}",
|
|
709
|
+
changeShowLines: "[one]{count} weitere Zeile anzeigen[other]{count} weitere Zeilen anzeigen",
|
|
710
|
+
changeHiddenLines: "[one]{count} unveränderte Zeile nicht enthalten[other]{count} unveränderte Zeilen nicht enthalten",
|
|
711
|
+
changeLineCounts: "Hinzugefügte Zeilen: {added}, entfernte: {removed}",
|
|
712
|
+
changeLineAdded: "Hinzugefügte Zeile {line}",
|
|
713
|
+
changeLineRemoved: "Entfernte Zeile {line}",
|
|
714
|
+
changeLineContext: "Zeile {line}",
|
|
715
|
+
changeBefore: "Vorher",
|
|
716
|
+
changeAfter: "Nachher",
|
|
717
|
+
changeBinary: "Binärdatei: nach Größe und Hash verglichen, nicht zeilenweise.",
|
|
718
|
+
changeUnavailable: "Der Inhalt dieser Datei ist nicht verfügbar.",
|
|
719
|
+
changeIdentical: "Der Text hat sich nicht geändert.",
|
|
720
|
+
changeTruncated: "Einige Änderungen fehlen: Der Vergleich war zu groß.",
|
|
721
|
+
changeTooLarge: "Diese Texte sind zu lang, um sie hier zu vergleichen.",
|
|
722
|
+
changeDiffOf: "Änderungen in {name}",
|
|
723
|
+
changeAdded: "Hinzugefügt",
|
|
724
|
+
changeRemoved: "Entfernt",
|
|
725
|
+
changeModified: "Geändert",
|
|
726
|
+
changeRenamed: "Umbenannt",
|
|
727
|
+
changeFlaggedOnly: "Nur markierte",
|
|
728
|
+
changeFlaggedCount: "{count} markiert",
|
|
729
|
+
changeNoItems: "Keine Änderungen anzuzeigen.",
|
|
730
|
+
changeSize: "Größe",
|
|
731
|
+
changeHash: "Hash",
|
|
732
|
+
changeTime: "Zeit",
|
|
733
|
+
changeCopyHash: "Vollständigen Hash kopieren",
|
|
734
|
+
changeDetails: "Details zu {name}",
|
|
735
|
+
changeFileCount: "[one]{count} Datei[other]{count} Dateien",
|
|
736
|
+
changeFrom: "von {path}",
|
|
737
|
+
changeShowMore: "Mehr anzeigen",
|
|
738
|
+
changeFlags: "Markierungen",
|
|
739
|
+
changeFacts: "Details",
|
|
740
|
+
changeRoot: "Oberste Ebene",
|
|
741
|
+
changeShown: "{shown} von {total} angezeigt",
|
|
742
|
+
changeFilter: "Änderungen anzeigen",
|
|
743
|
+
changeActions: "Aktionen für {name}",
|
|
744
|
+
changeConverged: "Konvergiert",
|
|
745
|
+
changePropagating: "Wird repliziert",
|
|
746
|
+
changeFault: "Fehler",
|
|
747
|
+
changeUnknown: "Unbekannt",
|
|
748
|
+
changeReplica: "Replikat",
|
|
749
|
+
changeState: "Zustand",
|
|
750
|
+
changeFirstSeen: "Zuerst gesehen",
|
|
751
|
+
changeLastSeen: "Zuletzt gesehen",
|
|
752
|
+
changeTimeline: "Verzögerung",
|
|
753
|
+
changeNotSeen: "Noch nicht gesehen",
|
|
754
|
+
changeDelay: "+{duration}",
|
|
755
|
+
changeSource: "Quelle",
|
|
756
|
+
changeProgress: "{converged} von {total} haben die Änderung",
|
|
757
|
+
changeSeconds: "{count} s",
|
|
758
|
+
changeMinutes: "{count} Min.",
|
|
759
|
+
changeHours: "{count} Std.",
|
|
760
|
+
changeDays: "{count} T.",
|
|
761
|
+
changeUtcTime: "{time} UTC",
|
|
762
|
+
changeExportCsv: "CSV exportieren",
|
|
763
|
+
changeExportJson: "JSON exportieren",
|
|
764
|
+
changeReason: "Grund",
|
|
765
|
+
changeReasonHint: "{action}: Begründen Sie die Aktion. Der Grund wird mit ihr gespeichert.",
|
|
766
|
+
changeReasonRequired: "Geben Sie zuerst einen Grund ein.",
|
|
767
|
+
changeCancel: "Abbrechen",
|
|
768
|
+
changeUnclaimed: "Diese Seite kann „{action}“ nicht selbst ausführen. Kopieren Sie die Anfrage, um sie weiterzugeben.",
|
|
769
|
+
changeCopyRequest: "Anfrage kopieren",
|
|
770
|
+
changeFiltered: "Gefiltert: {filters}",
|
|
771
|
+
changePrintLimit: "{count} weitere Zeilen werden nicht gedruckt.",
|
|
698
772
|
});
|
|
699
773
|
const staticLabels = Object.freeze({
|
|
700
774
|
overflowNote: "{shown} Zeilen angezeigt. Gesamtzahl: {total}.",
|