@evotecit/canopyx 0.3.6 → 0.3.7
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-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 +62 -40
- package/CanopyX.Html/Assets/canopyx-grid.css +22 -0
- package/CanopyX.Html/Assets/canopyx-grid.js +62 -40
- package/CanopyX.Html/Assets/canopyx-interactive.js +4 -4
- package/CanopyX.Html/Assets/canopyx-labels-de.js +3 -1
- package/CanopyX.Html/Assets/canopyx-labels-es.js +3 -1
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +3 -1
- package/CanopyX.Html/Assets/canopyx-labels-it.js +3 -1
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +3 -1
- package/CanopyX.Html/Assets/canopyx-live.js +4 -3
- package/CanopyX.Html/Assets/canopyx-matrix.js +3 -3
- package/CanopyX.Html/Assets/canopyx-module.mjs +4 -4
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +64 -42
- package/CanopyX.Html/Assets/canopyx-reporting.css +22 -0
- package/CanopyX.Html/Assets/canopyx-reporting.js +64 -42
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +7 -6
- package/CanopyX.Html/Assets/canopyx.js +4 -4
- package/JavaScript/grid.d.ts +6 -0
- package/JavaScript/locales/de.mjs +3 -1
- package/JavaScript/locales/es.mjs +3 -1
- package/JavaScript/locales/fr.mjs +3 -1
- package/JavaScript/locales/it.mjs +3 -1
- package/JavaScript/locales/pl.mjs +3 -1
- package/JavaScript/protocol.d.ts +1 -1
- package/README.md +6 -2
- package/package.json +1 -1
|
@@ -60,7 +60,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
60
60
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
61
61
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
62
62
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
63
|
-
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
63
|
+
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
64
64
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
65
65
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
66
66
|
return Object.freeze(labels)}
|
|
@@ -334,7 +334,7 @@ function hostRenderers(renderers,columns,plugins){if(![Object.prototype,null].in
|
|
|
334
334
|
Object.keys(renderers).some(id=>typeof renderers[id]!=="function"||!columns.some(column=>column.id===id)))
|
|
335
335
|
throw new Error("CanopyX: invalid column renderers.");const named=Object.assign(Object.create(null),...plugins.map(item=>item.cellRenderers));return Object.assign(Object.create(null),...columns.filter(column=>typeof column.renderer==="string"&&named[column.renderer])
|
|
336
336
|
.map(column=>({[column.id]:named[column.renderer]})),renderers)}
|
|
337
|
-
function disposeHostSlot(slot){const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
|
|
337
|
+
function disposeHostSlot(slot){slot.childSlots?.forEach(disposeHostSlot);const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
|
|
338
338
|
function disposeRowHostCells(row){row._cells?.forEach(disposeHostSlot)}
|
|
339
339
|
class HostCellContext{#controller;#cleanups;constructor(slot,column,level,expanded,index){slot.hostLifetime=this;this.column=column;this.level=level;this.expanded=expanded;this.index=index}
|
|
340
340
|
get signal(){this.#controller||=new AbortController();if(this.#cleanups===null)this.#controller.abort();return this.#controller.signal}
|
|
@@ -504,7 +504,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
|
|
|
504
504
|
active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
|
|
505
505
|
close()}else{return}
|
|
506
506
|
e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
|
|
507
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["
|
|
507
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["4c6c4101089c4444","canopyx-tree-tools.510207e8f47014fd.js","canopyx-tree-tools.ef7a3fb9c9115a82.css"],"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":["b7324bd75b73b9a3","canopyx-matrix.c8e156769fe3eb9d.js","canopyx-matrix.b6ea56044183ca82.css"],"editing":["c82648dfaa7e5ee5","canopyx-editing.4fe83feec389c2ce.js","canopyx-editing.67c43d3b80f20232.css"],"column-groups":["b42238fd108a8614","canopyx-column-groups.d8ad6322f769b915.js","canopyx-column-groups.37e177d74cebb516.css"],"cell-range":["e99a39e7cccc57b1","canopyx-cell-range.647da96e57924f3e.js","canopyx-cell-range.23f3222652588441.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["1a28068597f435de","canopyx-formatting.68c501f97b71f1ec.js","canopyx-formatting.a59507e4e8334891.css"],"format-editor":["24f176a39c02944a","canopyx-format-editor.3b1dec2527e53988.js","canopyx-format-editor.1ba153c82aa87b04.css"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"detail-rows":["4908d1d2b7f67aa8","canopyx-detail-rows.fe29b1759c962565.js","canopyx-detail-rows.8e38a8ad01fded76.css"],"grouping":["0970f2edbcb32de8","canopyx-grouping.84660cd1a0ea5f8f.js","canopyx-grouping.6c93259b4b89e523.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"facets":["f9219d35a87635f8","canopyx-facets.8bf477b7915bdcd6.js","canopyx-facets.648a88d2f36d4999.css"],"live":["a27c818b731c22e3","canopyx-live.d19df9edc92e7d09.js","canopyx-live.cc4b94a2dec6f064.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.css"],"calendar":["762f4b4b62ecb4d8","canopyx-calendar.dc45ebdeb704d9c3.js","canopyx-calendar.1099197a45632f63.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["bdde26d4b7de2096","canopyx-calendar-edit.4ab2cf55e84f310f.js"],"calendar-ics":["feb3ed2cd67d057f","canopyx-calendar-ics.2a3af9eb3bf444fc.js"],"timeline":["3f04ba99401e9ebd","canopyx-timeline.76928f089774b3de.js","canopyx-timeline.0393f92746f8fa09.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
508
508
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
509
509
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
510
510
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -602,7 +602,7 @@ function gridDateInputMoment(text,local){const match=/^(\d{4})-(\d{2})-(\d{2})T(
|
|
|
602
602
|
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}
|
|
603
603
|
function gridFreeze(value){if(value&&typeof value==="object"&&!Object.isFrozen(value)){Object.values(value).forEach(gridFreeze);Object.freeze(value)}
|
|
604
604
|
return value}
|
|
605
|
-
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
|
|
605
|
+
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)}
|
|
606
606
|
function gridDecorateButton(button,icon,ghost){button.classList.add("cx-btn");if(ghost)button.classList.add("ghost");if(icon)button.prepend(gridIcon(icon));return button}
|
|
607
607
|
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)}
|
|
608
608
|
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)}
|
|
@@ -625,7 +625,10 @@ function gridQueryStart(query,patch){return{...query,...patch,offset:0,cursor:un
|
|
|
625
625
|
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||
|
|
626
626
|
Object.keys(format).some(key=>!["minimumFractionDigits","maximumFractionDigits","prefix","suffix"].includes(key))||
|
|
627
627
|
[format.prefix,format.suffix].some(text=>text!==undefined&&(typeof text!=="string"||!text||text.length>16)))throw new Error("CanopyX: invalid number format.")}
|
|
628
|
-
function validateGridView(view){checkDocument(view,"grid");requireIdentifier(view.id,"grid ID");if(
|
|
628
|
+
function validateGridView(view){checkDocument(view,"grid");requireIdentifier(view.id,"grid ID");if(view.rowIdentity!==undefined&&!["stableKey","ordinal"].includes(view.rowIdentity))
|
|
629
|
+
throw new Error("CanopyX: rowIdentity must be stableKey or ordinal.");if(view.rowIdentity==="ordinal"&&view.live)
|
|
630
|
+
throw new Error("CanopyX: ordinal row identity is snapshot-local; keyed live updates require stable row keys.");if(view.rowIdentity==="ordinal"&&view.record?.deepLink)
|
|
631
|
+
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)
|
|
629
632
|
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)}
|
|
630
633
|
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)||
|
|
631
634
|
column.width!==undefined&&(!Number.isInteger(column.width)||column.width<40)||
|
|
@@ -706,9 +709,10 @@ gridResultShape(gridColumnProjection(request.query,request.column))!==gridResult
|
|
|
706
709
|
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)
|
|
707
710
|
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)
|
|
708
711
|
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})}
|
|
709
|
-
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(
|
|
712
|
+
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)
|
|
713
|
+
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=[]}
|
|
710
714
|
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"))
|
|
711
|
-
throw new Error("CanopyX: source navigation must match the grid definition.");this.pageSize=this.view.pageSize;this.
|
|
715
|
+
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?
|
|
712
716
|
this.view.source.kind==="inline"?0:300:this.view.searchDelayMs:options.searchDelayMs;if(!Number.isInteger(this.searchDelayMs)||this.searchDelayMs<0||this.searchDelayMs>5000)
|
|
713
717
|
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||
|
|
714
718
|
!Number.isInteger(this.requestTimeoutMs)||this.requestTimeoutMs<1||this.requestTimeoutMs>2147483647)
|
|
@@ -724,7 +728,7 @@ async setQuery(input,paging){if(this.destroyed)throw new DOMException("Grid was
|
|
|
724
728
|
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;
|
|
725
729
|
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);
|
|
726
730
|
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)}}
|
|
727
|
-
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}
|
|
731
|
+
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}
|
|
728
732
|
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}
|
|
729
733
|
this.render();if(hadFocus){const element=this.focused&&this.rendered.get(this.focused);(element||this.grid).focus({preventScroll:true})}
|
|
730
734
|
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})}
|
|
@@ -743,8 +747,9 @@ render(){if(this.destroyed||!this.sized)return;let measured=false;if(this.autoRo
|
|
|
743
747
|
for(const[index,row]of this.placeholders)if(!this.rendered.has(row)&&this.focused!==row)this.placeholders.delete(index);this.loadWindow();return measured}
|
|
744
748
|
observeDetail(){}
|
|
745
749
|
trimInactiveCache(){this.trimPages()}
|
|
750
|
+
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()}}
|
|
746
751
|
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()}
|
|
747
|
-
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()}
|
|
752
|
+
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()}
|
|
748
753
|
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")}}
|
|
749
754
|
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)
|
|
750
755
|
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.")}
|
|
@@ -789,17 +794,17 @@ this.activateRow(row,false)},{signal});grid.addEventListener("keydown",event=>th
|
|
|
789
794
|
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)
|
|
790
795
|
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}
|
|
791
796
|
style.setProperty("--cx-min-h",(this.toolbar.hidden?0:[...host.children].reduce((height,child)=>
|
|
792
|
-
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)}
|
|
797
|
+
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)}
|
|
793
798
|
this.scheduleRender()}));this.resizeObserver.observe(grid);this.resizeObserver.observe(this.head)},setLogicalTop(top){if(!this.hasGridSize()){this.hiddenScrollTop=top;return}
|
|
794
|
-
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
|
|
799
|
+
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)}
|
|
800
|
+
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)}
|
|
795
801
|
button.setAttribute("aria-label",cell.getAttribute("aria-label")+ ", "+sorts[index].direction+", " +(index+1))}}
|
|
796
802
|
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})}
|
|
797
|
-
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}
|
|
798
|
-
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 || ""
|
|
803
|
+
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 || ""
|
|
799
804
|
}):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}
|
|
800
805
|
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}
|
|
801
806
|
else if(slot.missing){slot.cell.classList.remove("p-missing");slot.missing=false}
|
|
802
|
-
if(this.phone||slot.hiddenFields)this.paintHiddenFields?.(slot,row.h,column,this.columnIndex[i])}
|
|
807
|
+
if(this.phone||slot.hiddenFields||slot.phonePrimary)this.paintHiddenFields?.(slot,row.h,column,this.columnIndex[i])}
|
|
803
808
|
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}
|
|
804
809
|
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]}
|
|
805
810
|
return this}
|
|
@@ -820,16 +825,17 @@ this.total=this.rowOffsets.top(count);this.syncScrollRange(this.logicalTop());th
|
|
|
820
825
|
if(changed){this.total=this.rowOffsets.top(this.rowOffsets.count);this.syncScrollRange(rows.rowTop(anchor.index)+ anchor.offset)}
|
|
821
826
|
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));
|
|
822
827
|
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()}
|
|
823
|
-
return measured};DataGrid.prototype.fitHeight=function(){if(this.view.autoHeight===false||!this.
|
|
828
|
+
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;
|
|
824
829
|
}
|
|
825
|
-
const height=Math.ceil(this.host.
|
|
830
|
+
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}
|
|
826
831
|
function gridRank(column){const value=column.priority;return typeof value==="number"?value:value==="optional"?10000:value==="essential"||value===undefined&&column.identity?0:5000}
|
|
827
832
|
function gridLevel(column){const rank=gridRank(column);return rank<2?0:rank<10000?1:2}
|
|
828
833
|
function gridOptions(column){return column.presenter||{}}
|
|
829
834
|
const COLUMN_DIGITS=new Map(),COLUMN_NUMERIC_CHARS="0123456789 .,:;+-−/()[]\u00a0\u202f",COLUMN_HAS_NUMERIC=/[0-9\s.,:;+\-−/()\[\]]/;
|
|
830
835
|
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)}
|
|
831
836
|
const variant=getComputedStyle(sample).fontVariantNumeric;if(owned)sample.remove();return variant}
|
|
832
|
-
function gridClassFont(grid,className){const probe=
|
|
837
|
+
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}
|
|
838
|
+
probe.remove();return font}
|
|
833
839
|
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())}
|
|
834
840
|
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)}
|
|
835
841
|
document.body.appendChild(probe);const zero=glyphs[0].getBoundingClientRect().width / 50, numeric = new Map(), plain = new Map();
|
|
@@ -851,23 +857,30 @@ return excess},fitSpare(columns,spare){let target,flex=columns.filter(column=>co
|
|
|
851
857
|
flex=flex.filter(column=>column.maxW-column.renderWidth>0.5)}
|
|
852
858
|
const identity=columns.find(column=>column.identity),widest=columns.filter(column=>!column.identity&&
|
|
853
859
|
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));
|
|
854
|
-
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 +=
|
|
855
|
-
if(total>width&&remaining>1){column.fitHidden=true;total -=
|
|
856
|
-
if(identity&&!identity.fixed&&!identity.sized)total +=Math.min(identity.need??identity.width,(identity.indentNeed||0)+ 2*(this.fitCh||88))+(identity.reserve||0)-
|
|
857
|
-
if(total>width){column.fitHidden=true;total -=
|
|
860
|
+
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))
|
|
861
|
+
if(total>width&&remaining>1){column.fitHidden=true;total -=size(column);remaining--}
|
|
862
|
+
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))
|
|
863
|
+
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"}
|
|
858
864
|
grid.columns=["left","none","right"].flatMap(side=>grid.columns.filter(column=>column.pin===side))}
|
|
859
|
-
Object.assign(DataGrid.prototype,COLUMN_FIT,{
|
|
860
|
-
|
|
861
|
-
return
|
|
865
|
+
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)
|
|
866
|
+
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)))}
|
|
867
|
+
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;
|
|
868
|
+
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;
|
|
869
|
+
columns.forEach((column,index)=>column.renderWidth +=deficits[index]*ratio);spare=Math.max(0,spare-total)}
|
|
870
|
+
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}
|
|
871
|
+
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})}
|
|
872
|
+
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}
|
|
862
873
|
queueMicrotask(()=>this.destroyed||this.applyWidths())}
|
|
863
|
-
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}}
|
|
864
|
-
for(const column of this.columns){
|
|
865
|
-
this.fitHide(shown,width,phone)
|
|
866
|
-
const[
|
|
867
|
-
(query?.sort.some(sort=>sort.column===column.id)?22:0)+(gridColumnFiltered(query,column.id)?24:0)+(first&&this.selectionControls?26:0)
|
|
868
|
-
Math.min(
|
|
869
|
-
(kind==="
|
|
870
|
-
|
|
874
|
+
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}}
|
|
875
|
+
for(const column of this.columns){if(!column.fixed&&!column.sized)column.width=this.fitSize(column)}
|
|
876
|
+
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))}
|
|
877
|
+
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 +
|
|
878
|
+
(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+/);
|
|
879
|
+
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)+
|
|
880
|
+
(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:
|
|
881
|
+
Math.min(kind==="longText"||kind==="tags"||kind==="list"||column.wrap?320:420,text(value))+
|
|
882
|
+
(kind==="progress"?80:kind==="tags"||kind==="list"?48:0));sampled++}
|
|
883
|
+
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}
|
|
871
884
|
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})}
|
|
872
885
|
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||
|
|
873
886
|
rule.target!==undefined&&!["row","cell"].includes(rule.target)||rule.tone===undefined&&rule.className===undefined)
|
|
@@ -931,12 +944,13 @@ if(event.key!=="F2")return false;GRID_DRAG.picked=gridDragItem(this,row);setText
|
|
|
931
944
|
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}
|
|
932
945
|
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. */ }
|
|
933
946
|
}}
|
|
934
|
-
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)||
|
|
947
|
+
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)||
|
|
935
948
|
!Number.isFinite(state.scrollTop)||state.scrollTop<0||state.scrollTop>MAX_PROTOCOL_INTEGER*this.rowH||!Array.isArray(state.selection))
|
|
936
|
-
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.
|
|
949
|
+
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)
|
|
950
|
+
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")||
|
|
937
951
|
!Number.isInteger(paging.offset)||paging.offset<0||paging.offset>MAX_PROTOCOL_INTEGER||this.cursor&&paging.offset!==0)
|
|
938
952
|
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)}
|
|
939
|
-
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||
|
|
953
|
+
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||
|
|
940
954
|
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}))}))}
|
|
941
955
|
catch(_){/* A disabled or full storage leaves the current session usable. */ }
|
|
942
956
|
}});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()))
|
|
@@ -952,7 +966,7 @@ return roots}
|
|
|
952
966
|
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")
|
|
953
967
|
throw new Error("CanopyX: invalid saved facet panel state.");if(this.view.facets||this.opts.facets)state.facets={open:facets.open}}
|
|
954
968
|
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}
|
|
955
|
-
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())
|
|
969
|
+
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())
|
|
956
970
|
.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")||
|
|
957
971
|
!!row&&Object.values(row.cells).some(cell=>isCellObject(cell)&&RECORD_STRUCTURE.some(name=>cell[name]!==undefined))};const GRID_RECORD_INIT=DataGrid.prototype.initializeState;DataGrid.prototype.initializeState=function(){const ready=GRID_RECORD_INIT.call(this);return this.columns.some(column=>column.presenter?.kind==="structured")?Promise.all([ready,this.loadRecordPanel()]).then(([result])=>result):ready};const GRID_DATA_IMPL={},GRID_DATA=definePart(DataGrid,"data","row data",()=>({GRID_DATA_IMPL,PROTOCOL,validateGridRows,inlineGridSource,loadSidecar,gridIdOrder}));function rowDataSource(grid){let inner=null;const source={reset:()=>{inner=null},query:(query,options)=>
|
|
958
972
|
(inner||=loadPart(GRID_DATA).then(()=>GRID_DATA_IMPL.source(grid,source)).catch(error=>{inner=null;throw error})).then(rows=>rows.query(query,options))};return source}
|
|
@@ -979,7 +993,9 @@ this.runGridHook(signal=>this.opts.onChart({query:this.getQuery(),selection:this
|
|
|
979
993
|
{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")||
|
|
980
994
|
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}
|
|
981
995
|
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)}}
|
|
982
|
-
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;
|
|
996
|
+
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()}
|
|
997
|
+
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))}
|
|
998
|
+
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))}
|
|
983
999
|
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)}}
|
|
984
1000
|
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"))}
|
|
985
1001
|
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)}}
|
|
@@ -1003,9 +1019,15 @@ throw new Error("CanopyX: details require an accepted query.");const row=[...thi
|
|
|
1003
1019
|
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)
|
|
1004
1020
|
.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)}
|
|
1005
1021
|
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())}}
|
|
1006
|
-
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.
|
|
1007
|
-
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}
|
|
1008
|
-
|
|
1022
|
+
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}
|
|
1023
|
+
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}
|
|
1024
|
+
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}
|
|
1025
|
+
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}
|
|
1026
|
+
return}
|
|
1027
|
+
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}
|
|
1028
|
+
let line=slot.phoneLine;if(!line||line.parentNode!==slot.cell){line=h("span","cx-phone-fields");slot.cell.appendChild(line)}
|
|
1029
|
+
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(""))})}}
|
|
1030
|
+
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&&
|
|
1009
1031
|
{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"])
|
|
1010
1032
|
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)}}}
|
|
1011
1033
|
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}
|
|
@@ -60,7 +60,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
60
60
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
61
61
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
62
62
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
63
|
-
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
63
|
+
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
64
64
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
65
65
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
66
66
|
return Object.freeze(labels)}
|
|
@@ -74,7 +74,7 @@ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.
|
|
|
74
74
|
catch(_){trustPolicy=null}}
|
|
75
75
|
return trustPolicy?trustPolicy["create"+kind](value):value}
|
|
76
76
|
function hostHtml(element,html,sanitize,kind){const text=String(html??""),value=sanitize?sanitize(text,{kind}):text;if(value?.nodeType)element.replaceChildren(value);else if(typeof value==="string")element.innerHTML=trusted("HTML",value);else if(global.trustedTypes?.isHTML?.(value))element.innerHTML=value;else throw new Error("CanopyX: invalid sanitizeHtml result.")}
|
|
77
|
-
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridMore:"More",gridPrint:"Print",gridDetails:"Record details",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close
|
|
77
|
+
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridMore:"More",gridPrint:"Print",gridDetails:"Record details",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close"}));DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{recordBack:"Back",recordBackTo:"Back to {record}",recordTrail:"Record trail",recordShowing:"Showing {record}",recordTabs:"Record views",recordSections:"Jump to a section",recordOtherFields:"Other fields",recordShowEmpty:"Show empty fields ({count})",recordHideEmpty:"Hide empty fields",recordActions:"Record actions",recordCopyValues:"Copy values",recordCopyJson:"Copy as JSON",recordCopyLink:"Copy link",recordCopied:"Copied to the clipboard",recordPrint:"Print record",recordExportCsv:"Export CSV",recordExportJson:"Export JSON",recordOpenAll:"Open all in grid",recordLoadMore:"Load more",recordCount:"{shown} of {total}",recordItems:"{count} items",recordMore:"+{count}",recordShowAll:"Show all {count}",recordRetry:"Retry",recordLoadFailed:"Could not load the record details: {error}",recordUnavailable:"Record {id} is not available here.",recordField:"Field",recordValue:"Value",recordSection:"Section",recordBefore:"Before",recordAfter:"After",recordAdded:"Added",recordRemoved:"Removed",recordChanged:"{count} changed fields"}));function boundedPattern(source,exact=true,whole=false){const bad=()=>{throw new Error("CanopyX: pattern requires literals, character classes and at most one variable repetition anchored at the start; groups, alternatives and backreferences are unsupported.")};if(typeof source!=="string"||source.length>256)bad();let width=0,variable=0;for(let i=0;i<source.length;){const unit=source[i++];if(unit==="^"&&i===1||unit==="$"&&i===source.length)continue;if(unit==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbBnrtfv\\.^$*+?{}\[\]()|/]$/.test(escape)) bad();
|
|
78
78
|
}else if(unit==="["){let closed=false;while(i<source.length){const c=source[i++];if(c==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbnrtfv\\.^$*+?{}\[\]()|/-]$/.test(escape)) bad(); }
|
|
79
79
|
else if(c==="]"){closed=true;break}}
|
|
80
80
|
if(!closed)bad()}else if("()|^$*+?{}]".includes(unit))bad();let count=1;if(i<source.length&&"*+?".includes(source[i])){variable++;i++}
|
|
@@ -334,7 +334,7 @@ function hostRenderers(renderers,columns,plugins){if(![Object.prototype,null].in
|
|
|
334
334
|
Object.keys(renderers).some(id=>typeof renderers[id]!=="function"||!columns.some(column=>column.id===id)))
|
|
335
335
|
throw new Error("CanopyX: invalid column renderers.");const named=Object.assign(Object.create(null),...plugins.map(item=>item.cellRenderers));return Object.assign(Object.create(null),...columns.filter(column=>typeof column.renderer==="string"&&named[column.renderer])
|
|
336
336
|
.map(column=>({[column.id]:named[column.renderer]})),renderers)}
|
|
337
|
-
function disposeHostSlot(slot){const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
|
|
337
|
+
function disposeHostSlot(slot){slot.childSlots?.forEach(disposeHostSlot);const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
|
|
338
338
|
function disposeRowHostCells(row){row._cells?.forEach(disposeHostSlot)}
|
|
339
339
|
class HostCellContext{#controller;#cleanups;constructor(slot,column,level,expanded,index){slot.hostLifetime=this;this.column=column;this.level=level;this.expanded=expanded;this.index=index}
|
|
340
340
|
get signal(){this.#controller||=new AbortController();if(this.#cleanups===null)this.#controller.abort();return this.#controller.signal}
|
|
@@ -504,7 +504,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
|
|
|
504
504
|
active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
|
|
505
505
|
close()}else{return}
|
|
506
506
|
e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
|
|
507
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["
|
|
507
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["4c6c4101089c4444","canopyx-tree-tools.510207e8f47014fd.js","canopyx-tree-tools.ef7a3fb9c9115a82.css"],"export":["8b99c0b7b0ec37c5","canopyx-export.6989ea36f5d6da7b.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
508
508
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
509
509
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
510
510
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|