@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
|
@@ -62,7 +62,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
62
62
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
63
63
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
64
64
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
65
|
-
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
65
|
+
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
66
66
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
67
67
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
68
68
|
return Object.freeze(labels)}
|
|
@@ -336,7 +336,7 @@ function hostRenderers(renderers,columns,plugins){if(![Object.prototype,null].in
|
|
|
336
336
|
Object.keys(renderers).some(id=>typeof renderers[id]!=="function"||!columns.some(column=>column.id===id)))
|
|
337
337
|
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])
|
|
338
338
|
.map(column=>({[column.id]:named[column.renderer]})),renderers)}
|
|
339
|
-
function disposeHostSlot(slot){const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
|
|
339
|
+
function disposeHostSlot(slot){slot.childSlots?.forEach(disposeHostSlot);const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
|
|
340
340
|
function disposeRowHostCells(row){row._cells?.forEach(disposeHostSlot)}
|
|
341
341
|
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}
|
|
342
342
|
get signal(){this.#controller||=new AbortController();if(this.#cleanups===null)this.#controller.abort();return this.#controller.signal}
|
|
@@ -506,7 +506,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
|
|
|
506
506
|
active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
|
|
507
507
|
close()}else{return}
|
|
508
508
|
e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
|
|
509
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["
|
|
509
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["4c6c4101089c4444","canopyx-tree-tools.510207e8f47014fd.js","canopyx-tree-tools.ef7a3fb9c9115a82.css"],"filter-editor":["8a058a87bbba3cbe","canopyx-filter-editor.15e355b04c7138cc.js","canopyx-filter-editor.01b7bb6820dc9edb.css"],"export":["8b99c0b7b0ec37c5","canopyx-export.6989ea36f5d6da7b.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["8f804f70b96409f2","canopyx-pager.ac543250cf2f6e8b.js","canopyx-pager.08ad67c69026852e.css"],"enhance":["31162b1ffa622bf8","canopyx-enhance.65868addbc5c4a1a.js"],"data":["f07aebe37f3d1bb4","canopyx-data.401d09bc34c61d2f.js"],"forms":["a8c60f205d9babca","canopyx-forms.16987de1cdf9bda9.js","canopyx-forms.29058ce3c88af96e.css"],"flow":["842e1f1956f6213f","canopyx-flow.efc6250968e8b10a.js","canopyx-flow.3152e616c5557452.css"],"flow-host":["de4f9b11ab881eca","canopyx-flow-host.aea5ed35816df2af.js","canopyx-flow-host.1301fcf3454a723a.css"],"flow-checks":["ec2451183901867b","canopyx-flow-checks.29c4586a80f04b6a.js","canopyx-flow-checks.4502d6f7f7487b73.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["426718e2fa1f3cd0","canopyx-flow-pick.379205e09325bca3.js","canopyx-flow-pick.771b06ac50c141a1.css"],"flow-records":["f3c09661bdffb8d0","canopyx-flow-records.fddf130ace0764b1.js","canopyx-flow-records.e362111fb5f85732.css"],"flow-drafts":["4f112f64736ca8e3","canopyx-flow-drafts.09b88e275c7bc3b9.js","canopyx-flow-drafts.2dd86fb31fc10458.css"],"flow-preview":["f4fb5c42743873c0","canopyx-flow-preview.5778d5fce9ae0d78.js","canopyx-flow-preview.7928e22901da2088.css"],"flow-command":["39472118ca80ef02","canopyx-flow-command.78f4f931c52b1bfc.js","canopyx-flow-command.0c1247a371b7e775.css"],"flow-tasks":["147dd31638a9cb94","canopyx-flow-tasks.f012a521560f7075.js","canopyx-flow-tasks.524df90f908f81dd.css"],"flow-dialog":["ebb432cd6e34aba6","canopyx-flow-dialog.b00addd6a176198e.js","canopyx-flow-dialog.e6192e827eca25d2.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"],"matrix":["16ab7faa98c96b46","canopyx-matrix.4d417eaeba54ca4f.js","canopyx-matrix.9b3f57c1d0f090b6.css"],"changes":["2db8e138da4b5658","canopyx-changes.053104f8f56b0a87.js","canopyx-changes.dfbdb3d6c468ccb1.css"],"editing":["c82648dfaa7e5ee5","canopyx-editing.4fe83feec389c2ce.js","canopyx-editing.67c43d3b80f20232.css"],"column-groups":["b42238fd108a8614","canopyx-column-groups.d8ad6322f769b915.js","canopyx-column-groups.37e177d74cebb516.css"],"cell-range":["e99a39e7cccc57b1","canopyx-cell-range.647da96e57924f3e.js","canopyx-cell-range.23f3222652588441.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["1a28068597f435de","canopyx-formatting.68c501f97b71f1ec.js","canopyx-formatting.a59507e4e8334891.css"],"format-editor":["24f176a39c02944a","canopyx-format-editor.3b1dec2527e53988.js","canopyx-format-editor.1ba153c82aa87b04.css"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"detail-rows":["4908d1d2b7f67aa8","canopyx-detail-rows.fe29b1759c962565.js","canopyx-detail-rows.8e38a8ad01fded76.css"],"grouping":["0970f2edbcb32de8","canopyx-grouping.84660cd1a0ea5f8f.js","canopyx-grouping.6c93259b4b89e523.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"facets":["f9219d35a87635f8","canopyx-facets.8bf477b7915bdcd6.js","canopyx-facets.648a88d2f36d4999.css"],"live":["a27c818b731c22e3","canopyx-live.d19df9edc92e7d09.js","canopyx-live.cc4b94a2dec6f064.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.css"],"calendar":["762f4b4b62ecb4d8","canopyx-calendar.dc45ebdeb704d9c3.js","canopyx-calendar.1099197a45632f63.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["bdde26d4b7de2096","canopyx-calendar-edit.4ab2cf55e84f310f.js"],"calendar-ics":["feb3ed2cd67d057f","canopyx-calendar-ics.2a3af9eb3bf444fc.js"],"timeline":["3f04ba99401e9ebd","canopyx-timeline.76928f089774b3de.js","canopyx-timeline.0393f92746f8fa09.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
510
510
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
511
511
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
512
512
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -604,7 +604,7 @@ function gridDateInputMoment(text,local){const match=/^(\d{4})-(\d{2})-(\d{2})T(
|
|
|
604
604
|
if(!match)return null;const moment=gridMomentFromParts(Number(match[1]),Number(match[2]),Number(match[3]),Number(match[4]),Number(match[5]),Number(match[6]||0),local);if(moment)moment.setTime(moment.getTime()+ Number((match[7]||"").padEnd(3,"0")));return moment}
|
|
605
605
|
function gridFreeze(value){if(value&&typeof value==="object"&&!Object.isFrozen(value)){Object.values(value).forEach(gridFreeze);Object.freeze(value)}
|
|
606
606
|
return value}
|
|
607
|
-
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridSelectionCount:"{count} selected",gridClearSelection:"Clear selection",gridSelectionQueryUnknown:"All matching records selected; {excluded} excluded",gridFitContent:"Fit to content",gridUnpin:"Unpin",gridWhere:"Where",gridComplexFilter:"This column belongs to a mixed condition group. Edit it in Filters.",gridPinLeft:"Pin left",gridPinRight:"Pin right",gridResponsiveHidden:"Hidden at this width",gridFilterMatch:"Match",gridFilterAll:"All",gridFilterAny:"Any",gridDeleteFilterGroup:"Remove condition group",gridFacetSearch:"Search values",gridFacetChoose:"Choose a value",gridFacetCounts:"{count} matching rows; {shown} of {total} values.",gridTrue:"True",gridFalse:"False",gridHeaderFilter:"Filter {column}",gridClearColumnFilter:"Clear filter",gridSelectionAggregate:"Count: {count} · Sum: {sum} · Average: {average} · Minimum: {minimum} · Maximum: {maximum}",gridConditionValue:"Value",gridConditionUpperValue:"Upper value",gridDeleteCondition:"Remove condition",gridShowRowsWhere:"Show rows where",gridOfTheseAreTrue:"of these are true",gridOfThese:"of these",gridGroupCount:"{count} groups",gridMore:"More",gridDone:"Done",gridClearAll:"Clear all",gridRows:"rows",gridResultNoun:"{count} of {total} {noun}",gridSearchNoun:"Search {noun}",gridChart:"Chart",gridPrint:"Print",gridRowPicked:"Picked up {title}. Move to a calendar and press Enter to drop it.",gridColumnMenu:"Menu for {column}",gridSortAscending:"Sort ascending",gridSortDescending:"Sort descending",gridClearSort:"Clear sort",gridFilterColumn:"Filter…",gridHideColumn:"Hide column",gridGroupedBy:"Grouped by",gridRemoveGrouping:"Remove grouping",gridSelectAllValues:"Select all values",gridFilterValues:"Search values",gridAddCondition:"+ Condition",gridAddGroup:"+ Group",gridAnd:"and",gridOr:"or",gridEditAsText:"Edit as text",gridFilterText:"Filter expression",gridDeepFilters:"This saved filter has more than two nesting levels.",gridToday:"Today",gridYesterday:"Yesterday",gridLastSevenDays:"Last 7 days",gridLastThirtyDays:"Last 30 days",gridThisMonth:"This month",gridDateRange:"Range",gridEmpty:"No {noun}",gridEmptyReason:"There are no records to display.",gridNoMatches:"No matching {noun}",gridNoMatchesReason:"Search: {search}. Active filters: {count}.",gridRetry:"Retry",gridLoadFailed:"Could not load records",gridAll:"All",gridPageOf:"{page} of {pages}",gridStatusCount:"{count} {noun} · {selected} selected",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close
|
|
607
|
+
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridSelectionCount:"{count} selected",gridClearSelection:"Clear selection",gridSelectionQueryUnknown:"All matching records selected; {excluded} excluded",gridFitContent:"Fit to content",gridUnpin:"Unpin",gridWhere:"Where",gridComplexFilter:"This column belongs to a mixed condition group. Edit it in Filters.",gridPinLeft:"Pin left",gridPinRight:"Pin right",gridResponsiveHidden:"Hidden at this width",gridFilterMatch:"Match",gridFilterAll:"All",gridFilterAny:"Any",gridDeleteFilterGroup:"Remove condition group",gridFacetSearch:"Search values",gridFacetChoose:"Choose a value",gridFacetCounts:"{count} matching rows; {shown} of {total} values.",gridTrue:"True",gridFalse:"False",gridHeaderFilter:"Filter {column}",gridClearColumnFilter:"Clear filter",gridSelectionAggregate:"Count: {count} · Sum: {sum} · Average: {average} · Minimum: {minimum} · Maximum: {maximum}",gridConditionValue:"Value",gridConditionUpperValue:"Upper value",gridDeleteCondition:"Remove condition",gridShowRowsWhere:"Show rows where",gridOfTheseAreTrue:"of these are true",gridOfThese:"of these",gridGroupCount:"{count} groups",gridMore:"More",gridDone:"Done",gridClearAll:"Clear all",gridRows:"rows",gridResultNoun:"{count} of {total} {noun}",gridSearchNoun:"Search {noun}",gridChart:"Chart",gridPrint:"Print",gridRowPicked:"Picked up {title}. Move to a calendar and press Enter to drop it.",gridColumnMenu:"Menu for {column}",gridSortAscending:"Sort ascending",gridSortDescending:"Sort descending",gridClearSort:"Clear sort",gridFilterColumn:"Filter…",gridHideColumn:"Hide column",gridGroupedBy:"Grouped by",gridRemoveGrouping:"Remove grouping",gridSelectAllValues:"Select all values",gridFilterValues:"Search values",gridAddCondition:"+ Condition",gridAddGroup:"+ Group",gridAnd:"and",gridOr:"or",gridEditAsText:"Edit as text",gridFilterText:"Filter expression",gridDeepFilters:"This saved filter has more than two nesting levels.",gridToday:"Today",gridYesterday:"Yesterday",gridLastSevenDays:"Last 7 days",gridLastThirtyDays:"Last 30 days",gridThisMonth:"This month",gridDateRange:"Range",gridEmpty:"No {noun}",gridEmptyReason:"There are no records to display.",gridNoMatches:"No matching {noun}",gridNoMatchesReason:"Search: {search}. Active filters: {count}.",gridRetry:"Retry",gridLoadFailed:"Could not load records",gridAll:"All",gridPageOf:"{page} of {pages}",gridStatusCount:"{count} {noun} · {selected} selected",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close",gridShowMore:"Show more",gridNoData:"No data",gridPeriodRange:"{from}–{to}: {state}",}));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)}
|
|
608
608
|
function gridDecorateButton(button,icon,ghost){button.classList.add("cx-btn");if(ghost)button.classList.add("ghost");if(icon)button.prepend(gridIcon(icon));return button}
|
|
609
609
|
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)}
|
|
610
610
|
const GRID_FILTER_LABELS={eq:"=",ne:"≠",contains:"gridContains",startsWith:"gridStartsWith",in:"gridIn",gt:">",ge:"≥",lt:"<",le:"≤",isNull:"gridIsNull",isNotNull:"gridIsNotNull"};function gridQueryRecord(input,record,strict,cursor){if(strict&&Object.keys(input).some(key=>!Object.hasOwn(record,key)&&!(cursor&&key==="offset")))throw new Error("CanopyX: invalid state query.");return gridFreeze(record)}
|
|
@@ -627,7 +627,10 @@ function gridQueryStart(query,patch){return{...query,...patch,offset:0,cursor:un
|
|
|
627
627
|
function gridNumberFormat(format){const minimum=format?.minimumFractionDigits??0,maximum=format?.maximumFractionDigits??3;if(!format||typeof format!=="object"||Array.isArray(format)||![minimum,maximum].every(digits=>Number.isInteger(digits)&&digits>=0&&digits<=10)||minimum>maximum||
|
|
628
628
|
Object.keys(format).some(key=>!["minimumFractionDigits","maximumFractionDigits","prefix","suffix"].includes(key))||
|
|
629
629
|
[format.prefix,format.suffix].some(text=>text!==undefined&&(typeof text!=="string"||!text||text.length>16)))throw new Error("CanopyX: invalid number format.")}
|
|
630
|
-
function validateGridView(view){checkDocument(view,"grid");requireIdentifier(view.id,"grid ID");if(
|
|
630
|
+
function validateGridView(view){checkDocument(view,"grid");requireIdentifier(view.id,"grid ID");if(view.rowIdentity!==undefined&&!["stableKey","ordinal"].includes(view.rowIdentity))
|
|
631
|
+
throw new Error("CanopyX: rowIdentity must be stableKey or ordinal.");if(view.rowIdentity==="ordinal"&&view.live)
|
|
632
|
+
throw new Error("CanopyX: ordinal row identity is snapshot-local; keyed live updates require stable row keys.");if(view.rowIdentity==="ordinal"&&view.record?.deepLink)
|
|
633
|
+
throw new Error("CanopyX: ordinal row identity is snapshot-local; record deep links require stable row keys.");if(typeof view.label!=="string"||!view.label.trim()||!Array.isArray(view.columns)||!view.columns.length)
|
|
631
634
|
throw new Error("CanopyX: a grid needs a label and columns.");if(view.reporting!==undefined){if(!GRID_REPORTING.validate)throw new Error("CanopyX: this view needs the reporting runtime.");GRID_REPORTING.validate(view)}
|
|
632
635
|
const ids=new Set();for(const column of view.columns){requireIdentifier(column&&column.id,"grid column ID");if(ids.has(column.id)||typeof column.title!=="string"||!["text","number","datetime"].includes(column.kind)||
|
|
633
636
|
column.width!==undefined&&(!Number.isInteger(column.width)||column.width<40)||
|
|
@@ -708,9 +711,10 @@ gridResultShape(gridColumnProjection(request.query,request.column))!==gridResult
|
|
|
708
711
|
throw new Error("CanopyX: facet counts contradict the known accepted dataset counts.");const keys=new Set();let occurrences=0;const items=input.items.map(item=>{if(!item||!Object.hasOwn(item,"value")||!Number.isInteger(item.count)||item.count<1||item.count>input.matched)
|
|
709
712
|
throw new Error("CanopyX: invalid facet value/count bucket.");const key=gridFacetKey(item.value,column);if(keys.has(key))throw new Error("CanopyX: duplicate typed facet bucket.");keys.add(key);occurrences +=item.count;return{value:item.value,count:item.count}});if(occurrences>input.matched||!request.search&&!input.truncated&&occurrences!==input.matched)
|
|
710
713
|
throw new Error("CanopyX: facet buckets contradict the matching row count.");return gridFreeze({protocol:PROTOCOL,type:"gridFacetPage",view:input.view,revision:input.revision,column:input.column,search:input.search,includeCurrentFilter:input.includeCurrentFilter,matched:input.matched,totalValues:input.totalValues,truncated:input.truncated,items})}
|
|
711
|
-
class DataGrid{constructor(host,options){const{rows,rowData,...definition}=validateGridView(options.view),owned=parsedViews.has(options.view);this.view=JSON.parse(JSON.stringify(definition));if(
|
|
714
|
+
class DataGrid{constructor(host,options){const{rows,rowData,...definition}=validateGridView(options.view),owned=parsedViews.has(options.view);this.view=JSON.parse(JSON.stringify(definition));if(this.view.rowIdentity==="ordinal"&&options.live)
|
|
715
|
+
throw new Error("CanopyX: ordinal row identity is snapshot-local; keyed live updates require stable row keys.");if(rows)this.view.rows=owned?rows:JSON.parse(JSON.stringify(rows));if(rowData){this.view.rowData=owned?rowData:structuredClone(rowData);this.view.rows=[]}
|
|
712
716
|
this.host=host;this.opts=options;this.id="cx" + ++instanceSeq;this.lifetime=new AbortController();this.dataLifetime=new AbortController();this.source=options.source||(this.view.source.kind==="inline"?this.view.rowData?rowDataSource(this):inlineGridSource(this.view):null);if(!this.source||typeof this.source.query!=="function")throw new Error("CanopyX: host grids need a query source.");this.cursor=this.view.source.navigation==="cursor";if(this.source.navigation!==undefined&&this.source.navigation!==(this.cursor?"cursor":"offset"))
|
|
713
|
-
throw new Error("CanopyX: source navigation must match the grid definition.");this.pageSize=this.view.pageSize;this.
|
|
717
|
+
throw new Error("CanopyX: source navigation must match the grid definition.");this.pageSize=this.view.pageSize;this.authoredAutoRows=this.view.rowHeight==="auto"||!!this.view.autoRowHeight;this.autoRows=this.authoredAutoRows;this.rowH=this.view.rowHeight==="auto"?this.view.estimatedRowHeight||28:this.view.rowHeight;this.rowHeights=new Map();this.paged=this.view.presentation==="paged";this.pageLength=this.view.pageLength||50;this.pageOffset=0;this.searchDelayMs=options.searchDelayMs===undefined?this.view.searchDelayMs===undefined?
|
|
714
718
|
this.view.source.kind==="inline"?0:300:this.view.searchDelayMs:options.searchDelayMs;if(!Number.isInteger(this.searchDelayMs)||this.searchDelayMs<0||this.searchDelayMs>5000)
|
|
715
719
|
throw new Error("CanopyX: search delay must be an integer from 0 to 5000 milliseconds.");this.cachePageLimit=options.cachePageLimit===undefined?40:options.cachePageLimit;this.requestTimeoutMs=options.requestTimeoutMs===undefined?rowData&&!options.source?2147483647:30000:options.requestTimeoutMs;if(!Number.isInteger(this.cachePageLimit)||this.cachePageLimit<2||this.cachePageLimit>1000||
|
|
716
720
|
!Number.isInteger(this.requestTimeoutMs)||this.requestTimeoutMs<1||this.requestTimeoutMs>2147483647)
|
|
@@ -726,7 +730,7 @@ async setQuery(input,paging){if(this.destroyed)throw new DOMException("Grid was
|
|
|
726
730
|
const same=this.acceptedQuery&&gridResultShape(initial)===gridResultShape(this.acceptedQuery)&&initial.revision===this.acceptedQuery.revision;let query=this.paged&&!this.cursor?gridQuery(this.view,{...initial,offset:same?Math.min(desired,Math.max(0,Math.ceil(this.rowCount()/ length) - 1) * length) : 0 }) : initial;
|
|
727
731
|
const epoch=++this.queryEpoch;clearTimeout(this.searchTimer);this.searchTimer=null;this.dataLifetime.abort();this.dataLifetime=new AbortController();const lifetime=this.dataLifetime;this.pendingPages.clear();this.pendingQuery=query;this.pendingPaging=paging?{...paging,pageLength:length}:null;this.setNotice(this.labels.loading,false);this.grid.setAttribute("aria-busy","true");this.syncPager();try{let page=(this.cursor?validateGridCursorPage:validateGridPage)(await this.requestPage(query,lifetime.signal),this.view,query,same?this.snapshot:null);if(this.cursor&&paging&&paging.direction)this.validateCursorTransition(page,paging);if(this.paged&&!this.cursor&&!same&&desired){gridOperationActive(this,lifetime.signal);const offset=Math.min(desired,Math.max(0,Math.ceil(page.matched / length) - 1) * length);
|
|
728
732
|
if(offset){const snapshot={revision:page.revision,total:page.total,matched:page.matched};query=gridQuery(this.view,{...query,offset,revision:page.revision});page=validateGridPage(await this.requestPage(query,lifetime.signal),this.view,query,snapshot)}}
|
|
729
|
-
gridOperationActive(this,lifetime.signal);const hadFocus=this.canvas.contains(document.activeElement),previousId=this.focused&&this.focused.key;this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.focused=null;this.acceptedQuery=gridQuery(this.view,{...query,revision:page.revision});this.snapshot={revision:page.revision,total:page.total,matched:page.matched};this.pageLength=length;if(paging)this.pageAll=!!paging.allRows;this.pageOffset=this.cursor?page.offset:this.paged?query.offset:0;if(this.cursor)this.cursorWindow={end:page.offset+page.items.length,next:page.nextCursor,previous:page.previousCursor};if(this.autoRows){if(!same)this.rowHeights.clear();this.rowOffsets=null}
|
|
733
|
+
gridOperationActive(this,lifetime.signal);const hadFocus=this.canvas.contains(document.activeElement),previousId=this.focused&&this.focused.key;const retireSelection=this.view.rowIdentity==="ordinal"&&this.snapshot&&this.snapshot.revision!==page.revision;this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.focused=null;this.acceptedQuery=gridQuery(this.view,{...query,revision:page.revision});this.snapshot={revision:page.revision,total:page.total,matched:page.matched};if(retireSelection)this.clearSnapshotSelection();this.pageLength=length;if(paging)this.pageAll=!!paging.allRows;this.pageOffset=this.cursor?page.offset:this.paged?query.offset:0;if(this.cursor)this.cursorWindow={end:page.offset+page.items.length,next:page.nextCursor,previous:page.previousCursor};if(this.autoRows){if(!same)this.rowHeights.clear();this.rowOffsets=null}
|
|
730
734
|
this.storePage(page);this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=null;this.lastFailedPaging=null;this.version++;const hasRows=this.cursor?page.items.length:page.matched;this.total=(this.cursor?page.items.length:this.paged?Math.min(length,page.matched-this.pageOffset):page.matched)*this.rowH;this.grid.setAttribute("aria-rowcount",page.matched===null?"-1":String(page.matched+1 +(this.headDepth||0)));this.grid.tabIndex=hasRows?-1:0;this.syncScrollRange(this.paged?0:query.offset*this.rowH);this.buildHeader();this.syncColumnControls();this.setNotice(hasRows?"":this.labels.searchNoResults,false);this.grid.setAttribute("aria-busy","false");if(hadFocus){this.focused=[...this.rowCache.values()].find(row=>row.key===previousId)||this.rowCache.get(this.cursor?page.offset:query.offset)||null}
|
|
731
735
|
this.render();if(hadFocus){const element=this.focused&&this.rendered.get(this.focused);(element||this.grid).focus({preventScroll:true})}
|
|
732
736
|
this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=initial;this.lastFailedPaging={...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(fill(this.labels.queryFailed,{error:error.message}),true);this.syncPager();this.emit("error",{error})}
|
|
@@ -745,8 +749,9 @@ render(){if(this.destroyed||!this.sized)return;let measured=false;if(this.autoRo
|
|
|
745
749
|
for(const[index,row]of this.placeholders)if(!this.rendered.has(row)&&this.focused!==row)this.placeholders.delete(index);this.loadWindow();return measured}
|
|
746
750
|
observeDetail(){}
|
|
747
751
|
trimInactiveCache(){this.trimPages()}
|
|
752
|
+
clearSnapshotSelection(){const changed=this.selected.size||this.querySelection;this.selectionController?.abort();this.selectionAnchor=null;this.querySelection=null;this.selectionExcluded=null;this.selected.clear();if(changed){this.version++;this.scheduleRender();this.emit("select",{ids:[]});this.syncGridChrome()}}
|
|
748
753
|
setSelection(ids){if(this.destroyed)return;if(!Array.isArray(ids))throw new Error("CanopyX: selection must be an array of row IDs.");ids.forEach(id=>requireIdentifier(id,"selection ID"));const next=new Set(ids);if(this.view.selection==="none"&&next.size||!this.multi&&next.size>1)throw new Error("CanopyX: selection exceeds the view's mode.");this.selected=next;this.version++;this.scheduleRender();this.emit("select",{ids:[...next]});this.syncGridChrome();this.stateChanged()}
|
|
749
|
-
setColumnVisible(id,visible){const column=this.columns.find(item=>item.id===id);if(!column||typeof visible!=="boolean")throw new Error("CanopyX: visibility needs a declared column and boolean.");if(!visible&&this.columns.filter(item=>!item.hidden).length===1&&!column.hidden)throw new Error("CanopyX: keep at least one column visible.");column.hidden=!visible;this.buildHeader();this.scheduleRender();this.stateChanged();this.syncColumnControls()}
|
|
754
|
+
setColumnVisible(id,visible){const column=this.columns.find(item=>item.id===id);if(!column||typeof visible!=="boolean")throw new Error("CanopyX: visibility needs a declared column and boolean.");if(!visible&&this.columns.filter(item=>!item.hidden).length===1&&!column.hidden)throw new Error("CanopyX: keep at least one column visible.");column.hidden=!visible;this.buildHeader();this.version++;this.scheduleRender();this.stateChanged();this.syncColumnControls()}
|
|
750
755
|
destroy(){if(this.destroyed)return;this.writeStoredState(this.getState());this.destroyed=true;this.queryEpoch++;this.lifetime.abort();this.dataLifetime.abort();for(const row of[...this.rendered.values(),...this.pool])disposeRowHostCells(row);if(this.rafId)cancelAnimationFrame(this.rafId);clearTimeout(this.searchTimer);this.searchTimer=null;clearTimeout(this.stateTimer);if(this.disposeControls)this.disposeControls();if(this.cancelResize)this.cancelResize();this.resizeObserver.disconnect();this.detailObserver?.disconnect();this.rowHeights?.clear();this.rowOffsets=null;this.restoreHeight();this.host.classList.remove("cx-data-grid","cx-chrome","cx-phone","cx-has-selection","cx-scroll-left","cx-scroll-right","cx-grid-awaiting","cx-pins");this.grid.removeEventListener("wheel",this.onScaledWheel);this.grid.removeEventListener("touchstart",this.onScaledTouchStart);this.grid.removeEventListener("touchmove",this.onScaledTouchMove);this.grid.removeEventListener("touchend",this.onScaledTouchEnd);this.grid.removeEventListener("touchcancel",this.onScaledTouchEnd);this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.pendingPages.clear();this.rendered.clear();this.pool.length=0;this.toolbar.remove();this.grid.remove();this.notice.remove();this.live.remove();this.querySummary?.remove();if(this.pager)this.pager.remove();this.statusBar?.remove();this.groupBar?.remove();this.statusAggregateController?.abort();this.host.removeAttribute("data-cx-ready");this.host.removeAttribute("data-canopyx-mounted")}}
|
|
751
756
|
Object.assign(DataGrid.prototype,ROW_SCROLLING,ROW_DOM_ORDER,ROW_VIEWPORT,ROW_HELPERS);Object.assign(DataGrid.prototype,{requestPage(query,signal){return this.runGridHook(signal=>this.source.query(query,{signal}),signal)},storePage(page){const rows=page.items.map((item,i)=>({key:item.id,h:item,_ri:page.offset+i,hpx:this.rowH}));const incoming=new Map(rows.map(row=>[row.key,row._ri]));for(const cached of this.rowCache.values())if(incoming.has(cached.key)&&incoming.get(cached.key)!==cached._ri)
|
|
752
757
|
throw new Error("CanopyX: inconsistent grid row identity.");for(const row of rows){const existing=this.rowCache.get(row._ri);if(existing&&existing.key!==row.key)throw new Error("CanopyX: inconsistent grid row identity.")}
|
|
@@ -791,17 +796,17 @@ this.activateRow(row,false)},{signal});grid.addEventListener("keydown",event=>th
|
|
|
791
796
|
this.canvas.addEventListener("focusin",event=>{const element=event.target.closest(".cx-row");if(element&&element._w&&this.pendingNavigation&&this.pendingQuery&&element._w._ri!==this.pendingNavigation.index)
|
|
792
797
|
this.pendingNavigation=null;if(element&&element._w&&this.focused!==element._w){this.pendingNavigation=null;this.focused=element._w;this.scheduleRender()}},{signal});document.addEventListener("focusin",event=>{if(this.pendingNavigation&&this.pendingNavigation.focus&&!this.canvas.contains(event.target))this.pendingNavigation=null},{signal});this.canvas.addEventListener("focusout",event=>this.settleCell(event.relatedTarget),{signal});this.sized=this.hasGridSize();this.resizeObserver=new ResizeObserver(()=>requestAnimationFrame(()=>{if(this.destroyed)return;if(!grid.clientWidth||!grid.checkVisibility()){this.sized=false;return}
|
|
793
798
|
style.setProperty("--cx-min-h",(this.toolbar.hidden?0:[...host.children].reduce((height,child)=>
|
|
794
|
-
height +(child===grid?0:child.offsetHeight),this.rowH*Math.min(4,Math.max(1,this.rowCount()))+ 2))+ "px");if(!(this.sized=this.hasGridSize()))return;this.applyWidths();this.updateGridPhone();this.fitHeight();this.viewportHeight=grid.clientHeight-this.head.offsetHeight;if(this.hiddenScrollTop!==undefined){const top=this.hiddenScrollTop;delete this.hiddenScrollTop;this.setLogicalTop(top)}
|
|
799
|
+
height +(child===grid?0:child.offsetHeight),this.rowH*Math.min(4,Math.max(1,this.rowCount()))+ 2))+ "px");this.fitHeight();if(!(this.sized=this.hasGridSize()))return;this.applyWidths();this.updateGridPhone();this.fitHeight();this.viewportHeight=grid.clientHeight-this.head.offsetHeight;if(this.hiddenScrollTop!==undefined){const top=this.hiddenScrollTop;delete this.hiddenScrollTop;this.setLogicalTop(top)}
|
|
795
800
|
this.scheduleRender()}));this.resizeObserver.observe(grid);this.resizeObserver.observe(this.head)},setLogicalTop(top){if(!this.hasGridSize()){this.hiddenScrollTop=top;return}
|
|
796
|
-
return ROW_SCROLLING.setLogicalTop.call(this,top)},logicalTop(){return this.hiddenScrollTop??ROW_SCROLLING.logicalTop.call(this)},hasGridSize(){return!!(this.grid.clientWidth&&this.grid.clientHeight&&this.grid.checkVisibility())},buildHeader(){const sorts=this.acceptedQuery?this.acceptedQuery.sort:[];this.sortState=sorts[0]||null;ROW_HELPERS.buildHeader.call(this);for(const cell of this.headCells){const
|
|
801
|
+
return ROW_SCROLLING.setLogicalTop.call(this,top)},logicalTop(){return this.hiddenScrollTop??ROW_SCROLLING.logicalTop.call(this)},hasGridSize(){return!!(this.grid.clientWidth&&this.grid.clientHeight&&this.grid.checkVisibility())},buildHeader(){const sorts=this.acceptedQuery?this.acceptedQuery.sort:[];this.sortState=sorts[0]||null;ROW_HELPERS.buildHeader.call(this);for(const cell of this.headCells){const button=cell.querySelector(".cx-sort");if(button){const label=h("span","cx-htext");setText(label,button.textContent);button.replaceChildren(label)}
|
|
802
|
+
const index=sorts.findIndex(sort=>sort.column===cell.getAttribute("data-cx-column"));if(index>=0){cell.setAttribute("aria-sort",sorts.length===1?sorts[index].direction==="asc"?"ascending":"descending":"other");cell.setAttribute("data-cx-sort",sorts[index].direction);cell.setAttribute("data-cx-sort-priority",String(index+1));button.setAttribute("data-cx-sort-priority",String(index+1));if(sorts.length>1){const priority=h("sup","cx-sort-priority");setText(priority,String(index+1));button.appendChild(priority)}
|
|
797
803
|
button.setAttribute("aria-label",cell.getAttribute("aria-label")+ ", "+sorts[index].direction+", " +(index+1))}}
|
|
798
804
|
this.buildHeaderSelection?.();this.buildColumnMenus?.()},cellOf(row,column){return row.cells[column.id]},refreshRowState(element,row){setAttr(element,"aria-selected",row.status||this.view.selection==="none"?null:String(this.selected.has(row.key)))},fillRow(element,row){const kind=row.status?"status":"node";element._w=row;if(element._kind!==kind||element._layout!==this.layout){disposeRowHostCells(element);element.textContent="";element._kind=kind;element._layout=this.layout;element._attrs={};element._cls=null;element.setAttribute("role","row");element.style.height=this.rowH+"px";element.style.width=this.rowWidth+"px";element._cells=(row.status?[null]:this.cols).map((column,index)=>{const cell=this.cell(element,index,column?column.width:this.rowWidth,column?column.kind:null);if(!column)cell.setAttribute("aria-colspan",String(this.cols.length));const content=index===0&&column?.render&&this.view.reporting?.selectionControls?cell.appendChild(h("span","cx-content")):cell;const slot={cell,content,base:cell.className +(column?.wrap?" cx-wrap":""),cls:null,title:null,badges:[],mode:"default"};slot.textSpan=content.appendChild(h("span","cx-text"));slot.text=slot.textSpan.appendChild(document.createTextNode(""));return slot})}
|
|
799
|
-
setClass(element,"cx-row" +(row.status?" cx-status cx-"+row.status:this.autoRows?" cx-auto-row":""));if(this.autoRows){element.style.height=row.status?this.rowH+"px":"auto";this.observeDetail(element,!row.status);this.measureNeeded=true}
|
|
800
|
-
setAttr(element,"data-cx-id",row.key||null);setAttr(element,"data-cx-status",row.status||null);setAttr(element,"draggable",this.view.dragRows&&!row.status?"true":null);setAttr(element,"aria-busy",row.status==="loading"?"true":null);this.refreshRowState(element,row);if(row.status)element._cells[0].text.data=row.status==="error"?fill(this.labels.loadError,{error:((this.pages.get(Math.floor(row._ri / this.pageSize) * this.pageSize) || {}).error || {}).message || ""
|
|
805
|
+
setClass(element,"cx-row" +(row.status?" cx-status cx-"+row.status:this.autoRows?" cx-auto-row":""));if(this.autoRows){element.style.height=row.status?this.rowH+"px":"auto";this.observeDetail(element,!row.status);this.measureNeeded=true}else element.style.height=this.rowH+"px";setAttr(element,"data-cx-id",row.key||null);setAttr(element,"data-cx-status",row.status||null);setAttr(element,"draggable",this.view.dragRows&&!row.status?"true":null);setAttr(element,"aria-busy",row.status==="loading"?"true":null);this.refreshRowState(element,row);if(row.status)element._cells[0].text.data=row.status==="error"?fill(this.labels.loadError,{error:((this.pages.get(Math.floor(row._ri / this.pageSize) * this.pageSize) || {}).error || {}).message || ""
|
|
801
806
|
}):this.labels.loading;else for(let i=0;i<this.cols.length;i++){const slot=element._cells[i];if(slot.highlighted){slot.cls=null;slot.highlighted=false}
|
|
802
807
|
const column=this.cols[i];this.paintSlot(slot,row.h,column,this.columnIndex[i],row);if(!column.render&&!slot.text.data){slot.text.data="—";slot.cell.classList.add("p-missing");slot.missing=true}
|
|
803
808
|
else if(slot.missing){slot.cell.classList.remove("p-missing");slot.missing=false}
|
|
804
|
-
if(this.phone||slot.hiddenFields)this.paintHiddenFields?.(slot,row.h,column,this.columnIndex[i])}
|
|
809
|
+
if(this.phone||slot.hiddenFields||slot.phonePrimary)this.paintHiddenFields?.(slot,row.h,column,this.columnIndex[i])}
|
|
805
810
|
this.paintGridHighlights(element,row);if(row.status)this.paintGridSkeleton(element,row)}});class AxisWindow{constructor(){this.count=0;this.uniform=0;this.offsets=null;this.total=0}
|
|
806
811
|
reset(sizes,count){if(typeof sizes==="number"){this.count=count;this.uniform=sizes;this.offsets=null;this.total=count*sizes}else{const offsets=new Float64Array(sizes.length+1);for(let index=0;index<sizes.length;index++)offsets[index+1]=offsets[index]+ sizes[index];this.count=sizes.length;this.uniform=0;this.offsets=offsets;this.total=offsets[sizes.length]}
|
|
807
812
|
return this}
|
|
@@ -822,16 +827,17 @@ this.total=this.rowOffsets.top(count);this.syncScrollRange(this.logicalTop());th
|
|
|
822
827
|
if(changed){this.total=this.rowOffsets.top(this.rowOffsets.count);this.syncScrollRange(rows.rowTop(anchor.index)+ anchor.offset)}
|
|
823
828
|
return changed},revealGridRow(row,index,rows=this){const top=rows.rowTop(index),viewport=Math.max(0,this.grid.clientHeight-this.head.offsetHeight);if(top<this.logicalTop())this.setLogicalTop(top);else if(top+Math.min(row.hpx,viewport)>this.logicalTop()+ viewport)this.setLogicalTop(top+Math.min(row.hpx,viewport)- viewport)},gridPageStep(row,direction,rows=this){const index=this.rowProjection?rows.indexOf(row):row._ri;if(!this.autoRows)return index+direction*Math.max(1,Math.floor((this.grid.clientHeight-this.head.offsetHeight)/ this.rowH));
|
|
824
829
|
const proposed=rows.rowAt(Math.max(0,rows.rowTop(index)+ direction*(this.grid.clientHeight-this.head.offsetHeight)));return direction>0?Math.max(index+1,proposed):Math.min(index-1,proposed)}});const HEIGHT_RENDER=DataGrid.prototype.render;DataGrid.prototype.render=function(){const measured=HEIGHT_RENDER.call(this);if(this.sized&&this.total!==this.fitTotal){this.fitTotal=this.total;this.fitHeight()}
|
|
825
|
-
return measured};DataGrid.prototype.fitHeight=function(){if(this.view.autoHeight===false||!this.
|
|
830
|
+
return measured};DataGrid.prototype.fitHeight=function(){if(this.view.autoHeight===false||this.pendingQuery||!this.grid.clientWidth||!this.host.checkVisibility())return;const grid=this.grid,style=this.host.style,box=grid.getBoundingClientRect(),computed=getComputedStyle(grid);const borders=parseFloat(computed.borderTopWidth)+ parseFloat(computed.borderBottomWidth);const scrollbar=grid.scrollWidth>grid.clientWidth?Math.max(0,grid.offsetHeight-grid.clientHeight-borders):0;const content=[...grid.children].reduce((sum,child)=>sum+child.getBoundingClientRect().height,borders+scrollbar);if(this.fitInline===undefined){const own=getComputedStyle(this.host).maxHeight;this.fitInline=style.maxHeight;this.fitMax=own==="none"||!own?Infinity:/^-?[\d.]+px$/.test(own) ? parseFloat(own) : own;
|
|
826
831
|
}
|
|
827
|
-
const height=Math.ceil(this.host.
|
|
832
|
+
const hostStyle=getComputedStyle(this.host);const chrome=[...this.host.children].filter(child=>child!==grid).reduce((sum,child)=>{const css=getComputedStyle(child);return css.position==="absolute"||css.position==="fixed"?sum:sum+child.getBoundingClientRect().height},parseFloat(hostStyle.borderTopWidth)+ parseFloat(hostStyle.borderBottomWidth)+ parseFloat(hostStyle.paddingTop)+ parseFloat(hostStyle.paddingBottom));const height=Math.ceil(Math.max(this.host.getBoundingClientRect().height-box.height,chrome)+ content),bound=this.fitMax;const value=!this.rowCount()?this.fitInline:typeof bound==="number"?Math.min(bound,height)+ "px":"min("+height+"px, "+bound+")";if(this.host.style.maxHeight!==value)this.host.style.maxHeight=value};function gridPriority(value){return["essential","normal","optional"].includes(value)||Number.isInteger(value)&&value>=0&&value<=MAX_PROTOCOL_INTEGER}
|
|
828
833
|
function gridRank(column){const value=column.priority;return typeof value==="number"?value:value==="optional"?10000:value==="essential"||value===undefined&&column.identity?0:5000}
|
|
829
834
|
function gridLevel(column){const rank=gridRank(column);return rank<2?0:rank<10000?1:2}
|
|
830
835
|
function gridOptions(column){return column.presenter||{}}
|
|
831
836
|
const COLUMN_DIGITS=new Map(),COLUMN_NUMERIC_CHARS="0123456789 .,:;+-−/()[]\u00a0\u202f",COLUMN_HAS_NUMERIC=/[0-9\s.,:;+\-−/()\[\]]/;
|
|
832
837
|
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)}
|
|
833
838
|
const variant=getComputedStyle(sample).fontVariantNumeric;if(owned)sample.remove();return variant}
|
|
834
|
-
function gridClassFont(grid,className){const probe=
|
|
839
|
+
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}
|
|
840
|
+
probe.remove();return font}
|
|
835
841
|
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())}
|
|
836
842
|
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)}
|
|
837
843
|
document.body.appendChild(probe);const zero=glyphs[0].getBoundingClientRect().width / 50, numeric = new Map(), plain = new Map();
|
|
@@ -853,23 +859,30 @@ return excess},fitSpare(columns,spare){let target,flex=columns.filter(column=>co
|
|
|
853
859
|
flex=flex.filter(column=>column.maxW-column.renderWidth>0.5)}
|
|
854
860
|
const identity=columns.find(column=>column.identity),widest=columns.filter(column=>!column.identity&&
|
|
855
861
|
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));
|
|
856
|
-
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 +=
|
|
857
|
-
if(total>width&&remaining>1){column.fitHidden=true;total -=
|
|
858
|
-
if(identity&&!identity.fixed&&!identity.sized)total +=Math.min(identity.need??identity.width,(identity.indentNeed||0)+ 2*(this.fitCh||88))+(identity.reserve||0)-
|
|
859
|
-
if(total>width){column.fitHidden=true;total -=
|
|
862
|
+
grow(identity,Infinity);grow(widest,Infinity);return target},fitHide(shown,width,phone,size=column=>this.fitSize(column,1)){let total=0,remaining=shown.length;const order=(a,b)=>gridLevel(b)- gridLevel(a)||gridRank(b)- gridRank(a)||shown.indexOf(b)- shown.indexOf(a),identity=phone&&shown.find(column=>column.identity);const hide=(column,pinned)=>!column.sized&&!column.alwaysVisible&&(column.pin==="none")!==pinned&&!(phone&&column.identity)&&gridLevel(column)>!phone;for(const column of this.columns)column.fitHidden=false;if(this.layoutMode&&this.layoutMode!=="fit")return;for(const column of shown)total +=size(column);for(const column of shown.filter(column=>hide(column,false)).sort(order))
|
|
863
|
+
if(total>width&&remaining>1){column.fitHidden=true;total -=size(column);remaining--}
|
|
864
|
+
if(identity&&!identity.fixed&&!identity.sized)total +=Math.min(identity.need??identity.width,(identity.indentNeed||0)+ 2*(this.fitCh||88))+(identity.reserve||0)- size(identity);if(identity)for(const column of shown.filter(column=>hide(column,true)).sort(order))
|
|
865
|
+
if(total>width){column.fitHidden=true;total -=size(column)}}};const FIT={};for(const name of["applyWidths","newCell","setColumnWidth","startResize","buildHeader","visibleColumns"])FIT[name]=DataGrid.prototype[name];function gridFitPrepare(grid){const identity=grid.columns.find(column=>column.rowHeader)||grid.columns[0];for(const column of grid.columns){gridFitColumn(column,identity);column.pin??=column.pinned===undefined?column.identity?"left":"none":column.pinned||"none"}
|
|
860
866
|
grid.columns=["left","none","right"].flatMap(side=>grid.columns.filter(column=>column.pin===side))}
|
|
861
|
-
Object.assign(DataGrid.prototype,COLUMN_FIT,{
|
|
862
|
-
|
|
863
|
-
return
|
|
867
|
+
Object.assign(DataGrid.prototype,COLUMN_FIT,{fitHide(shown,width,phone){COLUMN_FIT.fitHide.call(this,shown,width,phone);if(!phone||(this.layoutMode||"fit")!=="fit")return;const identity=shown.find(column=>column.identity);if(!identity)return;for(const column of shown)if(!column.identity&&gridLevel(column)>0&&!column.alwaysVisible&&!column.fixed&&!column.sized)column.fitHidden=true;const peers=shown.filter(column=>!column.fitHidden&&!column.identity&&gridLevel(column)===0);if(identity.fixed||identity.sized)return;const primary=columnWidth(identity,Math.min(Math.max(identity.contentNeed||0,identity.pref||0,identity.controlNeed||0),Math.max(160,width*.65)));if(primary+peers.reduce((sum,column)=>sum+this.fitSize(column,2),0)>width)
|
|
868
|
+
for(const column of peers)if(!column.fixed&&!column.sized&&!column.alwaysVisible)column.fitHidden=true},fitSize(column,level){if(column.fixed||column.sized)return columnWidth(column,column.width);const need=column.need??column.width,content=column.autoSize==="header"?need:column.contentNeed??need;const header=level===undefined||level===2?column.headWrapNeed||0:column.headWordNeed||column.controlNeed||0;const floor=Math.max(level===undefined?need:content,header);let width=Math.max(floor,level===undefined?column.pref||0:0);if(column.identity&&this.host.clientWidth<=640&&(this.layoutMode||"fit")==="fit"){const minimum=Math.min(content,this.grid.clientWidth*.4);width=Math.max(minimum,Math.min(width,Math.max(minimum,this.grid.clientWidth*.5)))}
|
|
869
|
+
return Math.ceil(columnWidth(column,width))},fitShrink(cols,excess,level){const slack=cols.map(column=>Math.max(0,column.renderWidth-this.fitSize(column,level)));const total=slack.reduce((sum,width)=>sum+width,0),ratio=total?Math.min(1,excess / total) : 0;
|
|
870
|
+
cols.forEach((column,index)=>column.renderWidth -=slack[index]*ratio);return Math.max(0,excess-total)},fitSpare(columns,spare){for(const target of["headWrapNeed","pref"]){const deficits=columns.map(column=>Math.max(0,Math.min(column[target]||0,column.maxW)- column.renderWidth));const total=deficits.reduce((sum,value)=>sum+value,0),ratio=total?Math.min(1,spare / total) : 0;
|
|
871
|
+
columns.forEach((column,index)=>column.renderWidth +=deficits[index]*ratio);spare=Math.max(0,spare-total)}
|
|
872
|
+
return COLUMN_FIT.fitSpare.call(this,columns,spare)},visibleColumns(){return FIT.visibleColumns.call(this).filter(column=>!column.fitHidden)},newCell(index,width,kind){return FIT.newCell.call(this,index,kind?this.cols[index].renderWidth??width:width,kind)},buildHeader(){this.fitLayout();this.fitBuilding=true;try{FIT.buildHeader.call(this)}finally{this.fitBuilding=false}
|
|
873
|
+
this.headCells.forEach((cell,index)=>{cell.querySelector(".cx-sort,.cx-htext").title=this.cols[index].title;cell.querySelector(".cx-resize").addEventListener("keydown",event=>{if(["ArrowLeft","ArrowRight","Home"].includes(event.key))this.fitManual(this.cols[index])},true)})},startResize(event,column){if(!this.destroyed&&!event.button){this.fitManual(column);global.addEventListener("pointerup",()=>this.emit("columnResize",{column:column.id,width:column.width}),{once:true,signal:this.lifetime.signal})}
|
|
874
|
+
return FIT.startResize.call(this,event,column)},setColumnWidth(id,width){const column=this.columns.find(item=>item.id===id);if(column&&Number.isFinite(width))column.sized=true;FIT.setColumnWidth.call(this,id,width);this.emit("columnResize",{column:id,width:column.width})},applyWidths(){this.fitLayout();if(this.phone!==undefined)this.updateGridPhone();const visible=this.visibleColumns(),cols=this.cols,width=this.grid.clientWidth;if(cols&&(visible.length!==cols.length||visible.some((column,index)=>column!==cols[index]))){if(!this.fitBuilding){this.buildHeader();this.syncColumnControls();this.render();return}
|
|
864
875
|
queueMicrotask(()=>this.destroyed||this.applyWidths())}
|
|
865
|
-
FIT.applyWidths.call(this,this.fitWidths(cols,width))},fitLayout(){const width=this.grid.clientWidth,phone=this.host.clientWidth<=640,shown=FIT.visibleColumns.call(this).filter(column=>!column.responsiveHidden);if(!width)return;const key=this.pendingQuery?this.fitKey:this.queryEpoch+":"+phone;if(key!==this.fitKey||!this.fitCh){this.fitKey=key;this.fitFont=null;for(const column of this.columns){const result=this.measureGridColumn(column);column.need=result.width;column.headNeed=result.head}}
|
|
866
|
-
for(const column of this.columns){
|
|
867
|
-
this.fitHide(shown,width,phone)
|
|
868
|
-
const[
|
|
869
|
-
(query?.sort.some(sort=>sort.column===column.id)?22:0)+(gridColumnFiltered(query,column.id)?24:0)+(first&&this.selectionControls?26:0)
|
|
870
|
-
Math.min(
|
|
871
|
-
(kind==="
|
|
872
|
-
|
|
876
|
+
FIT.applyWidths.call(this,this.fitWidths(cols,width));this.fitHeight()},fitLayout(){const width=this.grid.clientWidth,phone=this.host.clientWidth<=640,shown=FIT.visibleColumns.call(this).filter(column=>!column.responsiveHidden);if(!width)return;const key=this.pendingQuery?this.fitKey:this.queryEpoch+":"+phone;if(key!==this.fitKey||!this.fitCh){this.fitKey=key;this.fitFont=null;for(const column of this.columns){const result=this.measureGridColumn(column);column.need=result.width;column.headNeed=result.head}}
|
|
877
|
+
for(const column of this.columns){if(!column.fixed&&!column.sized)column.width=this.fitSize(column)}
|
|
878
|
+
this.fitHide(shown,width,phone)},measureGridColumn(column){const context=this.fitContext||=document.createElement("canvas").getContext("2d"),query=this.acceptedQuery;if(!context)throw new Error("CanopyX: no canvas context.");if(!this.fitFont){const style=getComputedStyle(this.grid),head=this.headCells?.[0]&&getComputedStyle(this.headCells[0]),family=" "+style.fontFamily;this.fitFont=[style.fontWeight+" "+style.fontSize+family,"700 12.5px"+family,(head?head.fontWeight+" "+head.fontSize:"700 13px")+ family,parseFloat(getComputedStyle(this.host).getPropertyValue("--cx-cell-px"))||12];this.fitFont.push(gridClassFont(this.grid,"p-mono"),gridClassFont(this.grid,"p-sub"),gridClassFont(this.grid,"p-pill",this.fitPill={}));this.fitNumericVariant=gridNumericVariant(this.grid);context.font=this.fitFont[0];this.fitCh=Math.ceil(gridMeasureText(context,"00000000000",this.fitNumericVariant))}
|
|
879
|
+
const[,,headFont,pad,mono,sub,pillFont]=this.fitFont,first=column===FIT.visibleColumns.call(this)[0],options=gridOptions(column),kind=options.kind;const text=(value,font=this.fitFont[0],numeric=true)=>{context.font=font;return gridMeasureText(context,value,numeric?this.fitNumericVariant:"normal")};const move=this.view.reporting?.columnReorder?Math.max(32,Math.ceil(text("⋮⋮",headFont,false))+ 8):0;const chrome=2*pad +(this.tools.columnMenus===false?8:this.host.clientWidth<=640?52:32)+ move +
|
|
880
|
+
(query?.sort.some(sort=>sort.column===column.id)?22:0)+(gridColumnFiltered(query,column.id)?24:0)+(first&&this.selectionControls?26:0);column.controlNeed=Math.ceil(24+chrome);const title=text(column.title,headFont,false),head=Math.ceil(Math.max(24,title)+ chrome);const words=column.title.trim().split(/\s+/);
|
|
881
|
+
let balanced=title;for(let split=1;split<words.length;split++)balanced=Math.min(balanced,Math.max(text(words.slice(0,split).join(" "),headFont,false),text(words.slice(split).join(" "),headFont,false)));column.headWordNeed=Math.ceil(Math.max(24,...words.map(word=>text(word,headFont,false)))+ chrome);column.headWrapNeed=Math.ceil(Math.max(24,balanced)+ chrome);let values=0,sampled=0;const none=column.autoSize==="none"||column.pref&&(column.wrap||["longText","tags","list"].includes(kind));if(!none&&column.autoSize!=="header")for(const row of this.rowCache.values()){if(sampled===200)break;const cell=row.h.cells[column.id],value=cellText(cell,column,this.fmt)||"—",series=gridSeries(cell).length;const tone=gridPresenterTone(options,cellValue(cell),isCellObject(cell)&&cell.tone),quiet=options.quietTones?.includes(tone);const secondary=kind==="identifier"&&(options.secondaryColumn?cellText(row.h.cells[options.secondaryColumn],this.columns.find(item=>item.id===options.secondaryColumn),this.fmt):isCellObject(cell)&&cell.secondary);const atomic=kind==="enum"||kind==="state";const pill=kind==="enum"&&!quiet&&tone!=="success";const atomicWidth=atomic?text(value,pill?pillFont:undefined)+
|
|
882
|
+
(pill?this.fitPill.extra+this.fitPill.spacing*Array.from(value).length:quiet&&kind==="enum"?16:quiet?0:kind==="state"&&tone!=="success"?15:13):0;values=Math.max(values,atomic?atomicWidth:kind==="identifier"?Math.min(420,text(value,options.mono?mono:undefined,!options.mono)+(secondary?6+text(secondary,sub):0)):kind==="statusStrip"?Math.min(series,12)*7:kind==="sparklineBars"?Math.min(series,12)*6:kind==="sparklineLine"?80:kind==="boolean"?16:
|
|
883
|
+
Math.min(kind==="longText"||kind==="tags"||kind==="list"||column.wrap?320:420,text(value))+
|
|
884
|
+
(kind==="progress"?80:kind==="tags"||kind==="list"?48:0));sampled++}
|
|
885
|
+
const cap=columnWidth(column,kind==="enum"||kind==="state"?column.maxW:420);const measured=Math.min(cap,Math.ceil(values +(sampled?2*pad+4 +(first&&this.selectionControls?28:0):0)));column.contentNeed=none||!sampled?0:measured;const need=none?column.pref||column.width:Math.min(cap,Math.max(column.headWrapNeed,measured));return Object.freeze({width:Math.max(column.minW,need),head:Math.min(head,cap),sampled,scope:"loaded"})},autoFitColumn(id){const column=this.columns.find(item=>item.id===id);if(!column||this.destroyed||this.pendingQuery||!this.acceptedQuery||!this.hasGridSize())throw new Error("CanopyX: auto-fit is unavailable.");this.fitFont=null;const result=this.measureGridColumn(column);this.setColumnWidth(id,result.width);return result},autoFitColumns(){return Object.freeze(Object.fromEntries(this.columns.map(column=>[column.id,this.autoFitColumn(column.id)])))},autoSizeColumns(ids=this.columns.map(column=>column.id)){if(!Array.isArray(ids)||ids.some(id=>!this.columns.some(column=>column.id===id)))throw new Error("CanopyX: name declared columns.");for(const column of this.columns)if(ids.includes(column.id)){column.sized=false;if(column.flexWeight)column.flex=true}
|
|
873
886
|
this.fitKey=null;this.applyWidths();this.stateChanged()},setColumnPriority(id,priority){const column=this.columns.find(item=>item.id===id);if(!column||!gridPriority(priority))throw new Error("CanopyX: invalid column priority.");column.priority=priority;this.applyWidths();this.syncColumnControls();this.stateChanged()}});const FIT_STATE_COLUMN=gridStateColumn,FIT_STATE_COLUMNS=gridStateColumns;gridStateColumn=column=>Object.assign(FIT_STATE_COLUMN(column),{width:column.sized||column.fixed?column.width:column.declared},column.sized&&{sized:true},column.priority!==undefined&&{priority:column.priority});gridStateColumns=(grid,input)=>{const result=FIT_STATE_COLUMNS(grid,input),sources=new Map(input.map(column=>[column?.id,column]));for(const saved of result){const{sized=sources.get(saved.id)?.flex===false||undefined,priority}=sources.get(saved.id)||saved;if(sized!==undefined&&typeof sized!=="boolean"||priority!==undefined&&!gridPriority(priority))throw new Error("CanopyX: invalid saved column.");Object.assign(saved,sized&&{sized},priority!==undefined&&{priority})}
|
|
874
887
|
return result};function validateGridHighlights(view){if(view.highlightRules===undefined)return;if(!Array.isArray(view.highlightRules)||view.highlightRules.length>64)throw new Error("CanopyX: at most 64 highlight rules.");const columns=new Map(view.columns.map(column=>[column.id,column])),budget={predicates:0};for(const rule of view.highlightRules){if(!rule||
|
|
875
888
|
rule.target!==undefined&&!["row","cell"].includes(rule.target)||rule.tone===undefined&&rule.className===undefined)
|
|
@@ -933,12 +946,13 @@ if(event.key!=="F2")return false;GRID_DRAG.picked=gridDragItem(this,row);setText
|
|
|
933
946
|
function gridStateColumns(grid,input){if(!Array.isArray(input))throw new Error("CanopyX: invalid columns.");const seen=new Set(),declared=new Map(grid.columns.map(column=>[column.id,column]));const columns=input.map(column=>readStateColumn(column,seen)).filter(column=>declared.has(column.id));for(const column of columns)column.width=columnWidth(declared.get(column.id),column.width);for(const column of grid.columns)if(!seen.has(column.id))columns.push(gridStateColumn(column));if(!columns.some(column=>!column.hidden))throw new Error("CanopyX: keep at least one column visible.");return columns}
|
|
934
947
|
Object.assign(DataGrid.prototype,{prepareState(){this.storageKey=this.view.stateKey?"cx:grid:"+this.view.stateKey+":"+this.view.id:null;this.savedViews=new Map();this.defaultState={version:1,view:this.view.id,columns:this.columns.map(gridStateColumn),query:gridQuery(this.view,gridQueryStart(this.view.query)),timeZone:this.local?"local":"utc",selection:[],scrollTop:0};if(this.paged)this.defaultState.paging={pageLength:this.pageLength,offset:0};const stored=this.readStoredState();if(stored&&Array.isArray(stored.views)){for(const entry of stored.views.slice(0,20)){try{this.savedViews.set(this.viewName(entry.name),this.readGridState(entry.state))}catch(_){/* Removed or invalid saved views are skipped. */ }
|
|
935
948
|
}}
|
|
936
|
-
try{this.initialState=stored&&stored.current?this.readGridState(stored.current):null}catch(_){this.initialState=null}},initializeState(){const ready=this.initialState?this.setState(this.initialState):this.setQuery(this.view.query||{});return this.view.formatRules||this.view.formatting?Promise.all([ready,this.loadFormatting().catch(error=>this.emit("error",{error}))]).then(([result])=>result):ready},getState(){const query=this.getQuery()||this.defaultState.query;const state={version:1,view:this.view.id,columns:this.columns.map(gridStateColumn),query:JSON.parse(JSON.stringify({...query,offset:this.cursor?undefined:0,cursor:undefined,revision:undefined})),timeZone:this.local?"local":"utc",selection:[...this.selected],scrollTop:this.grid?this.logicalTop():0};if(this.paged)state.paging={pageLength:this.pageLength,offset:this.cursor?0:this.pageOffset,...this.pageAll?{allRows:true}:{}};if(this.formatEdited)state.formatRules=JSON.parse(JSON.stringify(this.formatRules));return state},readGridState(state){if(!state||state.version!==1||state.view!==this.view.id||!["utc","local"].includes(state.timeZone)||
|
|
949
|
+
try{this.initialState=stored&&stored.current?this.readGridState(stored.current):null}catch(_){this.initialState=null}},initializeState(){const ready=this.initialState?this.setState(this.initialState):this.setQuery(this.view.query||{});return this.view.formatRules||this.view.formatting?Promise.all([ready,this.loadFormatting().catch(error=>this.emit("error",{error}))]).then(([result])=>result):ready},getState(){const query=this.getQuery()||this.defaultState.query;const state={version:1,view:this.view.id,columns:this.columns.map(gridStateColumn),query:JSON.parse(JSON.stringify({...query,offset:this.cursor?undefined:0,cursor:undefined,revision:undefined})),timeZone:this.local?"local":"utc",selection:this.view.rowIdentity==="ordinal"?[]:[...this.selected],scrollTop:this.grid?this.logicalTop():0};if(this.paged)state.paging={pageLength:this.pageLength,offset:this.cursor?0:this.pageOffset,...this.pageAll?{allRows:true}:{}};if(this.formatEdited)state.formatRules=JSON.parse(JSON.stringify(this.formatRules));return state},readGridState(state){if(!state||state.version!==1||state.view!==this.view.id||!["utc","local"].includes(state.timeZone)||
|
|
937
950
|
!Number.isFinite(state.scrollTop)||state.scrollTop<0||state.scrollTop>MAX_PROTOCOL_INTEGER*this.rowH||!Array.isArray(state.selection))
|
|
938
|
-
throw new Error("CanopyX: invalid grid state.");const columns=gridStateColumns(this,state.columns);const selection=[...new Set(state.selection.map(id=>{requireIdentifier(id,"state selection ID");return id}))];if(this.view.
|
|
951
|
+
throw new Error("CanopyX: invalid grid state.");const columns=gridStateColumns(this,state.columns);const selection=[...new Set(state.selection.map(id=>{requireIdentifier(id,"state selection ID");return id}))];if(this.view.rowIdentity==="ordinal"&&selection.length)
|
|
952
|
+
throw new Error("CanopyX: ordinal row identity is snapshot-local; replaying saved selections requires stable row keys.");if(this.view.selection==="none"&&selection.length||!this.multi&&selection.length>1)throw new Error("CanopyX: invalid state selection.");const input=state.query;if(!input||typeof input!=="object"||!Array.isArray(input.sort)||!Array.isArray(input.filters))throw new Error("CanopyX: invalid state query.");const known=id=>this.columns.some(column=>column.id===id);const query=gridQuery(this.view,gridQueryStart(input,{sort:input.sort.filter(sort=>sort&&known(sort.column)),filters:input.filters.filter(filter=>filter&&known(filter.column)),[LINK_IMPL.queryOwn]:true}),true);const parsed={version:1,view:this.view.id,columns,query,timeZone:state.timeZone,selection,scrollTop:state.scrollTop,formatRules:state.formatRules,calendar:state.calendar};if(this.paged||state.paging){const paging=state.paging||this.defaultState.paging;if(!paging||!Number.isInteger(paging.pageLength)||paging.pageLength<1||paging.pageLength>Math.max(10000,this.view.source.kind==="inline"?(this.view.rowData?.count??this.view.rows.length):0)||paging.allRows!==undefined&&(typeof paging.allRows!=="boolean"||paging.allRows&&this.view.source.kind!=="inline")||
|
|
939
953
|
!Number.isInteger(paging.offset)||paging.offset<0||paging.offset>MAX_PROTOCOL_INTEGER||this.cursor&&paging.offset!==0)
|
|
940
954
|
throw new Error("CanopyX: invalid paged view state.");if(this.paged){parsed.paging={pageLength:paging.pageLength,offset:paging.offset,...paging.allRows?{allRows:true}:{}};if(!state.paging)parsed.scrollTop=0}else parsed.scrollTop=Math.min(MAX_PROTOCOL_INTEGER*this.rowH,paging.offset*this.rowH+state.scrollTop)}
|
|
941
|
-
return parsed},async setState(input){const state=this.readGridState(input);const rules=state.formatRules!==undefined?JSON.parse(JSON.stringify(state.formatRules)):this.formatEdited?this.view.formatRules||[]:undefined;const before=this.queryEpoch;if(rules!==undefined)await this.validateFormatRules(rules);if(this.destroyed||before!==this.queryEpoch)throw new DOMException("Grid state was superseded.","AbortError");state.formatRules=rules;clearTimeout(this.searchTimer);this.searchTimer=null;const pending=this.setQuery({...state.query,offset:state.paging?state.paging.offset:0},state.paging),epoch=this.queryEpoch;this.restoringEpoch=epoch;try{await pending;if(this.destroyed||epoch!==this.queryEpoch)throw new DOMException("Grid state was superseded.","AbortError");await this.applyStatePresentation(state);return this.getQuery()}finally{if(this.restoringEpoch===epoch){this.restoringEpoch=null;this.stateChanged()}}},applyStatePresentation(state){if(this.cancelResize)this.cancelResize();const current=new Map(this.columns.map(column=>[column.id,column]));this.columns=state.columns.map(saved=>{const column=current.get(saved.id);return Object.assign(column,{sized:false,priority:column.basePriority},saved)});this.setTimeZone(state.timeZone);this.setSelection(state.selection);this.buildHeader();this.syncColumnControls();this.setLogicalTop(state.scrollTop);this.render();if(state.formatRules!==undefined||this.formatEdited)return this.setFormatRules(state.formatRules||this.view.formatRules||[])},setColumnOrder(ids){if(!Array.isArray(ids)||ids.length!==this.columns.length||new Set(ids).size!==ids.length||
|
|
955
|
+
return parsed},async setState(input){const state=this.readGridState(input);const rules=state.formatRules!==undefined?JSON.parse(JSON.stringify(state.formatRules)):this.formatEdited?this.view.formatRules||[]:undefined;const before=this.queryEpoch;if(rules!==undefined)await this.validateFormatRules(rules);if(this.destroyed||before!==this.queryEpoch)throw new DOMException("Grid state was superseded.","AbortError");state.formatRules=rules;clearTimeout(this.searchTimer);this.searchTimer=null;const pending=this.setQuery({...state.query,offset:state.paging?state.paging.offset:0},state.paging),epoch=this.queryEpoch;this.restoringEpoch=epoch;try{await pending;if(this.destroyed||epoch!==this.queryEpoch)throw new DOMException("Grid state was superseded.","AbortError");await this.applyStatePresentation(state);return this.getQuery()}finally{if(this.restoringEpoch===epoch){this.restoringEpoch=null;this.stateChanged()}}},applyStatePresentation(state){if(this.cancelResize)this.cancelResize();const current=new Map(this.columns.map(column=>[column.id,column]));this.columns=state.columns.map(saved=>{const column=current.get(saved.id);return Object.assign(column,{sized:false,priority:column.basePriority},saved)});this.setTimeZone(state.timeZone);if(this.view.rowIdentity!=="ordinal")this.setSelection(state.selection);this.buildHeader();this.syncColumnControls();this.setLogicalTop(state.scrollTop);this.render();if(state.formatRules!==undefined||this.formatEdited)return this.setFormatRules(state.formatRules||this.view.formatRules||[])},setColumnOrder(ids){if(!Array.isArray(ids)||ids.length!==this.columns.length||new Set(ids).size!==ids.length||
|
|
942
956
|
ids.some(id=>!this.columns.some(column=>column.id===id)))throw new Error("CanopyX: name each column once.");if(this.cancelResize)this.cancelResize();const columns=new Map(this.columns.map(column=>[column.id,column]));this.columns=ids.map(id=>columns.get(id));this.columns.forEach((column,index,all)=>{if(column.pin==="left"&&all.slice(0,index).some(item=>item.pin!=="left")||column.pin==="right"&&all.slice(index+1).some(item=>item.pin!=="right"))column.pin="none"});this.buildHeader();this.syncColumnControls();this.scheduleRender();this.stateChanged()},viewName(name){if(typeof name!=="string"||!name.trim()||name.trim().length>100)throw new Error("CanopyX: view names need 1 to 100 nonblank characters.");return name.trim()},getSavedViews(){return[...this.savedViews.keys()]},saveView(name){name=this.viewName(name);if(!this.getQuery())throw new Error("CanopyX: saving needs an accepted query.");if(!this.savedViews.has(name)&&this.savedViews.size>=20)throw new Error("CanopyX: maximum 20 saved views.");this.savedViews.set(name,this.getState());this.writeStoredState(this.getState());this.syncSavedViews();if(this.savedChoice)this.savedChoice.value=name},applySavedView(name){const state=this.savedViews.get(this.viewName(name));if(!state)throw new Error("CanopyX: the saved view does not exist.");return this.setState(state)},removeSavedView(name){this.savedViews.delete(this.viewName(name));this.writeStoredState(this.getState());this.syncSavedViews()},resetView(){return this.setState(this.defaultState)},readStoredState(){if(!this.storageKey)return null;try{return JSON.parse(global.sessionStorage.getItem(this.storageKey))}catch(_){return null}},writeStoredState(state){if(!this.storageKey||this.destroyed)return;try{global.sessionStorage.setItem(this.storageKey,JSON.stringify({current:state,views:[...this.savedViews].map(([name,value])=>({name,state:value}))}))}
|
|
943
957
|
catch(_){/* A disabled or full storage leaves the current session usable. */ }
|
|
944
958
|
}});const GRID_HISTORY_IMPL={},GRID_HISTORY=definePart(DataGrid,"history","history presenters",()=>({GRID_HISTORY_IMPL,h,setText,fill,gridSeries,gridPresenterTone,toneColors,toneOf,GRID_TONE_RANK}));const GRID_HISTORY_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.loadHistory=function(){return this.historyLoad||=loadPart(GRID_HISTORY).then(()=>{this.version++;this.scheduleRender()},error=>this.emit("error",{error}))};DataGrid.prototype.initializeState=function(){const ready=GRID_HISTORY_INIT.call(this);return this.columns.some(column=>GRID_HISTORY_KINDS.includes(column.presenter?.kind))?Promise.all([ready,this.loadHistory()]).then(([result])=>result):ready};const GRID_CALENDAR=definePart(DataGrid,"calendar","calendar",()=>({DataGrid,h,setText,fill,plural,gridButton,gridIcon,gridFreeze,cellText,cellValue,isCellObject,gridQuery,gridQueryRows,gridResultShape,gridPresenterTone,validateGridRows,validateGridPage,validateGridCursorPage,validStructuralCount,checkDocument,numberFormat,loadPart,HostCellContext,disposeHostSlot,PROTOCOL}));definePart(DataGrid,"timeline","resource timeline",()=>({DataGrid,TreeGrid,h,setText,fill,numberFormat}));definePart(DataGrid,"calendar-recurrence","calendar recurrence",()=>({DataGrid}));definePart(DataGrid,"calendar-edit","calendar editing",()=>({DataGrid,h,setText,fill,cellValue,GRID_DRAG}));definePart(DataGrid,"calendar-ics","iCalendar",()=>({DataGrid,h,fill,cellText}));const GRID_CALENDAR_API=["getCalendar","setCalendarView","setCalendarDate","setCalendarZoom","calendarStep","calendarToday","getCalendarEvents","exportCalendar","openCalendarEvent","clearCalendarSelection","setCalendarSource"];for(const name of GRID_CALENDAR_API)DataGrid.prototype[name]=function(...args){return this.loadCalendar().then(()=>this[name](...args))};DataGrid.prototype.loadCalendar=function(){return this.calLoad||=loadPart(GRID_CALENDAR).then(()=>this.destroyed||this.calParts()).then(()=>this.destroyed||this.startCalendar()).catch(error=>{this.calLoad=null;this.emit("error",{error});throw error})};const GRID_CALENDAR_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const start=()=>GRID_CALENDAR_INIT.call(this);return this.view.calendar?this.loadCalendar().then(start,start):start()};const CAL_PRESETS={basic:{toolbar:false,details:"popover",views:["month","week","day","agenda"]},standard:{toolbar:["search","filters","export"],details:"popover",print:true,views:["month","week","day","days","agenda","year"]},scheduler:{toolbar:["search","filters","views","export"],details:"drawer",print:true,editable:true,create:true,views:["month","week","day","agenda"]}};const CAL_FIELDS=["allDay","description","tone","resource","recurrence","exceptions","source"];const CAL_TITLES={allDay:"All day",description:"Description",tone:"Tone",resource:"Resource",recurrence:"Repeats",exceptions:"Exceptions",source:"Source"};const CAL_OWN=new Set(["events","preset","id","label","views","view","date","timeZone","firstDay","toolbar","details","editable","create","drop","resources","timeline","live","facets","drawer","export","print","sources","calendar","links"]);const calPad=(value,size=2)=>String(value).padStart(size,"0");function calInstantText(value,field,allDay){if(value instanceof Date&&Number.isFinite(value.getTime()))
|
|
@@ -954,14 +968,19 @@ return roots}
|
|
|
954
968
|
const GRID_EDITING=definePart(DataGrid,"editing","editing",()=>({DataGrid,FORMS_IMPL,h,setText,fill,gridButton,gridDecorateButton,GRID_ICONS,cellValue,cellText,isCellObject,gridFreeze,gridMomentFromParts,numberFormat,gridQuery,foldText,requireIdentifier,checkDocument,validateGridRows,inlineGridSource,PROTOCOL,boundedPattern,validateGridFacetPage,RECORD_IMPL}));const GRID_EDIT_INIT=DataGrid.prototype.initializeState;const GRID_EDIT_API=["beginEdit","endEdit","setCellValue","validate","commitRow","commitChanges","insertRow","isEditing","hasChanges","undo","redo","canUndo","canRedo","cancelEdit","revertChanges","getChanges","setReadOnly"];GRID_EDIT_API.forEach((name,index)=>{DataGrid.prototype[name]=index<7?function(...args){return this.loadEditing().then(()=>this[name](...args))}:index<15?()=>false:()=>[]});DataGrid.prototype.setReadOnly=function(value){this.editReadOnly=!!value};DataGrid.prototype.loadEditing=function(){return this.editLoad||=loadPart(GRID_EDITING).then(()=>this.startEditing()).catch(error=>{this.editLoad=null;this.emit("error",{error});throw error})};DataGrid.prototype.initializeState=function(){const ready=GRID_EDIT_INIT.call(this);return this.columns.some(column=>column.editable)?Promise.all([ready,this.loadEditing().catch(()=>{})]).then(([result])=>result):ready};DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridFacetPanel:"Filter by",gridFacetPanelHide:"Hide the filter panel",gridFacetPanelShow:"Show the filter panel",gridFacetShowMore:"Show {count} more",gridFacetShowFewer:"Show fewer",gridFacetEmptyValue:"(Empty)",gridFacetFrom:"From",gridFacetTo:"To",gridFacetHistogram:"Distribution of {column}",gridFacetBin:"{from} to {to}: {count} rows",gridFacetNoChart:"Too many values to chart",gridFacetClear:"Clear {column}",gridFacetCustom:"Another condition filters this column.",gridFacetResult:"{count} matching rows",gridFacetSelected:"{count} selected",gridFacetValueCount:"{value}, {count} rows",gridFacetCollapse:"Collapse {column}",gridFacetExpand:"Expand {column}",gridFacetInvalid:"Enter a valid value.",gridFacetReversed:"From must not be after To."}));const GRID_FACETS=definePart(DataGrid,"facets","facet panel",()=>({DataGrid,h,setText,fill,gridButton,gridIcon,gridQueryStart,gridQueryRows,gridColumnProjection,gridScalar,gridOrder,cellText,foldText,numberFormat,gridCellRenderer,gridFreeze}));Object.assign(DataGrid.prototype,{loadFacets(){return this.facetLoad||=loadPart(GRID_FACETS).then(()=>this.destroyed||this.startFacets()).catch(error=>{this.facetLoad=null;throw error})},setFacetPanelOpen(open){return this.loadFacets().then(()=>this.setFacetPanelOpen(open))},getFacetPanel(){return gridFreeze({open:this.facetOpen??null,columns:(this.facetColumns||[]).map(facet=>facet.column)})}});const FACET_STATE={get:DataGrid.prototype.getState,read:DataGrid.prototype.readGridState,apply:DataGrid.prototype.applyStatePresentation,init:DataGrid.prototype.initializeState};Object.assign(DataGrid.prototype,{getState(){const state=FACET_STATE.get.call(this);if((this.view.facets||this.opts.facets)&&this.facetOpen!==undefined)state.facets={open:this.facetOpen};return state},readGridState(input){const state=FACET_STATE.read.call(this,input);if(input.facets!==undefined){const facets=input.facets;if(!facets||typeof facets!=="object"||Array.isArray(facets)||Object.keys(facets).some(key=>key!=="open")||typeof facets.open!=="boolean")
|
|
955
969
|
throw new Error("CanopyX: invalid saved facet panel state.");if(this.view.facets||this.opts.facets)state.facets={open:facets.open}}
|
|
956
970
|
return state},applyStatePresentation(state){const applied=FACET_STATE.apply.call(this,state);if(state.facets&&state.facets.open!==this.facetOpen&&!this.destroyed){if(this.facetPanel)this.setFacetPanelOpen(state.facets.open).catch(error=>this.emit("error",{error}));else this.facetOpen=state.facets.open}
|
|
957
|
-
return applied},initializeState(){if(this.initialState?.facets)this.facetOpen=this.initialState.facets.open;const ready=FACET_STATE.init.call(this);return this.view.facets||this.opts.facets?Promise.all([ready,this.loadFacets().catch(error=>this.emit("error",{error}))]).then(([result])=>result):ready}});const GRID_FORMAT=definePart(DataGrid,"formatting","conditional formatting",()=>({DataGrid,h,setText,setClass,fill,gridFreeze,gridDateInputMoment,cellValue,cellText,foldText,toneOf,numberFormat,gridButton,gridOption,gridInputLabel,gridIcon,gridDecorateButton,GRID_REPORTING,loadPart,definePart,announceMenu,boundedPattern,wildcardMatch,svgIcon}));Object.assign(DataGrid.prototype,{loadFormatting(){return this.formatLoad||=loadPart(GRID_FORMAT).then(()=>this.startFormatting(),error=>{this.formatLoad=null;throw error})},setFormatRules(rules){return this.loadFormatting().then(()=>this.setFormatRules(rules))},validateFormatRules(rules){return this.loadFormatting().then(()=>this.validateFormatRules(rules))},openFormatRules(){return this.loadFormatting().then(()=>this.openFormatRules())},getFormatRules(){return gridFreeze(JSON.parse(JSON.stringify(this.formatRules||this.view.formatRules||[])))}});DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridLiveOrderChanged:"Order changed",gridLiveResort:"Re-sort",gridLiveNewData:"New data",gridLiveRefresh:"Refresh",gridLiveOrderHint:"Rows keep their places while data changes. Re-sort to move them where the sort puts them.",gridLiveChanged:"Rows changed: {added} added, {updated} updated, {removed} removed",gridLiveSorted:"Rows moved to their sorted places.",gridLiveRecordRemoved:"This record was removed."}));const GRID_LIVE=definePart(DataGrid,"live","live data",()=>({DataGrid,h,setText,fill,gridButton,gridIcon,gridQuery,gridResultShape,gridQueryRows,gridCompare,gridOrder,gridIdOrder,validateGridRows,validateGridPage,validateGridCursorPage,gridFreeze,requireIdentifier,checkDocument,cellValue,PROTOCOL,GRID_REPORTING,VIEW_MODES,inlineGridSource}));const GRID_LIVE_API=["applyTransaction","addRows","updateRows","removeRows","setRows","flushTransactions","refreshRows","resort","poll"];for(const name of GRID_LIVE_API)DataGrid.prototype[name]=function(...args){return this.loadLive().then(()=>this[name](...args))};Object.assign(DataGrid.prototype,{loadLive(){return this.liveLoad||=loadPart(GRID_LIVE).then(()=>this.destroyed||this.startLive()).catch(error=>{this.liveLoad=null;throw error})},getLiveState(){return this.liveStatus?this.liveStatus():gridFreeze({orderChanged:false,newData:false,pending:0,polling:false,revision:this.snapshot?.revision??null})}});const GRID_LIVE_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_LIVE_INIT.call(this);return this.view.live&&this.opts.live!==false||this.opts.live?Promise.all([ready,this.loadLive().catch(error=>this.emit("error",{error}))]).then(([result])=>result):ready};const GRID_PAGER_IMPL={},GRID_PAGER=definePart(DataGrid,"pager","pager controls",()=>({DataGrid,GRID_PAGER_IMPL,h,setText,fill,gridButton,gridOption,numberFormat,gridCountLabel}));const GRID_PAGER_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_PAGER_INIT.call(this);return!this.pager||!this.view.pager||GRID_PAGER_IMPL.installed?ready:Promise.all([ready,loadPart(GRID_PAGER).then(()=>this.destroyed||this.buildPager())
|
|
971
|
+
return applied},initializeState(){if(this.initialState?.facets)this.facetOpen=this.initialState.facets.open;const ready=FACET_STATE.init.call(this);return this.view.facets||this.opts.facets?Promise.all([ready,this.loadFacets().catch(error=>this.emit("error",{error}))]).then(([result])=>result):ready}});const GRID_FORMAT=definePart(DataGrid,"formatting","conditional formatting",()=>({DataGrid,h,setText,setClass,fill,gridFreeze,gridDateInputMoment,cellValue,cellText,foldText,toneOf,numberFormat,gridButton,gridOption,gridInputLabel,gridIcon,gridDecorateButton,GRID_REPORTING,loadPart,definePart,announceMenu,boundedPattern,wildcardMatch,svgIcon}));Object.assign(DataGrid.prototype,{loadFormatting(){return this.formatLoad||=loadPart(GRID_FORMAT).then(()=>this.startFormatting(),error=>{this.formatLoad=null;throw error})},setFormatRules(rules){return this.loadFormatting().then(()=>this.setFormatRules(rules))},validateFormatRules(rules){return this.loadFormatting().then(()=>this.validateFormatRules(rules))},openFormatRules(){return this.loadFormatting().then(()=>this.openFormatRules())},getFormatRules(){return gridFreeze(JSON.parse(JSON.stringify(this.formatRules||this.view.formatRules||[])))}});DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridLiveOrderChanged:"Order changed",gridLiveResort:"Re-sort",gridLiveNewData:"New data",gridLiveRefresh:"Refresh",gridLiveOrderHint:"Rows keep their places while data changes. Re-sort to move them where the sort puts them.",gridLiveChanged:"Rows changed: {added} added, {updated} updated, {removed} removed",gridLiveSorted:"Rows moved to their sorted places.",gridLiveRecordRemoved:"This record was removed."}));const GRID_LIVE=definePart(DataGrid,"live","live data",()=>({DataGrid,h,setText,fill,gridButton,gridIcon,gridQuery,gridResultShape,gridQueryRows,gridCompare,gridOrder,gridIdOrder,validateGridRows,validateGridPage,validateGridCursorPage,gridFreeze,requireIdentifier,checkDocument,cellValue,PROTOCOL,GRID_REPORTING,VIEW_MODES,inlineGridSource}));const GRID_LIVE_API=["applyTransaction","addRows","updateRows","removeRows","setRows","flushTransactions","refreshRows","resort","poll"];for(const name of GRID_LIVE_API)DataGrid.prototype[name]=function(...args){return this.loadLive().then(()=>this[name](...args))};Object.assign(DataGrid.prototype,{loadLive(){if(this.view.rowIdentity==="ordinal")return Promise.reject(new Error("CanopyX: ordinal row identity is snapshot-local; keyed live updates require stable row keys."));return this.liveLoad||=loadPart(GRID_LIVE).then(()=>this.destroyed||this.startLive()).catch(error=>{this.liveLoad=null;throw error})},getLiveState(){return this.liveStatus?this.liveStatus():gridFreeze({orderChanged:false,newData:false,pending:0,polling:false,revision:this.snapshot?.revision??null})}});const GRID_LIVE_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_LIVE_INIT.call(this);return this.view.live&&this.opts.live!==false||this.opts.live?Promise.all([ready,this.loadLive().catch(error=>this.emit("error",{error}))]).then(([result])=>result):ready};const GRID_PAGER_IMPL={},GRID_PAGER=definePart(DataGrid,"pager","pager controls",()=>({DataGrid,GRID_PAGER_IMPL,h,setText,fill,gridButton,gridOption,numberFormat,gridCountLabel}));const GRID_PAGER_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_PAGER_INIT.call(this);return!this.pager||!this.view.pager||GRID_PAGER_IMPL.installed?ready:Promise.all([ready,loadPart(GRID_PAGER).then(()=>this.destroyed||this.buildPager())
|
|
958
972
|
.catch(error=>{this.pager.hidden=this.opts.toolbar===false;this.emit("error",{error})})]).then(([result])=>result)};DataGrid.prototype.parts["record-panel"]=RECORD_PART;RECORD_IMPL.grid={DataGrid,gridCellRenderer,createDataGrid,gridFreeze,gridQuery,gridResultShape,validatePresenter:gridPresenter};DataGrid.prototype.openRecord=TreeGrid.prototype.openRecord;DataGrid.prototype.loadRecordPanel=function(){return this.recordLoad||=loadRecordPanel().then(()=>{this.version++;this.scheduleRender()},error=>this.emit("error",{error}))};DataGrid.prototype.recordNeeded=function(row){return!!this.view.record||this.columns.some(column=>column.presenter?.kind==="structured")||
|
|
959
973
|
!!row&&Object.values(row.cells).some(cell=>isCellObject(cell)&&RECORD_STRUCTURE.some(name=>cell[name]!==undefined))};const GRID_RECORD_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_RECORD_INIT.call(this);return this.columns.some(column=>column.presenter?.kind==="structured")?Promise.all([ready,this.loadRecordPanel()]).then(([result])=>result):ready};const GRID_DATA_IMPL={},GRID_DATA=definePart(DataGrid,"data","row data",()=>({GRID_DATA_IMPL,PROTOCOL,validateGridRows,inlineGridSource,loadSidecar,gridIdOrder}));function rowDataSource(grid){let inner=null;const source={reset:()=>{inner=null},query:(query,options)=>
|
|
960
974
|
(inner||=loadPart(GRID_DATA).then(()=>GRID_DATA_IMPL.source(grid,source)).catch(error=>{inner=null;throw error})).then(rows=>rows.query(query,options))};return source}
|
|
961
975
|
class MatrixHost{}
|
|
962
|
-
const MATRIX_IMPL={},activeMatrices=new WeakMap();const MATRIX_PART=definePart(MatrixHost,"matrix","matrix view",()=>({MATRIX_IMPL,h,setText,fill,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}));const MATRIX_METHODS=["sort","group","filter","setSearch","setAttentionOnly","getState","setState","getVisible","focusCell","update"];function createMatrix(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: createMatrix needs a host element and a matrix document.");const existing=activeMatrices.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-matrix-host"].filter(name=>!host.classList.contains(name)),hadClass=host.hasAttribute("class");const previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null;const cancelled=()=>new DOMException("Matrix was destroyed.","AbortError");const ready=loadPart(MATRIX_PART).then(()=>{if(destroyed)throw cancelled();impl=MATRIX_IMPL.create(host,options);return impl.ready});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():options.view});for(const name of MATRIX_METHODS)api[name]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();return impl[name](...args)};if(destroyed)throw cancelled();return impl?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeMatrices.get(host)===api)activeMatrices.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");notice?.remove();if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
976
|
+
const MATRIX_IMPL={},activeMatrices=new WeakMap();const MATRIX_PART=definePart(MatrixHost,"matrix","matrix view",()=>({MATRIX_IMPL,h,setText,fill,plural,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}));const MATRIX_METHODS=["sort","group","filter","setSearch","setAttentionOnly","getState","setState","getVisible","focusCell","update"];function createMatrix(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: createMatrix needs a host element and a matrix document.");const existing=activeMatrices.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-matrix-host"].filter(name=>!host.classList.contains(name)),hadClass=host.hasAttribute("class");const previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null;const cancelled=()=>new DOMException("Matrix was destroyed.","AbortError");const ready=loadPart(MATRIX_PART).then(()=>{if(destroyed)throw cancelled();impl=MATRIX_IMPL.create(host,options);return impl.ready});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():options.view});for(const name of MATRIX_METHODS)api[name]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();return impl[name](...args)};if(destroyed)throw cancelled();return impl?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeMatrices.get(host)===api)activeMatrices.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");notice?.remove();if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
963
977
|
for(const name of addedClasses)host.classList.remove(name);if(!hadClass&&!host.classList.length)host.removeAttribute("class")};ready.catch(error=>{if(destroyed)return;notice=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);errorText=notice.textContent;host.setAttribute("data-cx-error",errorText);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeMatrices.set(host,api);host.classList.add("cx-host","cx-matrix-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
964
|
-
const MATRIX_API={createMatrix};
|
|
978
|
+
const MATRIX_API={createMatrix};class ChangesHost{}
|
|
979
|
+
const CHANGES_IMPL={},activeChangeViews=new WeakMap();const CHANGES_PART=definePart(ChangesHost,"changes","change views",()=>({CHANGES_IMPL,h,setText,fill,plural,numberFormat,gridFreeze,toneOf,applyTone,svgIcon,PROTOCOL}));const CHANGE_VIEW_METHODS={diff:["getLayout","setLayout","next","previous","expandAll","copy","getHunks","update"],changes:["getState","setState","toggle","focusItem","update"],propagation:["update"]};function changeViewFactory(kind,name){return function(host,options){if(!host||!options||!options.view||typeof options.view!=="object")throw new Error("CanopyX: "+name+" needs a host element and a "+kind+" document.");const existing=activeChangeViews.get(host);if(existing)return existing;const addedClasses=["cx-host","cx-change-host"].filter(className=>!host.classList.contains(className)),hadClass=host.hasAttribute("class"),previousError=host.getAttribute("data-cx-error");let impl=null,destroyed=false,notice=null,errorText=null,failure=null,loaded=false,currentView=options.view;const cancelled=()=>new DOMException("Change view was destroyed.","AbortError");const clearError=()=>{notice?.remove();notice=null;if(errorText!==null&&host.getAttribute("data-cx-error")===errorText){if(previousError===null)host.removeAttribute("data-cx-error");else host.setAttribute("data-cx-error",previousError)}
|
|
980
|
+
errorText=null};const showError=error=>{if(destroyed)return;impl?.destroy();impl=null;failure=error;clearError();notice=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);errorText=notice.textContent;host.setAttribute("data-cx-error",errorText);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))};const mount=view=>{clearError();impl=CHANGES_IMPL[kind](host,{...options,view});failure=null;return impl.ready};const ready=loadPart(CHANGES_PART).then(()=>{if(destroyed)throw cancelled();loaded=true;return mount(currentView)});const api={element:host};Object.defineProperty(api,"view",{enumerable:true,get:()=>impl?impl.document():currentView});for(const method of CHANGE_VIEW_METHODS[kind])api[method]=(...args)=>{const invoke=()=>{if(destroyed)throw cancelled();if(method==="update"){currentView=args[0];try{return impl?impl.update(...args):mount(currentView)}
|
|
981
|
+
catch(error){showError(error);throw error}}
|
|
982
|
+
if(failure)throw failure;return impl[method](...args)};if(destroyed)throw cancelled();return loaded?invoke():ready.then(invoke)};api.ready=ready.then(()=>{if(destroyed)throw cancelled();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;impl?.destroy();if(activeChangeViews.get(host)===api)activeChangeViews.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");clearError();for(const className of addedClasses)host.classList.remove(className);if(!hadClass&&!host.classList.length)host.removeAttribute("class")};ready.catch(showError);Object.freeze(api);activeChangeViews.set(host,api);host.classList.add("cx-host","cx-change-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}}
|
|
983
|
+
const CHANGES_API={createDiff:changeViewFactory("diff","createDiff"),createChangeList:changeViewFactory("changes","createChangeList"),createPropagation:changeViewFactory("propagation","createPropagation")};const CHANGE_VIEW_TYPES={diff:CHANGES_API.createDiff,changes:CHANGES_API.createChangeList,propagation:CHANGES_API.createPropagation};DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridCellRangeSelected:"{rows} rows × {columns} columns selected",gridCellRangesSelected:"{ranges} ranges selected, {cells} cells",gridCellRangeCleared:"Cell selection cleared",gridCopyCells:"Copy cells",gridCopyCellsWithHeaders:"Copy cells with headers",gridPasteCells:"Paste",gridSelectAllCells:"Select all cells",gridCellsCopied:"Copied {rows} rows × {columns} columns",gridCellsPasted:"Pasted {count} cells",gridPasteRefused:"{count} cells were not pasted",gridPasteReadOnly:"This cell cannot be changed.",gridPasteType:"“{value}” is not a valid value for {column}.",gridPasteReport:"Paste report",gridPasteCell:"Row {row}, {column}: {reason}",gridFillHandle:"Drag to fill the cells below",gridCellsFilled:"Filled {count} cells",gridCellMenu:"Cell actions",gridClearCellRanges:"Clear cell selection"}));const GRID_PART_CONTEXT=()=>({DataGrid,h,setText,fill,columnWidth,foldText,gridButton,gridIcon,gridDecorateButton,cellText,cellValue,isCellObject,numberFormat,gridFreeze,gridMomentFromParts,requireIdentifier,loadGridFilterEditor,CELL_CONTROLS,reachable,gridExportField});const GRID_COLUMN_GROUPS=definePart(DataGrid,"column-groups","column groups",GRID_PART_CONTEXT);const GRID_CELL_RANGE=definePart(DataGrid,"cell-range","cell ranges",GRID_PART_CONTEXT);const GRID_PART_API=[["column-groups","getColumnGroups","setColumnGroupVisible"],["cell-range","getCellRanges","setCellRanges","clearCellRanges","selectAllCells","copyCellRanges","getCellRangeText","pasteCells"]];const gridPartLoader=(part,start)=>function(){return(this.partLoads||={})[start]||=loadPart(part).then(()=>this.destroyed||this["start"+start]()).catch(error=>{this.partLoads[start]=null;throw error})};DataGrid.prototype.loadColumnGroups=gridPartLoader(GRID_COLUMN_GROUPS,"ColumnGroups");DataGrid.prototype.loadCellRanges=gridPartLoader(GRID_CELL_RANGE,"CellRanges");for(const[part,read,...actions]of GRID_PART_API){const load=part==="cell-range"?"loadCellRanges":"loadColumnGroups";DataGrid.prototype[read]=()=>[];for(const name of actions){const stub=DataGrid.prototype[name]=function(...args){return this[load]().then(()=>{if(DataGrid.prototype[name]===stub)throw new Error("CanopyX: the "+part+" part did not install "+name+".");return this[name](...args)})}}}
|
|
965
984
|
const GRID_PARTS_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_PARTS_INIT.call(this),range=this.opts.rangeSelection??this.view.rangeSelection;const parts=[this.view.columnGroups?.length&&this.loadColumnGroups(),range&&range.enabled!==false&&this.loadCellRanges()].filter(Boolean);return parts.length?Promise.all([ready,...parts.map(part=>part.catch(error=>this.emit("error",{error})))]).then(([result])=>result):ready};function gridButton(text,run){const button=h("button","cx-button");button.type="button";setText(button,text);button.onclick=event=>{button.focus({preventScroll:true});run(event)};return button}
|
|
966
985
|
let keyboardInput=false;if(typeof document!=="undefined"){document.addEventListener("keydown",()=>{keyboardInput=true},true);document.addEventListener("pointerdown",()=>{keyboardInput=false},true)}
|
|
967
986
|
const focusDrawerTitle=title=>{if(keyboardInput&&title===document.activeElement&&!title.matches(":focus-visible"))title.blur();title.toggleAttribute("data-cx-pointer-focus",!keyboardInput);if(!keyboardInput)title.addEventListener("blur",()=>title.removeAttribute("data-cx-pointer-focus"),{once:true});title.focus({preventScroll:true,focusVisible:keyboardInput})};function gridInputLabel(text,input){const label=h("label","cx-grid-field");label.appendChild(document.createTextNode(text));label.appendChild(input);return label}
|
|
@@ -981,7 +1000,9 @@ this.runGridHook(signal=>this.opts.onChart({query:this.getQuery(),selection:this
|
|
|
981
1000
|
{kind:"ids",ids:[...this.selected],revision:this.snapshot?.revision},signal}),this.dataLifetime.signal))),"chart",true));const clear=gridDecorateButton(gridButton("",()=>this.setSelection([])),"close",true);clear.classList.add("icon");clear.setAttribute("aria-label",this.labels.gridClearSelection);this.selectionBar.appendChild(clear);this.toolbarSeparator=h("span","cx-sep");const overflow=this.overflow=this.controlPanel(this.labels.gridMore,"cx-grid-overflow");const summary=overflow.details.firstChild;summary.replaceChildren(gridIcon("more"));summary.classList.add("icon");summary.setAttribute("aria-label",this.labels.gridMore);for(const action of[...this.opts.actions||[],...pluginItems(this,"menuItems")])overflow.panel.appendChild(this.gridAction(action,act));overflow.panel.append(this.toolbar.querySelector(".cx-grid-details"),this.toolbar.querySelector(".cx-grid-print")||
|
|
982
1001
|
Object.assign(gridButton(this.labels.gridPrint,()=>global.print()),{className:"cx-button cx-grid-print"}));(this.toolbar.querySelector(".cx-grid-export")||overflow.details).before(this.spacer,this.selectionBar,this.toolbarSeparator);for(const item of pluginItems(this,"toolbarItems"))this.spacer.before(this.gridAction(item,act));if(this.tools.more===false){overflow.details.remove();this.overflow=null}
|
|
983
1002
|
this.host.addEventListener("canopyx:select",()=>this.syncGridChrome(),{signal});this.syncGridChrome();signal.addEventListener("abort",()=>{this.headerSelectionFlyout?.dispose();this.headerMenusLifetime?.abort();this.closeGridPopover(false)},{once:true})},syncGridChrome(){if(!this.selectionBar)return;const count=this.querySelection?this.querySelection.matched===null?null:Math.max(0,this.querySelection.matched-this.selectionExcluded.size):this.selected.size;const selected=count===null||count>0;this.selectionBar.hidden=!selected;this.toolbarSeparator.hidden=!selected;this.host.classList.toggle("cx-has-selection",selected);gridCountLabel(this.selectedCount,count===null?this.labels.gridSelectionQueryUnknown:this.labels.gridSelectionCount,{count:numberFormat(this.lang).format(count),excluded:String(this.selectionExcluded?.size||0)});const filterSummary=this.toolbar.querySelector(".cx-grid-filters > summary"),active=gridFilterCount(this.acceptedQuery);if(filterSummary){filterSummary.classList.toggle("active",!!active);filterSummary.querySelector(".badge")?.remove();if(active){const badge=h("span","badge");setText(badge,String(active));filterSummary.appendChild(badge)}}
|
|
984
|
-
for(const button of this.selectionBar.querySelectorAll("button"))button.disabled=!!this.pendingQuery||!this.acceptedQuery;this.syncGridStatus?.()},updateGridPhone(){const phone=this.host.clientWidth<=640;this.host.classList.toggle("cx-phone",phone);if(phone===this.phone)return;
|
|
1003
|
+
for(const button of this.selectionBar.querySelectorAll("button"))button.disabled=!!this.pendingQuery||!this.acceptedQuery;this.syncGridStatus?.()},updateGridPhone(){const phone=this.host.clientWidth<=640,autoRows=this.authoredAutoRows||phone&&(this.layoutMode||"fit")==="fit";this.host.classList.toggle("cx-phone",phone);if(phone===this.phone&&autoRows===this.autoRows)return;const anchor=this.gridRowAnchor();const changedRows=autoRows!==this.autoRows;this.phone=phone;this.autoRows=autoRows;if(changedRows){this.rowOffsets=null;this.rowHeights?.clear()}
|
|
1004
|
+
this.rowWidthShape=null;if(!this.autoRows&&!this.rowProjection){const bounds=this.rowBounds();this.total=Math.max(0,bounds.last-bounds.first+1)*this.rowH;this.syncScrollRange(this.rowTop(anchor.index)+ Math.min(anchor.offset,this.rowH-1))}
|
|
1005
|
+
this.version++;this.scheduleRender();this.placeMenus(phone);this.syncPinnedShadows()},syncPinnedShadows(){if(!this.pinnedLeftWidth&&!this.pinnedRightWidth)return;this.host.classList.toggle("cx-scroll-left",this.grid.scrollLeft>0);this.host.classList.toggle("cx-scroll-right",this.grid.scrollLeft+this.grid.clientWidth<this.grid.scrollWidth-1)},gridAction(action,act){if(!action||typeof action.label!=="string"||typeof action.run!=="function")throw new Error("CanopyX: actions need a label and handler.");return gridButton(action.label,()=>act(()=>this.runGridHook(signal=>action.run({query:this.getQuery(),signal,api:this.host.canopyx}),this.dataLifetime.signal)))}});function gridColumnFiltered(query,id){const has=group=>group&&(group.filters.some(item=>item.column===id)||group.groups.some(has));return!!query&&(query.filters.some(item=>item.column===id)||!!has(query.filterGroup))}
|
|
985
1006
|
function gridColumnProjection(query,id){const project=group=>{if(!group)return undefined;const filters=group.filters.filter(item=>item.column!==id),groups=group.groups.map(project);if(group.operator==="or"&&(filters.length!==group.filters.length||groups.some(child=>!child)))return undefined;const children=groups.filter(Boolean);return filters.length||children.length?{operator:group.operator,filters,groups:children}:undefined};return{...query,filters:(query.filters||[]).filter(item=>item.column!==id),filterGroup:project(query.filterGroup)}}
|
|
986
1007
|
Object.assign(DataGrid.prototype,{closeGridPopover(focus=true){const open=this.gridPopover;if(!open)return;this.gridPopover=null;open.controller.abort();open.panel.remove();open.anchor?.setAttribute("aria-expanded","false");if(focus){const anchor=open.anchor?.isConnected&&!open.anchor.hidden?open.anchor:this.headRow.querySelector('[data-cx-column-menu="'+CSS.escape(open.columnId||"")+'"]');(anchor||this.grid).focus({preventScroll:true})}},buildColumnMenus(){this.headerMenusLifetime?.abort();this.headerMenusLifetime=new AbortController();const signal=this.headerMenusLifetime.signal;for(const cell of this.headCells){const id=cell.dataset.cxColumn,column=this.columns.find(item=>item.id===id);const filter=gridDecorateButton(gridButton("",()=>this.openColumnFilter(id,filter)),"filter",true),menu=gridDecorateButton(gridButton("",()=>this.openColumnMenu(id,menu)),"more",true);filter.classList.add("cx-grid-header-filter","icon");menu.classList.add("cx-grid-column-menu","icon");filter.dataset.cxFilterColumn=id;menu.dataset.cxColumnMenu=id;filter.setAttribute("aria-label",this.labels.gridHeaderFilter?fill(this.labels.gridHeaderFilter,{column:column.title}):column.title+": "+this.labels.gridFilterColumn);menu.setAttribute("aria-label",fill(this.labels.gridColumnMenu,{column:column.title}));menu.setAttribute("aria-haspopup","menu");menu.setAttribute("aria-expanded","false");filter.dataset.cxFiltered=String(gridColumnFiltered(this.acceptedQuery,id));filter.hidden=filter.dataset.cxFiltered!=="true";menu.addEventListener("keydown",event=>{if(event.key==="ArrowDown"){event.preventDefault();this.openColumnMenu(id,menu)}},{signal});cell.insertBefore(filter,cell.querySelector(".cx-resize"));if(this.tools.columnMenus!==false)cell.insertBefore(menu,cell.querySelector(".cx-resize"))}
|
|
987
1008
|
if(this.gridPopover)this.gridPopover.position()}});const GRID_PIN_PREPARE=DataGrid.prototype.prepareState,GRID_PIN_WIDTHS=DataGrid.prototype.applyWidths,GRID_PIN_CELL=DataGrid.prototype.newCell;function gridPinGeometry(grid){const width=column=>column.renderWidth??column.width;const budget=Math.max(0,grid.grid.clientWidth-(grid.view.reporting?.minimumCenterWidth||128));for(const column of grid.columns)column.effectivePin="none";const pinned=grid.cols.filter(column=>column.pin==="left"),identity=grid.layoutMode==="scroll"&&grid.cols[pinned.length];const left=identity?.identity&&identity.pin==="none"?[...pinned,identity]:pinned,right=grid.cols.filter(column=>column.pin==="right").reverse();const pinOf=column=>left.includes(column)?"left":column.pin;let used=0;const stopped=[false,false];for(let index=0;index<Math.max(left.length,right.length);index++)for(const[side,column]of[left[index],right[index]].entries())if(column&&!stopped[side]){if(used+width(column)>budget)stopped[side]=true;else{used+=width(column);column.effectivePin=pinOf(column)}}
|
|
@@ -1005,9 +1026,15 @@ throw new Error("CanopyX: details require an accepted query.");const row=[...thi
|
|
|
1005
1026
|
if(this.detailController)this.detailController.abort();const controller=this.detailController=new AbortController(),dataSignal=this.dataLifetime.signal;const abort=()=>controller.abort();dataSignal.addEventListener("abort",abort,{once:true});const record=gridFreeze(JSON.parse(JSON.stringify(row.h))),query=this.acceptedQuery,returnFocus=document.activeElement;return this.runGridHook(signal=>this.opts.onDetails({row:record,query,signal,returnFocus}),controller.signal)
|
|
1006
1027
|
.finally(()=>{dataSignal.removeEventListener("abort",abort);if(this.detailController===controller)this.detailController=null})}});DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridExport:"Export",gridFilteredResults:"Filtered results",gridSelectedRows:"Selected rows",gridAllResults:"All results",gridVisibleRows:"Visible rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridDetails:"Record details",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridNoExportColumns:"No visible columns allow export."}));const GRID_EXPORT_PART=definePart(DataGrid,"export","export part",()=>({...FILTER_EDITOR.context(),EXPORT_IMPL,gridOperationActive,formatting,validateGridCursorPage,validateGridPage,gridFreeze,isCellObject,exportTimeout,exportFormat,EXPORT_FORMATS,gridExportField}));function loadExportPart(){return loadPart(GRID_EXPORT_PART)}
|
|
1007
1028
|
for(const name of["toCsv","copy","exportToHost"])DataGrid.prototype[name]=function(...args){const capture=this.prepareExport(args.at(-1));return loadExportPart().then(()=>EXPORT_IMPL[name].call(this,capture,...args))};for(const name of["exportText","copyFocused"])DataGrid.prototype[name]=function(...args){return loadExportPart().then(()=>EXPORT_IMPL[name].apply(this,args))};Object.assign(DataGrid.prototype,{async*exportRows(...args){await loadExportPart();yield*EXPORT_IMPL.exportRows.apply(this,args)},exportAs(format,options){return exportAs(this,format,options)},buildExportControls(){this.toolbar.appendChild(Object.assign(gridButton(this.labels.gridDetails,()=>{try{const row=this.focused||[...this.rowCache.values()].find(item=>this.selected.has(item.key));if(!row||row.status)throw new Error("CanopyX: focus a record for details.");this.openDetails(row.key).catch(error=>this.emit("error",{error}))}catch(error){this.emit("error",{error})}}),{className:"cx-button cx-grid-details"}));if(this.tools.export!==false)this.exportControl=this.controlPanel(this.labels.gridExport,"cx-grid-export",panel=>this.renderGridExport(panel))},async renderGridExport(panel){if(panel.firstChild)return;setText(panel,this.labels.loading);try{await loadExportPart();if(!this.destroyed&&panel.isConnected){this.renderGridExport(panel);this.controlFlyouts.forEach(item=>item.position())}}
|
|
1008
|
-
catch(error){if(!this.destroyed&&panel.isConnected){setText(panel,this.labels.gridLoadFailed);panel.appendChild(gridButton(this.labels.gridRetry,()=>this.renderGridExport(panel,setText(panel,""))));this.emit("error",{error})}}}});DataGrid.prototype.
|
|
1009
|
-
if(!button){button=gridButton("",()=>Promise.resolve().then(()=>this.openDetails(button.dataset.cxRecord)).catch(error=>this.emit("error",{error})));button.classList.add("cx-hidden-fields");button.tabIndex=-1}
|
|
1010
|
-
|
|
1029
|
+
catch(error){if(!this.destroyed&&panel.isConnected){setText(panel,this.labels.gridLoadFailed);panel.appendChild(gridButton(this.labels.gridRetry,()=>this.renderGridExport(panel,setText(panel,""))));this.emit("error",{error})}}}});DataGrid.prototype.hiddenViewColumns=function(){return this.columns.filter(column=>!column.hidden&&(column.responsiveHidden||column.fitHidden))};DataGrid.prototype.phoneLineColumns=function(){if(this.host.clientWidth>640||(this.layoutMode||"fit")!=="fit")return[];const hidden=this.hiddenViewColumns().sort((a,b)=>gridRank(a)- gridRank(b));const compact=this.columns.filter(column=>!column.hidden&&!column.responsiveHidden&&!column.fitHidden).length<=2;return hidden.filter(column=>gridLevel(column)===0||compact).slice(0,2)};DataGrid.prototype.phoneRemainingColumns=function(){const shown=this.phoneLineColumns();return this.hiddenViewColumns().filter(column=>!shown.includes(column))};DataGrid.prototype.hiddenFieldCount=function(){return this.phoneRemainingColumns().length};DataGrid.prototype.hiddenFieldLabel=function(){const count=this.hiddenFieldCount();return fill(plural(this.labels.hiddenColumns,count,this.lang),{count:numberFormat(this.lang).format(count)})};DataGrid.prototype.paintHiddenFields=function(slot,row,column){if(this.phone&&column.identity)slot.cell.title=cellText(row.cells[column.id],column,this.fmt)||"";const first=this.phone&&column===this.cols[0],fields=first?this.phoneLineColumns():[];let button=slot.hiddenFields;const count=first&&this.hiddenFieldCount();if(!count){button?.remove();slot.hiddenFields=null}
|
|
1030
|
+
else{if(!button){button=gridButton("",()=>Promise.resolve().then(()=>this.openDetails(button.dataset.cxRecord)).catch(error=>this.emit("error",{error})));button.classList.add("cx-hidden-fields");button.tabIndex=-1}
|
|
1031
|
+
const label=this.hiddenFieldLabel(),titles=this.phoneRemainingColumns().map(item=>item.title).join(", ");button.dataset.cxRecord=row.id;button.setAttribute("aria-label",label+": "+titles);button.title=titles;setText(button,label);slot.hiddenFields=button}
|
|
1032
|
+
if(!first){slot.childSlots?.forEach(disposeHostSlot);slot.childSlots=null;slot.phoneLine?.remove();slot.phoneLine=null;if(slot.phonePrimary){slot.phonePrimary.replaceWith(...slot.phonePrimary.childNodes);slot.phonePrimary=null}
|
|
1033
|
+
return}
|
|
1034
|
+
let primary=slot.phonePrimary;if(!primary||primary.parentNode!==slot.cell)primary=h("span","cx-phone-primary");for(const node of[...slot.cell.childNodes])if(node!==primary&&node!==slot.phoneLine&&node!==button)primary.appendChild(node);if(primary.parentNode!==slot.cell)slot.cell.prepend(primary);slot.phonePrimary=primary;if(!fields.length&&!count){slot.childSlots?.forEach(disposeHostSlot);slot.childSlots=null;slot.phoneLine?.remove();slot.phoneLine=null;return}
|
|
1035
|
+
let line=slot.phoneLine;if(!line||line.parentNode!==slot.cell){line=h("span","cx-phone-fields");slot.cell.appendChild(line)}
|
|
1036
|
+
slot.phoneLine=line;const shape=JSON.stringify(fields.map(item=>item.id));if(line.dataset.cxFields!==shape){slot.childSlots?.forEach(disposeHostSlot);line.replaceChildren();line.dataset.cxFields=shape;slot.childSlots=[];for(const field of fields){const item=h("span","cx-phone-field"),label=h("span","cx-phone-field-title"),value=h("span","cx-phone-value");setText(label,field.title+":");item.append(label,value);line.appendChild(item);const content=value.appendChild(h("span","cx-content")),textSpan=content.appendChild(h("span","cx-text"));slot.childSlots.push({cell:value,content,base:"cx-phone-value",cls:null,title:null,badges:[],mode:"default",textSpan,text:textSpan.appendChild(document.createTextNode(""))})}}
|
|
1037
|
+
if(count&&button.parentNode!==line)line.appendChild(button);fields.forEach((field,index)=>{this.paintSlot(slot.childSlots[index],row,field,this.columns.indexOf(field),{level:0,expanded:false});slot.childSlots[index].cell.title=cellText(row.cells[field.id],field,this.fmt)||""})};LINK_IMPL.DataGrid=DataGrid;LINK_IMPL.gridQueryStart=gridQueryStart;linkMethods(DataGrid);linkGridPart(DataGrid);function createDataGrid(host,options){if(!host||!options||!options.view)throw new Error("CanopyX: createDataGrid needs a host element and a grid document.");const existing=activeGrids.get(host);if(existing)return existing;const grid=new DataGrid(host,options);const api={element:host,view:grid.view,ready:startPlugins(grid,()=>api),getTimeZone:()=>grid.local?"local":"utc",getSelection:()=>[...grid.selected],clearSelection:()=>grid.setSelection([]),getLoadedRows:ids=>{const wanted=new Set(Array.isArray(ids)?ids:[]),rows=[];for(const row of grid.rowCache.values())if(wanted.has(row.key))rows.push({id:row.key,cells:JSON.parse(JSON.stringify(row.h.cells||{}))});return rows},focus:()=>grid.setFocus(grid.focused||grid.rowItem(grid.rowAt(grid.logicalTop())),true),refresh:()=>{grid.version++;grid.scheduleRender()},reload:()=>grid.setQuery(gridQueryStart(grid.queryForChange(true)),grid.pendingPaging&&
|
|
1011
1038
|
{pageLength:grid.pendingPaging.pageLength,allRows:grid.pendingPaging.allRows}),destroy:()=>{grid.destroy();if(activeGrids.get(host)===api)activeGrids.delete(host);if(host.canopyx===api)delete host.canopyx}};for(const name of["getQuery","setQuery","sort","getPaging","goToPage","setPageLength","firstPage","previousPage","nextPage","setColumnWidth","autoFitColumn","autoFitColumns","autoSizeColumns","setColumnPriority","resetColumns","setColumnPinned","setColumnVisible","setColumnOrder","getState","setState","resetView","getSavedViews","saveView","applySavedView","removeSavedView","setTimeZone","setSelection","prepareExport","toCsv","copy","exportToHost","exportAs","openDetails","openRecord","scrollToRow","retry","closeMenus","getFormatRules","setFormatRules","openFormatRules","getLayout","setLayout","getMatches","setSearchHighlight","nextMatch","previousMatch",...GRID_EDIT_API,...GRID_LIVE_API,...GRID_CALENDAR_API,"getLiveState","getFacetPanel","setFacetPanelOpen"])
|
|
1012
1039
|
api[name]=(...args)=>grid[name](...args);for(const[,read,...names]of GRID_PART_API){api[read]=(...args)=>grid[read](...args);for(const name of names)api[name]=(...args)=>{try{return Promise.resolve(grid[name](...args))}catch(error){return Promise.reject(error)}}}
|
|
1013
1040
|
GRID_REPORTING.api?.(api,grid);Object.assign(api,linkApi(grid));api.ready=linkReady(grid,api.ready);Object.freeze(api);activeGrids.set(host,api);host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;recordStart(grid);return api}
|
|
@@ -1162,5 +1189,5 @@ watcher.observe(host)}
|
|
|
1162
1189
|
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}
|
|
1163
1190
|
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}}
|
|
1164
1191
|
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}
|
|
1165
|
-
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}
|
|
1166
|
-
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{}));if(typeof document!=="undefined"){const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}}})(runtimeHost);const CanopyX=runtimeHost.CanopyX;const{protocol,createTreeGrid,createDataGrid,createCalendar,createFlow,createMatrix,enhance,grid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce}=CanopyX;export{protocol,createTreeGrid,createDataGrid,createCalendar,createFlow,createMatrix,enhance,grid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce};export default CanopyX;
|
|
1192
|
+
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}
|
|
1193
|
+
global.CanopyX=Object.freeze(Object.assign({protocol:PROTOCOL,createTreeGrid,configure,unconfigure,mount:(root)=>mount(root,false),sources:Object.freeze({inline:inlineSource,sidecar:sidecarSource,remote:remoteSource}),badge:hostBadge,labels:DEFAULT_LABELS,registerExportFormat,use,registerPart,setNonce},typeof GRID_API==="object"?GRID_API:{},typeof FLOW_API==="object"?FLOW_API:{},typeof MATRIX_API==="object"?MATRIX_API:{},typeof CHANGES_API==="object"?CHANGES_API:{}));if(typeof document!=="undefined"){const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mount(document,true))}else{mount(document,true)}}})(runtimeHost);const CanopyX=runtimeHost.CanopyX;const{protocol,createTreeGrid,createDataGrid,createCalendar,createFlow,createMatrix,createDiff,createChangeList,createPropagation,enhance,grid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce}=CanopyX;export{protocol,createTreeGrid,createDataGrid,createCalendar,createFlow,createMatrix,createDiff,createChangeList,createPropagation,enhance,grid,configure,unconfigure,mount,sources,badge,labels,registerExportFormat,use,registerPart,setNonce};export default CanopyX;
|