@evotecit/canopyx 0.3.15 → 0.3.18
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-board.css +50 -0
- package/CanopyX.Html/Assets/canopyx-board.js +39 -0
- package/CanopyX.Html/Assets/canopyx-buckets.js +15 -0
- package/CanopyX.Html/Assets/canopyx-calculations.css +7 -0
- package/CanopyX.Html/Assets/canopyx-calculations.js +52 -0
- package/CanopyX.Html/Assets/canopyx-calendar-edit.js +3 -3
- package/CanopyX.Html/Assets/canopyx-calendar.css +5 -24
- package/CanopyX.Html/Assets/canopyx-calendar.js +14 -19
- package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
- package/CanopyX.Html/Assets/canopyx-changes.css +6 -24
- package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
- package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
- package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
- package/CanopyX.Html/Assets/canopyx-data.js +3 -3
- package/CanopyX.Html/Assets/canopyx-editing.css +2 -2
- package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
- package/CanopyX.Html/Assets/canopyx-enhance.js +4 -4
- package/CanopyX.Html/Assets/canopyx-export.js +54 -13
- package/CanopyX.Html/Assets/canopyx-facets.css +14 -5
- package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +71 -85
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
- package/CanopyX.Html/Assets/canopyx-flow-checks.css +2 -0
- package/CanopyX.Html/Assets/canopyx-flow-checks.js +5 -4
- package/CanopyX.Html/Assets/canopyx-flow-dialog.css +2 -0
- package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-entry.css +136 -12
- package/CanopyX.Html/Assets/canopyx-flow-entry.js +5 -5
- package/CanopyX.Html/Assets/canopyx-flow-facts.js +2 -0
- package/CanopyX.Html/Assets/canopyx-flow-module.mjs +5 -5
- package/CanopyX.Html/Assets/canopyx-flow.js +8 -7
- package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
- package/CanopyX.Html/Assets/canopyx-formatting.js +10 -9
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +185 -131
- package/CanopyX.Html/Assets/canopyx-grid.css +228 -96
- package/CanopyX.Html/Assets/canopyx-grid.js +185 -131
- package/CanopyX.Html/Assets/canopyx-grouping.css +22 -15
- package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
- package/CanopyX.Html/Assets/canopyx-interactive.css +197 -74
- package/CanopyX.Html/Assets/canopyx-interactive.js +38 -45
- package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
- package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
- package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
- package/CanopyX.Html/Assets/canopyx-layouts.css +48 -20
- package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
- package/CanopyX.Html/Assets/canopyx-link.js +2 -2
- package/CanopyX.Html/Assets/canopyx-live.css +1 -3
- package/CanopyX.Html/Assets/canopyx-live.js +20 -15
- package/CanopyX.Html/Assets/canopyx-matrix.css +1 -8
- package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
- package/CanopyX.Html/Assets/canopyx-module.mjs +38 -45
- package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
- package/CanopyX.Html/Assets/canopyx-path.css +45 -0
- package/CanopyX.Html/Assets/canopyx-path.js +28 -0
- package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
- package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
- package/CanopyX.Html/Assets/canopyx-plan.css +56 -0
- package/CanopyX.Html/Assets/canopyx-plan.js +67 -0
- package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
- package/CanopyX.Html/Assets/canopyx-record-panel.css +11 -2
- package/CanopyX.Html/Assets/canopyx-record-panel.js +18 -12
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +225 -164
- package/CanopyX.Html/Assets/canopyx-reporting.css +240 -107
- package/CanopyX.Html/Assets/canopyx-reporting.js +225 -164
- package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
- package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
- package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
- package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
- package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +36 -35
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
- package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
- package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
- package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
- package/CanopyX.Html/Assets/canopyx-ui-overlays.js +42 -0
- package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
- package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
- package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
- package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
- package/CanopyX.Html/Assets/canopyx-values.css +5 -0
- package/CanopyX.Html/Assets/canopyx-values.js +13 -0
- package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
- package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
- package/CanopyX.Html/Assets/canopyx.css +197 -71
- package/CanopyX.Html/Assets/canopyx.js +29 -19
- package/JavaScript/board.d.ts +30 -0
- package/JavaScript/changes.d.ts +4 -1
- package/JavaScript/facets.d.ts +5 -3
- package/JavaScript/flow.d.ts +6 -0
- package/JavaScript/grid.d.ts +153 -17
- package/JavaScript/hosts.d.ts +14 -1
- package/JavaScript/index.d.ts +4 -2
- package/JavaScript/live.d.ts +2 -0
- package/JavaScript/locales/de.mjs +177 -9
- package/JavaScript/locales/es.mjs +177 -9
- package/JavaScript/locales/fr.mjs +176 -8
- package/JavaScript/locales/it.mjs +176 -8
- package/JavaScript/locales/pl.mjs +176 -8
- package/JavaScript/matrix.d.ts +4 -1
- package/JavaScript/path.d.ts +33 -0
- package/JavaScript/pivot.d.ts +135 -0
- package/JavaScript/plan.d.ts +23 -0
- package/JavaScript/protocol.d.ts +16 -3
- package/JavaScript/records.d.ts +20 -4
- package/JavaScript/stack.d.ts +28 -0
- package/JavaScript/time-slider.d.ts +58 -0
- package/JavaScript/ui.d.ts +261 -0
- package/JavaScript/view-intents.d.ts +45 -0
- package/README.md +22 -3
- package/ThirdParty/OfficeIMO/LICENSE +21 -0
- package/ThirdParty/OfficeIMO/README.md +13 -0
- package/package.json +76 -3
|
@@ -75,7 +75,8 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
75
75
|
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];
|
|
76
76
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
77
77
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
78
|
-
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)=>{
|
|
78
|
+
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)=>{const uiLabel=/^(?:tabs(?:More(?:Selected)?|ScrollPrevious|ScrollNext|Section|Position|Pause|Play|MotionDisabled)|stepper(?:StepOf|Back|Next|Finish|Skip|SaveDraft|AllSteps|Optional|Completed|Skipped|Issues?)|dialogClose|drawer(?:Close|Previous|Next)|state(?:Loading|Retry|Details))$/.test(name);
|
|
79
|
+
if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change|board|plan|path|stack|time|compare|viewIntent)[A-Z]\w{0,63}$/.test(name) && !uiLabel) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
79
80
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
80
81
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
81
82
|
return Object.freeze(labels)}
|
|
@@ -95,7 +96,7 @@ function overlayTheme(host,element,inherit=false){for(const name of["data-hfx-st
|
|
|
95
96
|
const theme=getComputedStyle(host),parent=inherit&&host.parentElement&&getComputedStyle(host.parentElement);element.style.colorScheme=theme.colorScheme;const copied=[];for(const name of theme)if((name.startsWith("--cx-")||name.startsWith("--hfx-"))&&(!parent||theme.getPropertyValue(name)!==parent.getPropertyValue(name))){element.style.setProperty(name,theme.getPropertyValue(name));copied.push(name)}
|
|
96
97
|
return copied}
|
|
97
98
|
function watchOverlayTheme(host,element,signal){if(signal?.aborted)return()=>{};let copied=[];const refresh=()=>{for(const name of copied)element.style.removeProperty(name);copied=overlayTheme(host,element,element.parentElement===host.parentElement)};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:THEME_ATTRIBUTES});const media=["(prefers-color-scheme:dark)","(prefers-contrast:more)","(forced-colors:active)"].map(query=>matchMedia(query));for(const query of media)query.addEventListener("change",refresh);const dispose=()=>{observer.disconnect();for(const query of media)query.removeEventListener("change",refresh);signal?.removeEventListener("abort",dispose)};signal?.addEventListener("abort",dispose,{once:true});dispose.refresh=refresh;refresh();return dispose}
|
|
98
|
-
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:"
|
|
99
|
+
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:"CSV",gridCopy:"Copy",gridRows:"rows",gridUnknownCount:"Result count unavailable",gridDownloadXlsx:"Excel workbook (.xlsx)",gridDownloadPdf:"PDF",gridExportWorkbookHint:"Formatted, with groups and totals",gridExportPdfHint:"Paged report with repeating headings",gridExportCsvHint:"Plain text values (.csv)",gridExportCopy:"Copy to clipboard",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:"Changed fields: {count}"}));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();
|
|
99
100
|
}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(); }
|
|
100
101
|
else if(c==="]"){closed=true;break}}
|
|
101
102
|
if(!closed)bad()}else if("()|^$*+?{}]".includes(unit))bad();let count=1;if(i<source.length&&"*+?".includes(source[i])){variable++;i++}
|
|
@@ -141,15 +142,18 @@ if(typeof value!=="string"&&typeof value!=="boolean")throw new Error("CanopyX: t
|
|
|
141
142
|
function gridExactTokens(column){return column.kind==="text"&&(column.valueOrder?.length||Object.keys(column.valueLabels||{}).length)}
|
|
142
143
|
function cellMatches(cell,predicate,column){const scalar=gridScalar(cell,column),op=predicate.operator;if(op==="isNull")return scalar===null;if(op==="isNotNull")return scalar!==null;if(scalar===null)return false;const normalize=value=>column.kind==="text"&&!gridExactTokens(column)&&typeof value==="string"?foldText(value):value;const value=normalize(scalar),values=predicate.values.map(operand=>normalize(gridScalar(operand,column))),operand=values[0];switch(op){case "eq":return value===operand;case "ne":return value!==operand;case "in":return values.includes(value);case "contains":return String(value).includes(String(operand));case "startsWith":return String(value).startsWith(String(operand));case "gt":return value>operand;case "ge":return value>=operand;case "lt":return value<operand;case "le":return value<=operand}
|
|
143
144
|
return false}
|
|
144
|
-
function validateGridRows(rows,columns,ids=new Set()){if(!Array.isArray(rows))throw new Error("CanopyX: grid rows must be an array.");const declared=new Map(columns.map(column=>[column.id,column]));
|
|
145
|
-
throw new Error("CanopyX: invalid flat row fields.");
|
|
145
|
+
function validateGridRows(rows,columns,ids=new Set(),repair=null){if(!Array.isArray(rows))throw new Error("CanopyX: grid rows must be an array.");const declared=new Map(columns.map(column=>[column.id,column])),repaired=new Map();let result=rows;rows.forEach((row,index)=>{requireIdentifier(row&&row.id,"grid row ID");if(ids.has(row.id))throw new Error("CanopyX: duplicate grid row ID "+row.id);ids.add(row.id);if(!row.cells||typeof row.cells!=="object"||Array.isArray(row.cells))
|
|
146
|
+
throw new Error("CanopyX: invalid flat row fields.");let copy=null;const own=()=>copy||(result===rows&&(result=rows.slice()),result[index]=copy={...row,cells:{...row.cells}});try{gridDecoration(row.tone,row.className)}catch(error){if(!repair)throw error;delete own().tone;delete copy.className}
|
|
147
|
+
for(const id of Object.keys(row.cells)){const column=declared.get(id);try{if(!column)throw new Error("CanopyX: undeclared grid column "+id);validateGridCell(row.cells[id],column)}
|
|
148
|
+
catch(error){if(!repair)throw error;const cells=own().cells;if(column)cells[id]=repair(cells[id],column);else delete cells[id];const seen=repaired.get(id);if(seen)seen.count++;else repaired.set(id,{row:row.id,count:1})}}});for(const[id,seen]of repaired)
|
|
149
|
+
console.warn("CanopyX: "+seen.count+" cell(s) in column "+id+" did not fit the column and were coerced, emptied or dropped (first row "+seen.row+").");return result}
|
|
150
|
+
function validateGridCell(cell,column){if(isCellObject(cell)){if(Array.isArray(cell)||
|
|
146
151
|
["text","searchText","title","tone","secondary"].some(name=>cell[name]!==undefined&&typeof cell[name]!=="string")||
|
|
147
152
|
cell.secondary!==undefined&&cell.secondary.length>4096||cell.sort!==undefined&&!(typeof cell.sort==="string"?cell.sort.length<=4096:Number.isFinite(cell.sort))||cell.series!==undefined&&!gridSeriesValid(cell.series)||
|
|
148
153
|
cell.badges!==undefined&&(!Array.isArray(cell.badges)||cell.badges.some(badge=>!badge||typeof badge.text!=="string"||
|
|
149
154
|
["tone","title"].some(name=>badge[name]!==undefined&&typeof badge[name]!=="string"))))
|
|
150
155
|
throw new Error("CanopyX: malformed grid cell.");if(typeof cell.sort==="number")gridScalar(cell.sort,{kind:"number"})}
|
|
151
|
-
gridScalar(cell,
|
|
152
|
-
return rows}
|
|
156
|
+
gridScalar(cell,column)}
|
|
153
157
|
function gridDecoration(tone,className){if(tone!==undefined&&(typeof tone!=="string"||!/^[a-z][a-z0-9-]{0,31}$/.test(tone) || tone.endsWith("-bg")) ||
|
|
154
158
|
className!==undefined&&(typeof className!=="string"||!className.trim()||className.length>1024||/[\u0000-\u001f\u007f-\u009f]/.test(className)))
|
|
155
159
|
throw new Error("CanopyX: invalid highlight tone or className.")}
|
|
@@ -278,7 +282,7 @@ value.sort===undefined||typeof value!=="object")throw new Error("CanopyX: query
|
|
|
278
282
|
const named=new Set(value.filters);if(named.size!==value.filters.length||value.filters.some(id=>!(grid.view.filters||[]).some(f=>f.id===id)))
|
|
279
283
|
throw new Error("CanopyX: query filters must be unique declared IDs.");const filters=Object.freeze((grid.view.filters||[]).filter(f=>named.has(f.id)).map(f=>f.id));return Object.freeze({version:1,sort,filters})}
|
|
280
284
|
function snapshotRevision(value,expected){requireIdentifier(value&&value.revision,"dataset revision");if(expected!=null&&value.revision!==expected)throw new Error("CanopyX: dataset revision changed; reload the roots before continuing.");return value.revision}
|
|
281
|
-
Object.assign(TreeGrid.prototype,{getQuery(){return{version:1,sort:this.sortState&&Object.assign({},this.sortState),filters:Array.from(this.activeFilters)}},sourceRequest(signal){return this.queryAware?{signal:signal||this.dataLifetime.signal,query:this.acceptedQuery,revision:this.datasetRevision}:{signal}},syncQueryControls(){this.toolbar.querySelectorAll("[data-cx-filter]").forEach(input=>{input.checked=this.activeFilters.has(input.getAttribute("data-cx-filter"))})},querySortHeader(id){const query=this.pendingQuery||this.acceptedQuery,state=query.sort&&query.sort.column===id?query.sort.direction:null;this.sort(id,state==="asc"?"desc":state==="desc"?null:"asc").catch(()=>{})}});Object.assign(TreeGrid.prototype,{retireWrapper(w){w._invalidated=true;this.retirePage(w);if(this.inlineRetained&&this.inlineRetained.get(w.key)===w)this.inlineRetained.delete(w.key);if(this.inactiveCache)this.inactiveCache.delete(w);if(this.keyMap.get(w.key)===w)this.keyMap.delete(w.key);w.children=null;w.inlineCache=null;w.inlineOrder=null;const selected=this.selected.delete(w);if(this.anchor===w)this.anchor=null;return selected?w:null}});Object.assign(TreeGrid.prototype,{build(){const host=this.host;host.classList.add("cx-host");watchTheme(host,this.lifetime.signal);host.style.setProperty("--cx-row-h",this.rowH+"px");this.setTreeColumnPinned(this.view.pinTreeColumn);this.toolbar=h("div","cx-toolbar");this.toolbar.hidden=true;const grid=this.grid=h("div","cx-grid");grid.id=this.id;grid.setAttribute("role","treegrid");grid.setAttribute("aria-label",this.view.label);if(this.multi){grid.setAttribute("aria-multiselectable","true")}
|
|
285
|
+
Object.assign(TreeGrid.prototype,{getQuery(){return{version:1,sort:this.sortState&&Object.assign({},this.sortState),filters:Array.from(this.activeFilters)}},sourceRequest(signal){return this.queryAware?{signal:signal||this.dataLifetime.signal,query:this.acceptedQuery,revision:this.datasetRevision}:{signal}},syncQueryControls(){this.toolbar.querySelectorAll("[data-cx-filter]").forEach(input=>{input.checked=this.activeFilters.has(input.getAttribute("data-cx-filter"))})},querySortHeader(id){const query=this.pendingQuery||this.acceptedQuery,state=query.sort&&query.sort.column===id?query.sort.direction:null;this.sort(id,state==="asc"?"desc":state==="desc"?null:"asc").catch(()=>{})}});Object.assign(TreeGrid.prototype,{retireWrapper(w){w._invalidated=true;this.retirePage(w);if(this.inlineRetained&&this.inlineRetained.get(w.key)===w)this.inlineRetained.delete(w.key);if(this.inactiveCache)this.inactiveCache.delete(w);if(this.keyMap.get(w.key)===w)this.keyMap.delete(w.key);w.children=null;w.inlineCache=null;w.inlineOrder=null;const selected=this.selected.delete(w);if(this.anchor===w)this.anchor=null;return selected?w:null}});Object.assign(TreeGrid.prototype,{build(){const host=this.host;host.classList.add("cx-host");watchTheme(host,this.lifetime.signal);host.style.setProperty("--cx-row-h",this.rowH+"px");this.setTreeColumnPinned(this.view.pinTreeColumn);this.toolbar=h("div","cx-toolbar");this.toolbar.hidden=true;const grid=this.grid=h("div","cx-grid");grid.id=this.id;grid.setAttribute("role","treegrid");grid.setAttribute("data-cx-finish-allow","empty-band");grid.setAttribute("aria-label",this.view.label);if(this.multi){grid.setAttribute("aria-multiselectable","true")}
|
|
282
286
|
this.head=h("div","cx-head");this.head.setAttribute("role","rowgroup");this.headRow=h("div","cx-hrow");this.headRow.setAttribute("role","row");this.headRow.setAttribute("aria-rowindex","1");this.head.appendChild(this.headRow);this.canvas=h("div","cx-canvas");this.canvas.setAttribute("role","rowgroup");grid.appendChild(this.head);grid.appendChild(this.canvas);this.live=h("div","cx-live cx-sr-only");this.live.setAttribute("aria-live","polite");this.outline=h("div","cx-outline");host.appendChild(this.toolbar);host.appendChild(grid);host.appendChild(this.live);host.appendChild(this.outline);this.buildHeader();this.onScroll=()=>{this.scheduleRender();this.stateChanged()};this.onPrint=()=>{const table=this.outlineElement();this.outline.replaceChildren(...table?[table]:[])};grid.addEventListener("scroll",this.onScroll,{passive:true});grid.addEventListener("click",(e)=>this.onClick(e));grid.addEventListener("dblclick",(e)=>this.onDblClick(e));grid.addEventListener("pointerover",(e)=>this.cellTip(e));grid.addEventListener("keydown",(e)=>this.onKey(e));this.canvas.addEventListener("focusin",(e)=>{const rowEl=e.target.closest(".cx-row");if(rowEl&&rowEl._w&&this.focused!==rowEl._w){this.focusRevision=(this.focusRevision||0)+ 1;this.focused=rowEl._w;this.scheduleRender()}});this.canvas.addEventListener("focusout",(e)=>this.settleCell(e.relatedTarget));global.addEventListener("beforeprint",this.onPrint);this.onHash=(e)=>{const href=global.location.href;const last=this.locationEvent;this.locationEvent=last&&last.href===href&&last.type!==e.type?null:{href,type:e.type};if(this.locationEvent)this.readLocation()};global.addEventListener("hashchange",this.onHash);global.addEventListener("popstate",this.onHash);const viewWidth=()=>{if(grid.clientWidth)host.style.setProperty("--cx-view-w",grid.clientWidth+"px")};viewWidth();this.resizeObserver=new ResizeObserver(()=>{viewWidth();this.scheduleRender()});this.resizeObserver.observe(grid)},visibleColumns(){return this.columns.filter((column)=>!column.hidden)},buildHeader(){const active=document.activeElement;const focusedColumn=active&&this.headRow.contains(active)?active.closest(".cx-hcell").getAttribute("data-cx-column"):null;const focusedResize=active&&active.classList.contains("cx-resize");const nextCols=this.visibleColumns();const layoutChanged=!this.cols||this.cols.length!==nextCols.length||nextCols.some((column,i)=>column!==this.cols[i]);this.cols=nextCols;this.columnIndex=this.cols.map((column)=>this.columns.indexOf(column));if(layoutChanged){this.layout=(this.layout||0)+ 1;this.version++}
|
|
283
287
|
this.grid.setAttribute("aria-colcount",String(this.cols.length));this.headRow.textContent="";this.headCells=this.cols.map((column,i)=>{const cell=h("div","cx-hcell cx-kind-" +(column.kind||"text"));cell.setAttribute("role","columnheader");cell.setAttribute("aria-label",column.title);if(column.headerDescription)cell.setAttribute("aria-description",column.headerDescription);cell.title=column.headerDescription??column.title;cell.setAttribute("data-cx-column",column.id);cell.setAttribute("aria-colindex",String(i+1));if(column.sortable){const sorted=this.sortState&&this.sortState.column===column.id?this.sortState.direction:null;cell.setAttribute("aria-sort",sorted==="asc"?"ascending":sorted==="desc"?"descending":"none");const button=h("button","cx-sort");button.type="button";button.title=column.headerDescription??column.title;setText(button,column.title);button.addEventListener("click",(event)=>this.queryAware?this.querySortHeader(column.id,event):this.sort(column.id,sorted==="asc"?"desc":sorted==="desc"?null:"asc"));cell.appendChild(button)}else{const title=h("span","cx-htext");title.title=column.headerDescription??column.title;setText(title,column.title);cell.appendChild(title)}
|
|
284
288
|
const grip=h("span","cx-resize");grip.setAttribute("aria-label",fill(this.labels.resizeColumn,{column:column.title}));grip.tabIndex=0;grip.setAttribute("role","separator");grip.setAttribute("aria-orientation","vertical");grip.setAttribute("aria-valuemin",column.minW);grip.setAttribute("aria-valuemax",column.maxW);grip.addEventListener("keydown",(e)=>{if(!["ArrowLeft","ArrowRight","Home"].includes(e.key))return;e.preventDefault();e.stopPropagation();column.width=columnWidth(column,e.key==="Home"?40:column.width +(e.key==="ArrowLeft"?-1:1)*(e.shiftKey?50:10));this.applyWidths();this.stateChanged()});grip.addEventListener("pointerdown",(e)=>this.startResize(e,column));cell.appendChild(grip);this.headRow.appendChild(cell);return cell});this.applyWidths();if(focusedColumn){const index=this.cols.findIndex((c)=>c.id===focusedColumn);const button=index>=0?this.headCells[index].querySelector(focusedResize?".cx-resize":".cx-sort"):null;if(button){button.focus()}}},rowCount(){return this.rows.length},rowItem(index){return this.rows[index]},rowTop(index){return this.tops[index]},rowAt(y){const tops=this.tops;let lo=0;let hi=this.rows.length-1;while(lo<hi){const mid=(lo+hi+1)>>1;if(tops[mid]<=y){lo=mid}else{hi=mid-1}}
|
|
@@ -508,11 +512,10 @@ fill(this.labels.itemsLoaded,{count:count.format(items.length)}));this.stateChan
|
|
|
508
512
|
const exportFormatIds=list=>Array.isArray(list)&&new Set(list).size===list.length&&list.every(exportFormatId);function exportFormat(format){if(!format||!exportFormatId(format.id)||format.id==="csv"||
|
|
509
513
|
typeof format.label!=="string"||!format.label.trim()||typeof format.extension!=="string"||!/^[a-z\d]{1,16}$/i.test(format.extension) ||
|
|
510
514
|
format.mime!==undefined&&typeof format.mime!=="string"||
|
|
515
|
+
format.values!==undefined&&!["raw","display"].includes(format.values)||
|
|
511
516
|
format.showInMenu!==undefined&&typeof format.showInMenu!=="boolean"||typeof format.write!=="function")
|
|
512
|
-
throw new Error("CanopyX: invalid export format.");return Object.freeze({id:format.id,label:format.label,extension:format.extension,mime:format.mime||"application/octet-stream",showInMenu:format.showInMenu!==false,write:format.write})}
|
|
517
|
+
throw new Error("CanopyX: invalid export format.");return Object.freeze({id:format.id,label:format.label,extension:format.extension,mime:format.mime||"application/octet-stream",showInMenu:format.showInMenu!==false,values:format.values,write:format.write})}
|
|
513
518
|
function registerExportFormat(format){format=exportFormat(format);EXPORT_FORMATS.set(format.id,format);return()=>EXPORT_FORMATS.get(format.id)===format&&EXPORT_FORMATS.delete(format.id)}
|
|
514
|
-
EXPORT_IMPL.formatsOf=function(grid){const list=grid.opts.exportFormats??grid.view.exportFormats,known=new Map(EXPORT_FORMATS);for(const format of grid.plugins.filter(item=>(grid.opts.plugins||[]).some(local=>local.name===item.name))
|
|
515
|
-
.flatMap(item=>item.exportFormats||[]))known.set(format.id,exportFormat(format));if(list===undefined)return[...known.values()];const formats=Array.isArray(list)?list.map(item=>typeof item==="string"?known.get(item):exportFormat(item)).filter(Boolean):null;if(!formats||new Set(formats.map(format=>format.id)).size!==formats.length)throw new Error("CanopyX: invalid exportFormats.");return formats};function exportTimeout(grid,options){const timeout=options?.timeoutMs??grid.opts.exportTimeoutMs??600000;if(!Number.isInteger(timeout)||timeout<1||timeout>2147483647)throw new Error("CanopyX: invalid export timeout.");return timeout}
|
|
516
519
|
Object.assign(TreeGrid.prototype,{buildToolbar(){const bar=this.toolbar,tools=this.tools;if(this.view.search&&this.source.canSearch&&tools.search!==false)this.buildSearch(bar,this.view.search);if(tools.filters!==false)(this.view.filters||[]).forEach((filter)=>{if(filter.hidden)return;const label=h("label","cx-switch");const input=h("input");input.type="checkbox";input.setAttribute("data-cx-filter",filter.id);input.addEventListener("change",()=>{const pending=this.setFilterActive(filter.id,input.checked);if(pending&&pending.catch)pending.catch(()=>{})});label.appendChild(input);label.appendChild(document.createTextNode(filter.label));bar.appendChild(label)});this.syncToolbar();this.toolsReady=loadPart(TREE_TOOLS).then(()=>this.destroyed||this.installTools()).catch(error=>this.emit("error",{error}))},syncToolbar(){this.toolbar.hidden=!this.toolbar.firstChild||this.opts.toolbar===false},syncColumnControls(){},clearDeclaredFilters(){if(!this.activeFilters.size){return}
|
|
517
520
|
this.activeFilters.clear();this.toolbar.querySelectorAll("[data-cx-filter]").forEach((input)=>{input.checked=false});this.emit("filter",{active:[]});this.stateChanged()},buildSearch(bar,options){const box=h("div","cx-search");const input=h("input","cx-search-input");const list=h("ul","cx-results");const status=h("span","cx-sr-only");list.id=this.id+"-results";list.hidden=true;const labels=this.labels;const count=(value)=>numberFormat(this.lang).format(value);list.setAttribute("role","listbox");list.setAttribute("aria-label",labels.searchResults);input.type="search";input.placeholder=options.placeholder||labels.searchPlaceholder;input.setAttribute("aria-label",options.placeholder||labels.searchPlaceholder);input.setAttribute("role","combobox");input.setAttribute("aria-autocomplete","list");input.setAttribute("aria-expanded","false");input.setAttribute("aria-controls",list.id);status.setAttribute("aria-live","polite");let timer=0;let blurTimer=0;let sequence=0;let navigation=null;const cancelNavigation=()=>{if(navigation)navigation.abort()};let hits=[];let active=-1;const close=()=>{list.hidden=true;active=-1;input.setAttribute("aria-expanded","false");input.removeAttribute("aria-activedescendant")};const flyout=watchFlyout(box,list,()=>!list.hidden);this.disposeSearchFlyout=flyout.dispose;const choose=async(index)=>{const hit=hits[index];if(!hit){return}
|
|
518
521
|
cancelNavigation();const current=navigation=new AbortController();close();try{await this.expandPath(hit.path,{select:true,focus:true,signal:current.signal})}catch(err){if(!this.destroyed&&!current.signal.aborted)setText(status,fill(labels.searchFailed,{error:err.message}))}};const show=(result)=>{hits=result.hits||[];list.textContent="";hits.forEach((hit,index)=>{const item=h("li","cx-result");item.id=list.id+"-"+index;item.setAttribute("role","option");item.setAttribute("aria-selected","false");const label=h("span","cx-result-label");setText(label,hit.label);item.appendChild(label);if(hit.kind){const kind=h("span","cx-result-kind");setText(kind,hit.kind);item.appendChild(kind)}
|
|
@@ -524,8 +527,10 @@ fill(labels.searchFailed,{error:err&&err.message?err.message:err}))}}};const mov
|
|
|
524
527
|
if(active>=0){list.children[active].setAttribute("aria-selected","false")}
|
|
525
528
|
active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
|
|
526
529
|
close()}else{return}
|
|
527
|
-
e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const
|
|
528
|
-
|
|
530
|
+
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 lifetime=new AbortController();let flyout=null,pending=null;const ready=()=>flyout?Promise.resolve(flyout):pending||=loadPart(SHARED_PARTS["ui-overlays"]).then(()=>{if(!lifetime.signal.aborted)flyout=UI_TOOLS.toolbarFlyout(anchorElement,panel,isOpen,lifetime.signal);return flyout}).catch(error=>{pending=null;throw error});const invoke=method=>{if(lifetime.signal.aborted||!isOpen())return;if(flyout){flyout[method]();return}
|
|
531
|
+
ready().then(value=>{if(!lifetime.signal.aborted&&isOpen())value?.[method]()}).catch(error=>{if(!lifetime.signal.aborted)(anchorElement.closest(".cx-host")||anchorElement)
|
|
532
|
+
.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))})};return{position:()=>invoke("position"),open:()=>invoke("open"),close:()=>flyout?.close(),dispose:()=>lifetime.abort()}}
|
|
533
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"ui-overlays":["68a7687b9c3c8a28","canopyx-ui-overlays.83acc4346a232940.js","canopyx-ui-overlays.bc49b6f13527aecd.css"],"ui-menu":["c86ee2a16b5a5a46","canopyx-ui-menu.1414af91bc295de8.js","canopyx-ui-menu.29b983c01571b5c3.css"],"ui-picker":["02ff3779dd1c1ef4","canopyx-ui-picker.7fc22075e98b3e14.js","canopyx-ui-picker.a10010ec2d8143ae.css"],"ui-navigation":["e7815ee277df3a57","canopyx-ui-navigation.86b48ef9eaffe773.js","canopyx-ui-navigation.4dd22a646eb71b44.css"],"ui-tabs":["96f562187c7e0732","canopyx-ui-tabs.4ea5e653f6919c8e.js","canopyx-ui-tabs.68bc5521fcc174fe.css"],"ui-stepper":["89aeb7d73c4b8160","canopyx-ui-stepper.0198464c5b259da1.js","canopyx-ui-stepper.fe35ecb9b43b2b2e.css"],"tree-tools":["ab6490d0ae0e0aff","canopyx-tree-tools.23262806ed53e5de.js","canopyx-tree-tools.9c5a978314bf0a86.css"],"export":["fa85a4b0e8aead4a","canopyx-export.f18d1ef109ccf0c6.js"],"office-export":["4fb7a4d570390ee9","canopyx-office-export.7e62c385b884e75b.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["fd21dd4495607a16","canopyx-link.5874879aadd6cefb.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["077268d4fb78c464","canopyx-layouts.9a318c748cde4c84.js","canopyx-layouts.18dbf5842f1c5efd.css"],"record-panel":["2a4059ade4ca1439","canopyx-record-panel.4f525c01ecbd0e07.js","canopyx-record-panel.f1d740569605e625.css"]},PART_CODE=new Map(),SHARED_PARTS={},partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
529
534
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
530
535
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
531
536
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -534,8 +539,8 @@ script.textContent=trusted("Script",payload.textContent);script.nonce=payload.no
|
|
|
534
539
|
const load=(element,attribute,file,kind)=>new Promise((resolve,reject)=>{const url=new URL(file,runtime).href;element[attribute]=attribute==="src"?trusted("ScriptURL",url):url;element.onload=resolve;element.onerror=()=>{element.remove();reject(new Error("CanopyX: "+part.label+" "+kind+" unavailable."))};document.head.appendChild(withNonce(element))});const link=h("link");link.rel="stylesheet";const style=styleFile&&(part.styleReady||=load(link,"href",hashed?styleFile:"canopyx-"+part.name+".css","stylesheet")
|
|
535
540
|
.catch(error=>{part.styleReady=null;throw error}));const code=PART_CODE.get(part.name)?.version===part.version||(part.scriptReady||=load(script,"src",hashed?scriptFile:"canopyx-"+part.name+".js","script")
|
|
536
541
|
.finally(()=>script.remove()).catch(error=>{part.scriptReady=null;throw error}));await Promise.all([style,code])}}
|
|
537
|
-
const code=PART_CODE.get(part.name);if(code?.version!==part.version)throw new Error("CanopyX: "+part.label+" and runtime must come from the same build.");for(const name of code.requires||[])await loadPart(part.parts[name]);code.install(part.context())}).catch(error=>{part.ready=null;throw error})}
|
|
538
|
-
const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};const TREE_TOOLS=definePart(TreeGrid,"tree-tools","tree tools",()=>({TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,
|
|
542
|
+
const code=PART_CODE.get(part.name);if(code?.version!==part.version)throw new Error("CanopyX: "+part.label+" and runtime must come from the same build.");for(const name of code.requires||[])await loadPart(part.parts[name]||SHARED_PARTS[name]);code.install(part.context())}).catch(error=>{part.ready=null;throw error})}
|
|
543
|
+
const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};const TREE_TOOLS=definePart(TreeGrid,"tree-tools","tree tools",()=>({TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField,columnNumericTone,columnValueTone,overlayTheme,UI_IMPL,UI_TOOLS}));const SEARCH_IMPL={},SEARCH_PART=definePart(TreeGrid,"search","sidecar search",()=>({SEARCH_IMPL,checkDocument,badIndex,isCount,isIdentifier,recentCache,packBytes,shardKey,foldText,trimSeparators,rankHits,validateSearchHit,PACK_CACHE,PACK_CACHE_BYTES,SHARD_CACHE,ENTRY_CACHE,ENTRY_BATCH,SEARCH_CANDIDATES}));async function requirePart(name){await this.toolsReady;const part=Object.hasOwn(this.parts,name)?this.parts[name]:SHARED_PARTS[name];if(!part)throw new Error("CanopyX: unknown part '"+name+"'.");return loadPart(part)}
|
|
539
544
|
TreeGrid.prototype.requirePart=requirePart;function readStateColumn(c,seen){requireIdentifier(c&&c.id,"state column ID");if(seen.has(c.id)||!Number.isFinite(c.width)||c.width<40||c.width>MAX_COLUMN_WIDTH||typeof c.hidden!=="boolean")
|
|
540
545
|
throw new Error("CanopyX: invalid state column.");seen.add(c.id);return{id:c.id,width:c.width,hidden:c.hidden}}
|
|
541
546
|
function statePaths(value){if(!Array.isArray(value))throw new Error("CanopyX: state paths must be arrays.");return value.map(path=>{if(!Array.isArray(path)||!path.length)throw new Error("CanopyX: state paths cannot be empty.");return path.map(id=>{requireIdentifier(id,"state path ID");return id})})}
|
|
@@ -586,7 +591,12 @@ w.content=nodeContent(w.h)});this.inlineOrderVersion=(this.inlineOrderVersion||0
|
|
|
586
591
|
const wanted=Array.from(new Set(ids||this.rows.filter((w)=>!w.status).map((w)=>w.key)));const mine=new Map();for(const id of wanted){const w=this.keyMap.get(id);if(w){w.countRevision=(w.countRevision||0)+ 1;mine.set(id,{w,revision:w.countRevision})}}
|
|
587
592
|
const navigation=navigationScope(this,this.dataLifetime.signal);let doc;try{doc=await navigation.wait(this.source.counts(wanted,this.sourceRequest(this.dataLifetime.signal)))}
|
|
588
593
|
finally{navigation.dispose()}
|
|
589
|
-
if(navigation.cancelled())return null;if(this.queryAware)snapshotRevision(doc,this.datasetRevision);checkDocument(doc,"counts");this.applyCounts(Object.assign({},doc,{items:doc.items.filter(item=>{const captured=mine.get(item.id);return captured&&this.keyMap.get(item.id)===captured.w&&captured.w.countRevision===captured.revision})}),true);return doc}});
|
|
594
|
+
if(navigation.cancelled())return null;if(this.queryAware)snapshotRevision(doc,this.datasetRevision);checkDocument(doc,"counts");this.applyCounts(Object.assign({},doc,{items:doc.items.filter(item=>{const captured=mine.get(item.id);return captured&&this.keyMap.get(item.id)===captured.w&&captured.w.countRevision===captured.revision})}),true);return doc}});function UiHost(){}
|
|
595
|
+
const UI_IMPL={},UI_TOOLS={},uiInstances=new WeakMap();const UI_KINDS={tabs:"ui-tabs",stepper:"ui-stepper",menu:"ui-menu",dialog:"ui-overlays",drawer:"ui-overlays",popover:"ui-overlays",tooltip:"ui-overlays"};const uiContext=()=>({UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml});for(const name of["ui-overlays","ui-menu","ui-picker","ui-navigation","ui-tabs","ui-stepper"])SHARED_PARTS[name]=definePart(UiHost,name,name.replace("ui-","UI "),uiContext);function createUi(kind,target,options={}){const root=typeof target==="string"?document.querySelector(target):target;if(root?.nodeType!==1)throw new Error("CanopyX: "+kind+" needs an element.");let registrations=uiInstances.get(root);if(!registrations)uiInstances.set(root,registrations=new Map());if(registrations.has(kind))return registrations.get(kind);const lifetime=new AbortController();watchTheme(root,lifetime.signal);let instance=null;const ready=loadPart(SHARED_PARTS[UI_KINDS[kind]]).then(()=>{if(lifetime.signal.aborted)throw new DOMException("UI component destroyed.","AbortError");instance=UI_IMPL[kind](root,options,lifetime.signal);return instance.ready||instance});const api={element:root,ready:ready.then(()=>api),destroy(){if(lifetime.signal.aborted)return;lifetime.abort();instance?.destroy?.();registrations.delete(kind)}};for(const name of["select","getSelected","refresh","preparePrint","open","close","next","back","skip","finish","setStepState","getState"])api[name]=(...args)=>{if(lifetime.signal.aborted)throw new Error("CanopyX: UI component destroyed.");return instance?instance[name]?.(...args):ready.then(()=>instance[name]?.(...args))};api.ready.catch(error=>{if(error.name!=="AbortError")root.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});registrations.set(kind,Object.freeze(api));return api}
|
|
596
|
+
function bindContextMenu(target,items,options={}){if(typeof target!=="string"&&target?.nodeType!==1)throw new Error("CanopyX: contextMenu needs an element or selector.");if(typeof target==="string")document.documentElement.matches(target);let disposed=false,cleanup=null;const dispose=()=>{disposed=true;cleanup?.()};dispose.ready=loadPart(SHARED_PARTS["ui-menu"]).then(()=>{if(!disposed)cleanup=UI_IMPL.contextMenu(target,items,options)});dispose.open=(...args)=>disposed?false:cleanup?cleanup.open(...args):dispose.ready.then(()=>!disposed&&cleanup.open(...args));dispose.close=(...args)=>cleanup?.close(...args);return dispose}
|
|
597
|
+
function mountUi(root=document){const mounted=[];for(const kind of Object.keys(UI_KINDS)){const selector="[data-cx-"+kind+"]",nodes=[...root.querySelectorAll(selector)];if(root.matches?.(selector))nodes.unshift(root);for(const element of nodes){if(kind==="menu"&&element.parentElement?.closest(selector))continue;if(kind==="stepper"&&["report","static"].includes(element.dataset.mode))continue;mounted.push(createUi(kind,element))}}
|
|
598
|
+
return mounted}
|
|
599
|
+
const UI_API={mountUi,contextMenu:bindContextMenu};for(const kind of Object.keys(UI_KINDS))UI_API[kind]=(target,options)=>createUi(kind,target,options);const LINKS=definePart(TreeGrid,"links","deep links",()=>({TreeGrid,navigationScope}));for(const name of["openDeepLink","writeDeepLink"])TreeGrid.prototype[name]=function(...args){return this.view.deepLink?loadPart(LINKS).then(()=>this[name](...args),error=>this.emit("error",{error})):Promise.resolve()};TreeGrid.prototype.readLocation=function(){if(this.destroyed)return Promise.resolve();if(this.initializing){if(this.linkOpening&&this.currentLink()!==this.link){this.linkOpening.abort();this.link=null;// Deferred reopening must not reuse the canceled link if the address changes back.
|
|
590
600
|
}
|
|
591
601
|
this.linkChanged=this.dataLifetime.signal;return this.ready.then(()=>undefined,()=>undefined)}
|
|
592
602
|
return this.openDeepLink()};function sharedDensity(host){const value=host.closest("[data-hfx-density]")?.getAttribute("data-hfx-density");return value==="compact"||value==="comfortable"?value:null}
|
|
@@ -607,7 +617,7 @@ DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{linkFilteredBy:"Fi
|
|
|
607
617
|
linkMethods(TreeGrid);function linkGridPart(View){(Object.hasOwn(View.prototype,"parts")?View.prototype.parts:View.prototype.parts={}).link=LINK_PART}
|
|
608
618
|
function linkReady(grid,ready){return Promise.all([ready,grid.linkStart()]).then(([result])=>result)}
|
|
609
619
|
function linkApi(grid){const api={};for(const name of LINK_METHODS.concat("getExternalFilters","getHighlight"))api[name]=(...args)=>grid[name](...args);return api}
|
|
610
|
-
const RECORD_IMPL={},RECORD_PART=definePart(TreeGrid,"record-panel","record panel",()=>({RECORD_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,badgeElement,loadSidecar,requireIdentifier,validateGridRows,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField,columnNumericTone,columnValueTone,validateColumnValues}));function loadRecordPanel(){return loadPart(RECORD_PART)}
|
|
620
|
+
const RECORD_IMPL={},RECORD_PART=definePart(TreeGrid,"record-panel","record panel",()=>({RECORD_IMPL,UI_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,badgeElement,loadSidecar,requireIdentifier,validateGridRows,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField,columnNumericTone,columnValueTone,validateColumnValues}));function loadRecordPanel(){return loadPart(RECORD_PART)}
|
|
611
621
|
const RECORD_STRUCTURE=["items","fields","records","events","changes","ref"];TreeGrid.prototype.recordNeeded=function(node){return!!this.view.record||!!node&&(!!node.fields||Object.values(node.cells||{}).some(cell=>isCellObject(cell)&&RECORD_STRUCTURE.some(name=>cell[name]!==undefined)))};TreeGrid.prototype.openRecord=function(id,options){return loadRecordPanel().then(()=>RECORD_IMPL.open(this,id,options))};function recordStart(grid){if(grid.view.record?.deepLink)loadRecordPanel().then(()=>RECORD_IMPL.start(grid),error=>grid.emit("error",{error}))}
|
|
612
622
|
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{matchesHighlight:"Highlight matches",matchesCount:"[one]{count} match[other]{count} matches",matchesPosition:"{current} of {count}",matchesNone:"No matches",matchesLoaded:"[one]{count} match in loaded rows[other]{count} matches in loaded rows",matchesPrevious:"Previous match",matchesNext:"Next match",matchesAnnounce:"Match {current} of {count}, {column}",layoutMenu:"Layout",layoutFit:"Fit to width",layoutScroll:"All columns, scroll sideways",layoutCards:"Cards",layoutDensity:"Density",layoutCompact:"Compact",layoutNormal:"Normal",layoutComfortable:"Comfortable",layoutChanged:"Layout: {mode}, {density}",layoutSort:"Sort by"}));const LAYOUT_MODES=["fit","scroll","cards"],LAYOUT_DENSITIES=["compact","default","comfortable"];const DENSITY_STEP={tree:{compact:-8,default:0,comfortable:0},grid:{compact:-8,default:0,comfortable:0}};const VIEW_MODES={};const HIGHLIGHT_KEYS=["enabled","search","filters","matchCase","ignoreAccents","minLength","filterTones"];function readSearchHighlight(value,columns){if(value===undefined||value===false)return null;const options=value===true?{}:value,tone=name=>typeof name==="string"&&/^[a-z][a-z0-9-]{0,31}$/.test(name) && !name.endsWith("-bg");
|
|
613
623
|
if(!options||typeof options!=="object"||Array.isArray(options)||Object.keys(options).some(key=>!HIGHLIGHT_KEYS.includes(key))||
|
|
@@ -629,7 +639,7 @@ function densityRowHeight(view,density){const shared=sharedDensity(view.host);if
|
|
|
629
639
|
const VIEW_MODE_METHODS={prepareViewModes(){const view=this.view,columns=this.columns||view.columns;this.highlightOptions=readSearchHighlight(view.searchHighlight,columns);this.declaredDensity=this.kind==="grid"?view.density||"default":"default";this.layoutOptions=readLayout(view.layout,this.kind,this.declaredDensity);this.baseRowH=this.rowH;this.adoptModes({layout:this.layoutOptions||{mode:"fit",density:this.declaredDensity},highlight:!!this.highlightOptions?.enabled});watchSharedDensity(this)},adoptModes(choice){if(choice.layout){this.layoutMode=choice.layout.mode;this.density=choice.layout.density}
|
|
630
640
|
if(choice.highlight!==undefined)this.highlightOn=choice.highlight;this.rowH=densityRowHeight(this,this.density);if(this.layoutMode==="fit")this.host.removeAttribute("data-cx-layout");else this.host.setAttribute("data-cx-layout",this.layoutMode)},modeState(state){if(this.layoutOptions)state.layout={mode:this.layoutMode,density:this.density};if(this.highlightOptions)state.highlight=!!this.highlightOn;return state},applyModeState(state){if(state.layout&&(state.layout.mode!==this.layoutMode||state.layout.density!==this.density))
|
|
631
641
|
this.setLayout(state.layout).catch(error=>this.emit("error",{error}));if(state.highlight!==undefined&&state.highlight!==!!this.highlightOn)
|
|
632
|
-
this.setSearchHighlight(state.highlight).catch(error=>this.emit("error",{error}))},startViewModes(){const parts=[this.highlightOptions&&"highlight",this.layoutOptions&&"layouts"].filter(Boolean);return Promise.all(parts.map(name=>this.requirePart(name).then(()=>this.destroyed||VIEW_MODES[name+"Start"](this))
|
|
642
|
+
this.setSearchHighlight(state.highlight).catch(error=>this.emit("error",{error}))},startViewModes(){const parts=[this.highlightOptions&&"highlight",(this.layoutOptions||this.view.stickyHeader)&&"layouts"].filter(Boolean);return Promise.all(parts.map(name=>this.requirePart(name).then(()=>this.destroyed||VIEW_MODES[name+"Start"](this))
|
|
633
643
|
.catch(error=>this.emit("error",{error}))))},getLayout(){return Object.freeze({mode:this.layoutMode,density:this.density,modes:this.layoutOptions?this.layoutOptions.modes:Object.freeze(["fit"])})},setLayout(change){if(!this.layoutOptions)return Promise.reject(new Error("CanopyX: this view declares no layout modes."));return this.requirePart("layouts").then(()=>VIEW_MODES.setLayout(this,change))},getMatches(){return VIEW_MODES.matches?VIEW_MODES.matches(this):Object.freeze({enabled:!!this.highlightOn,total:0,current:0,complete:true})},setSearchHighlight(enabled){if(typeof enabled!=="boolean")return Promise.reject(new Error("CanopyX: the highlight switch is a boolean."));if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.setHighlight(this,enabled))},nextMatch(options){return this.stepMatch(1,options)},previousMatch(options){return this.stepMatch(-1,options)},stepMatch(direction,options){if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.step(this,direction,options?.focus!==false))}};Object.assign(TreeGrid.prototype,VIEW_MODE_METHODS);const viewModeContext=()=>({VIEW_MODES,TreeGrid,h,setText,fill,numberFormat,foldText,cellText,cellValue,isCellObject,setAttr,toneOf,toneVariable,watchFlyout,densityRowHeight,layoutAnchor,layoutRows,layoutApplyTree,MAX_PROTOCOL_INTEGER,LAYOUT_DENSITIES,plural,svgIcon});definePart(TreeGrid,"highlight","search highlighting",viewModeContext);definePart(TreeGrid,"layouts","layout modes",viewModeContext);const MODES_TOOLBAR=TreeGrid.prototype.buildToolbar;TreeGrid.prototype.buildToolbar=function(){MODES_TOOLBAR.call(this);if(this.highlightOptions||this.layoutOptions)this.modesReady=Promise.resolve(this.toolsReady).then(()=>this.destroyed||this.startViewModes());this.lifetime.signal.addEventListener("abort",()=>this.host.removeAttribute("data-cx-layout"),{once:true})};Object.assign(TreeGrid.prototype,{destroy(){if(this.destroyed)return;this.destroyed=true;for(const row of[...this.rendered.values(),...this.pool])disposeRowHostCells(row);this.lifetime.abort();this.dataLifetime.abort();if(this.queryController)this.queryController.abort();if(this.restoreController)this.restoreController.abort();if(this.cancelResize)this.cancelResize();clearTimeout(this.saveTimer);clearTimeout(this.layoutTimer);if(this.cancelSearch)this.cancelSearch();if(this.disposeSearchFlyout)this.disposeSearchFlyout();cancelAnimationFrame(this.rafId);this.resizeObserver.disconnect();if(this.detailObserver)this.detailObserver.disconnect();this.grid.removeEventListener("scroll",this.onScroll);this.grid.removeEventListener("wheel",this.onScaledWheel);this.grid.removeEventListener("touchstart",this.onScaledTouchStart);this.grid.removeEventListener("touchmove",this.onScaledTouchMove);this.grid.removeEventListener("touchend",this.onScaledTouchEnd);this.grid.removeEventListener("touchcancel",this.onScaledTouchEnd);global.removeEventListener("beforeprint",this.onPrint);global.removeEventListener("hashchange",this.onHash);global.removeEventListener("popstate",this.onHash);if(this.linkOpening)this.linkOpening.abort();[this.toolbar,this.grid,this.live,this.outline].forEach(element=>element.remove());this.host.classList.remove("cx-pin-tree");this.host.removeAttribute("data-cx-ready");this.host.removeAttribute("data-canopyx-mounted");this.keyMap.clear();this.selected.clear();this.rendered.clear();this.pool.length=0;if(this.inactiveCache)this.inactiveCache.clear();if(this.inlineRetained)this.inlineRetained.clear();this.rows=[];this.tops=[0];this.total=0;this.root.children=null;this.root.inlineCache=null;this.root.inlineOrder=null;this.focused=null;this.anchor=null;this.source=null;this.touchScroll=null;this.opts={};for(const column of this.columns)column.render=null;this.filter=null;this.declaredFilter=null;this.pendingRestorationToggles=null;this.scrolledCell=null;this.focusHandoff=null;this.cancelResize=null;this.cancelSearch=null;this.disposeSearchFlyout=null;this.canvas.replaceChildren();this.outline.replaceChildren()}});function createTreeGrid(host,options){if(!host||!options||!options.view){throw new Error("CanopyX: createTreeGrid needs a host element and a view document.")}
|
|
634
644
|
const existing=activeGrids.get(host);if(existing)return existing;const grid=new TreeGrid(host,options);const api=Object.assign({element:host,view:grid.view,ready:startPlugins(grid,()=>api),expandPath:(ids,o)=>grid.expandPath(ids,o),setFilter:(filter,o)=>{if(!grid.queryAware)grid.clearDeclaredFilters();grid.setFilter(filter,o)},setFilterActive:(id,active)=>grid.setFilterActive(id,active),setActiveFilters:(ids)=>grid.setActiveFilters(ids),updateActiveFilters:(change)=>grid.updateActiveFilters(change),getActiveFilters:()=>Array.from(grid.activeFilters),sort:(columnId,direction)=>grid.sort(columnId,direction),getQuery:()=>grid.getQuery(),setQuery:(query,options)=>grid.setQuery(query,options),setColumnVisible:(columnId,visible)=>grid.setColumnVisible(columnId,visible),setColumnWidth:(columnId,width)=>grid.setColumnWidth(columnId,width),setTreeColumnPinned:(pinned)=>grid.setTreeColumnPinned(pinned),setTimeZone:(zone)=>grid.setTimeZone(zone),getTimeZone:()=>(grid.local?"local":"utc"),refresh:()=>{grid.version++;grid.scheduleRender()},reload:(id,options)=>grid.reload(id,options),readLocation:()=>grid.readLocation(),getSelected:()=>Array.from(grid.selected).map((w)=>w.h),setSelection:(ids)=>grid.setSelection(ids),clearSelection:()=>grid.setSelection([]),selectAll:(options)=>grid.selectAll(options),focus:()=>{if(grid.destroyed)return;const target=grid.indexOf(grid.focused)>=0?grid.focused:grid.rows[0];if(target)grid.setFocus(target,true);else grid.grid.focus({preventScroll:true})},visibleRows:()=>grid.visibleRows(),toOutline:()=>grid.toOutline(),getState:()=>grid.getState(),setState:(state)=>grid.setState(state),getLayout:()=>grid.getLayout(),setLayout:(change)=>grid.setLayout(change),getMatches:()=>grid.getMatches(),setSearchHighlight:(enabled)=>grid.setSearchHighlight(enabled),nextMatch:(options)=>grid.nextMatch(options),previousMatch:(options)=>grid.previousMatch(options),search:(query,limit)=>grid.search(query,limit||(grid.view.search&&grid.view.search.maxResults)||20),loadMore:(id)=>{const w=id==null?grid.root:grid.keyMap.get(id);return w?grid.loadMore(w):Promise.resolve()},applyCounts:(doc)=>grid.applyCounts(doc),refreshCounts:(ids)=>grid.refreshCounts(ids),closeMenus:()=>grid.closeMenus?.(),destroy:()=>{grid.destroy();if(activeGrids.get(host)===api)activeGrids.delete(host);if(host.canopyx===api)delete host.canopyx}},grid.interactionApi&&grid.interactionApi(),linkApi(grid));for(const name of["prepareExport","exportAs","getSavedViews","saveView","applySavedView","removeSavedView","resetView","setColumnOrder","resetColumns","setColumnPinned","openDetails","openRecord"])
|
|
635
645
|
api[name]=(...args)=>{if(grid[name])return grid[name](...args);const error=new Error("CanopyX: "+name+" needs the tree tools part.");if(/^(exportAs|applySavedView|resetView|openDetails|openRecord)$/.test(name)) return Promise.reject(error);
|
|
@@ -644,5 +654,5 @@ watcher.observe(host)}
|
|
|
644
654
|
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}
|
|
645
655
|
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}}
|
|
646
656
|
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}
|
|
647
|
-
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}
|
|
648
|
-
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);
|
|
657
|
+
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)}});mountUi(scope);return created}
|
|
658
|
+
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:{},UI_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,30 @@
|
|
|
1
|
+
import type { CellValue } from "./protocol.js";
|
|
2
|
+
import type { GridCommit } from "./editing.js";
|
|
3
|
+
|
|
4
|
+
/** Optional board renderer over the grid's records and accepted query. */
|
|
5
|
+
export interface GridBoardDefinition {
|
|
6
|
+
/** Column whose raw scalar values identify the lanes. */
|
|
7
|
+
column: string;
|
|
8
|
+
titleColumn?: string;
|
|
9
|
+
swimlaneColumn?: string;
|
|
10
|
+
/** Up to eight card fields; the compact card displays the first two and the record panel exposes the rest. */
|
|
11
|
+
fields?: string[];
|
|
12
|
+
/** Permit drag, Alt+Left/Right and lane selection to propose an edit. Requires stable keys and an editable lane column. */
|
|
13
|
+
editable?: boolean;
|
|
14
|
+
/** Ordered lane labels and work limits. Values present in records add further lanes. */
|
|
15
|
+
lanes?: { value: CellValue; label: string; wipLimit?: number }[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** A move changes nothing until a host accepts it or the configured editing writer saves it. */
|
|
19
|
+
export interface GridBoardMove {
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly column: string;
|
|
22
|
+
readonly previous: CellValue;
|
|
23
|
+
readonly value: CellValue;
|
|
24
|
+
readonly proposal: GridCommit;
|
|
25
|
+
/** Accept with true; reject with false. One event responder may answer. */
|
|
26
|
+
respondWith(answer: boolean | PromiseLike<boolean>): void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Phone lane preference; saved views retain the same query, facets and columns as a grid. */
|
|
30
|
+
export interface GridBoardState { lane: string; }
|
package/JavaScript/changes.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TimePlaybackApi } from "./time-slider.js";
|
|
1
2
|
// Type declarations for the change views (docs/changes.md): a text diff, a change list and a propagation view.
|
|
2
3
|
|
|
3
4
|
/** A note about a change that the lines cannot show, such as changed line endings. */
|
|
@@ -237,10 +238,12 @@ export interface PropagationOptions {
|
|
|
237
238
|
|
|
238
239
|
/** The API of a propagation view. */
|
|
239
240
|
export interface PropagationApi {
|
|
241
|
+
/** Snapshot controls; available after ready when the document supplies timeSlider. */
|
|
242
|
+
readonly playback: TimePlaybackApi;
|
|
240
243
|
readonly element: HTMLElement;
|
|
241
244
|
readonly view: PropagationDocument;
|
|
242
245
|
readonly ready: Promise<PropagationApi>;
|
|
243
|
-
update(view: PropagationDocument): void
|
|
246
|
+
update(view: PropagationDocument): void | Promise<void>;
|
|
244
247
|
destroy(): void;
|
|
245
248
|
}
|
|
246
249
|
|
package/JavaScript/facets.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// The facet panel of flat grids (docs/facets.md): value lists with counts and ranges with histograms that filter each other.
|
|
2
|
-
import type { GridRow, GridColumnId } from "./grid.js";
|
|
2
|
+
import type { GridRow, GridColumnId, GridBucket } from "./grid.js";
|
|
3
3
|
|
|
4
4
|
/** One facet: a column id, or a column with its settings. */
|
|
5
5
|
export type GridFacet<Row extends GridRow = GridRow> = GridColumnId<Row> | {
|
|
6
6
|
column: GridColumnId<Row>;
|
|
7
|
+
/** Calendar or numeric partition, shown as a chronological value list. */
|
|
8
|
+
bucket?: GridBucket;
|
|
7
9
|
/** "list" (text columns by default) or "range" with a histogram (number and date columns by default). */
|
|
8
10
|
kind?: "list" | "range";
|
|
9
11
|
/** The facet's heading; the column's title by default. */
|
|
@@ -22,8 +24,8 @@ export type GridFacet<Row extends GridRow = GridRow> = GridColumnId<Row> | {
|
|
|
22
24
|
export interface GridFacetPanelDefinition<Row extends GridRow = GridRow> {
|
|
23
25
|
/** 1 to 24 distinct columns; a hosted grid's must be reporting facet columns. */
|
|
24
26
|
columns: readonly GridFacet<Row>[];
|
|
25
|
-
/** Beside the grid (default) or
|
|
26
|
-
position?: "side" | "top";
|
|
27
|
+
/** Beside the grid (default), above it, or as compact toolbar menus. */
|
|
28
|
+
position?: "side" | "top" | "toolbar";
|
|
27
29
|
/** Starts open (default true); the grid state keeps the reader's choice. */
|
|
28
30
|
open?: boolean;
|
|
29
31
|
/** The reader can collapse the panel (default true). */
|
package/JavaScript/flow.d.ts
CHANGED
|
@@ -150,6 +150,8 @@ export interface FlowStep {
|
|
|
150
150
|
title?: string;
|
|
151
151
|
description?: string;
|
|
152
152
|
type?: "form" | "info" | "pick" | "review";
|
|
153
|
+
/** Information steps: at most 32 read-only facts, with full wrapped plain-text values up to 32768 characters. Never submitted as answers. */
|
|
154
|
+
facts?: readonly { readonly label: string; readonly value: string }[];
|
|
153
155
|
fields?: readonly FlowField[];
|
|
154
156
|
sections?: readonly FlowSection[];
|
|
155
157
|
when?: FlowCondition;
|
|
@@ -261,6 +263,8 @@ export interface FlowHookContext { signal: AbortSignal }
|
|
|
261
263
|
|
|
262
264
|
/** The submit event's detail: the proposal, how to answer it, and each secret once. */
|
|
263
265
|
export interface FlowSubmitDetail extends Readonly<FlowSubmission> {
|
|
266
|
+
/** Retired when answers change, the flow resets/destroys, or the submission settles. Cancellation cannot undo a server write already committed. */
|
|
267
|
+
readonly signal: AbortSignal;
|
|
264
268
|
respondWith(answer: FlowAnswer | Promise<FlowAnswer>): void;
|
|
265
269
|
/** A secret's value, once per field, until the answer settles; null afterwards. */
|
|
266
270
|
secret(fieldId: string): string | null;
|
|
@@ -371,6 +375,8 @@ export interface FlowApi {
|
|
|
371
375
|
/** Runs a check now; resolves with its result as the flow keeps it (field messages show in place), or null when it was cancelled.
|
|
372
376
|
* Rejects for a check the flow does not have. */
|
|
373
377
|
runCheck(checkId: string): Promise<{ status: FlowCheckStatus; message: string | null; details: { label: string; value: string }[]; at: string } | null>;
|
|
378
|
+
/** Marks selected checks (all when omitted) stale after an external dependency changes. Cancels runs and ignores late answers without changing field values or dirty state. */
|
|
379
|
+
invalidateChecks(checkIds?: readonly string[]): void;
|
|
374
380
|
/** Loads a host-option field's options again. Rejects for any other field. */
|
|
375
381
|
refreshOptions(fieldId: string): Promise<void>;
|
|
376
382
|
/** Sets a task's state as the host sees it; null returns it to what the answers say. Throws for a flow that is no task list. */
|