@evotecit/canopyx 0.3.13 → 0.3.16

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.
Files changed (103) hide show
  1. package/CanopyX.Html/Assets/canopyx-calendar-edit.js +36 -18
  2. package/CanopyX.Html/Assets/canopyx-calendar-ics.js +7 -5
  3. package/CanopyX.Html/Assets/canopyx-calendar.css +124 -116
  4. package/CanopyX.Html/Assets/canopyx-calendar.js +74 -54
  5. package/CanopyX.Html/Assets/canopyx-cell-range.css +8 -8
  6. package/CanopyX.Html/Assets/canopyx-cell-range.js +1 -1
  7. package/CanopyX.Html/Assets/canopyx-changes.css +113 -113
  8. package/CanopyX.Html/Assets/canopyx-changes.js +7 -10
  9. package/CanopyX.Html/Assets/canopyx-column-groups.css +5 -5
  10. package/CanopyX.Html/Assets/canopyx-column-groups.js +1 -1
  11. package/CanopyX.Html/Assets/canopyx-data.js +2 -2
  12. package/CanopyX.Html/Assets/canopyx-detail-rows.css +9 -9
  13. package/CanopyX.Html/Assets/canopyx-detail-rows.js +2 -2
  14. package/CanopyX.Html/Assets/canopyx-editing.css +18 -18
  15. package/CanopyX.Html/Assets/canopyx-editing.js +1 -1
  16. package/CanopyX.Html/Assets/canopyx-enhance.js +2 -2
  17. package/CanopyX.Html/Assets/canopyx-facets.css +33 -33
  18. package/CanopyX.Html/Assets/canopyx-facets.js +5 -6
  19. package/CanopyX.Html/Assets/canopyx-filter-editor.css +57 -57
  20. package/CanopyX.Html/Assets/canopyx-filter-editor.js +7 -5
  21. package/CanopyX.Html/Assets/canopyx-flow-checks.css +13 -11
  22. package/CanopyX.Html/Assets/canopyx-flow-checks.js +5 -4
  23. package/CanopyX.Html/Assets/canopyx-flow-command.css +7 -7
  24. package/CanopyX.Html/Assets/canopyx-flow-command.js +1 -1
  25. package/CanopyX.Html/Assets/canopyx-flow-dialog.css +9 -7
  26. package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
  27. package/CanopyX.Html/Assets/canopyx-flow-drafts.css +7 -7
  28. package/CanopyX.Html/Assets/canopyx-flow-drafts.js +1 -1
  29. package/CanopyX.Html/Assets/canopyx-flow-entry.css +17 -76
  30. package/CanopyX.Html/Assets/canopyx-flow-entry.js +11 -5
  31. package/CanopyX.Html/Assets/canopyx-flow-facts.js +2 -0
  32. package/CanopyX.Html/Assets/canopyx-flow-host.css +4 -4
  33. package/CanopyX.Html/Assets/canopyx-flow-host.js +1 -1
  34. package/CanopyX.Html/Assets/canopyx-flow-module.mjs +11 -5
  35. package/CanopyX.Html/Assets/canopyx-flow-pick.css +4 -4
  36. package/CanopyX.Html/Assets/canopyx-flow-pick.js +1 -1
  37. package/CanopyX.Html/Assets/canopyx-flow-preview.css +6 -6
  38. package/CanopyX.Html/Assets/canopyx-flow-preview.js +1 -1
  39. package/CanopyX.Html/Assets/canopyx-flow-records.css +3 -3
  40. package/CanopyX.Html/Assets/canopyx-flow-records.js +1 -1
  41. package/CanopyX.Html/Assets/canopyx-flow-tasks.css +17 -17
  42. package/CanopyX.Html/Assets/canopyx-flow-tasks.js +1 -1
  43. package/CanopyX.Html/Assets/canopyx-flow.css +79 -79
  44. package/CanopyX.Html/Assets/canopyx-flow.js +8 -7
  45. package/CanopyX.Html/Assets/canopyx-format-editor.css +23 -23
  46. package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -3
  47. package/CanopyX.Html/Assets/canopyx-formatting.css +17 -17
  48. package/CanopyX.Html/Assets/canopyx-formatting.js +5 -5
  49. package/CanopyX.Html/Assets/canopyx-forms.css +5 -5
  50. package/CanopyX.Html/Assets/canopyx-forms.js +1 -1
  51. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +97 -54
  52. package/CanopyX.Html/Assets/canopyx-grid-options.css +10 -0
  53. package/CanopyX.Html/Assets/canopyx-grid-options.js +47 -0
  54. package/CanopyX.Html/Assets/canopyx-grid.css +199 -261
  55. package/CanopyX.Html/Assets/canopyx-grid.js +97 -54
  56. package/CanopyX.Html/Assets/canopyx-grouping.css +17 -17
  57. package/CanopyX.Html/Assets/canopyx-grouping.js +12 -9
  58. package/CanopyX.Html/Assets/canopyx-highlight.css +14 -14
  59. package/CanopyX.Html/Assets/canopyx-highlight.js +2 -2
  60. package/CanopyX.Html/Assets/canopyx-interactive.css +94 -155
  61. package/CanopyX.Html/Assets/canopyx-interactive.js +33 -14
  62. package/CanopyX.Html/Assets/canopyx-labels-de.js +5 -0
  63. package/CanopyX.Html/Assets/canopyx-labels-es.js +5 -0
  64. package/CanopyX.Html/Assets/canopyx-labels-fr.js +5 -0
  65. package/CanopyX.Html/Assets/canopyx-labels-it.js +5 -0
  66. package/CanopyX.Html/Assets/canopyx-labels-pl.js +5 -0
  67. package/CanopyX.Html/Assets/canopyx-layouts.css +17 -17
  68. package/CanopyX.Html/Assets/canopyx-layouts.js +2 -10
  69. package/CanopyX.Html/Assets/canopyx-link.css +7 -7
  70. package/CanopyX.Html/Assets/canopyx-link.js +1 -1
  71. package/CanopyX.Html/Assets/canopyx-live.css +9 -9
  72. package/CanopyX.Html/Assets/canopyx-live.js +20 -15
  73. package/CanopyX.Html/Assets/canopyx-matrix.css +74 -74
  74. package/CanopyX.Html/Assets/canopyx-matrix.js +3 -4
  75. package/CanopyX.Html/Assets/canopyx-module.mjs +33 -14
  76. package/CanopyX.Html/Assets/canopyx-pager.css +2 -2
  77. package/CanopyX.Html/Assets/canopyx-pager.js +1 -1
  78. package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
  79. package/CanopyX.Html/Assets/canopyx-record-panel.css +57 -49
  80. package/CanopyX.Html/Assets/canopyx-record-panel.js +13 -8
  81. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +101 -57
  82. package/CanopyX.Html/Assets/canopyx-reporting.css +214 -276
  83. package/CanopyX.Html/Assets/canopyx-reporting.js +101 -57
  84. package/CanopyX.Html/Assets/canopyx-timeline.css +28 -28
  85. package/CanopyX.Html/Assets/canopyx-timeline.js +11 -10
  86. package/CanopyX.Html/Assets/canopyx-tree-tools.css +47 -47
  87. package/CanopyX.Html/Assets/canopyx-tree-tools.js +3 -3
  88. package/CanopyX.Html/Assets/canopyx.css +81 -142
  89. package/CanopyX.Html/Assets/canopyx.js +33 -14
  90. package/JavaScript/calendar.d.ts +15 -0
  91. package/JavaScript/flow.d.ts +6 -0
  92. package/JavaScript/grid.d.ts +29 -4
  93. package/JavaScript/live.d.ts +2 -0
  94. package/JavaScript/locales/de.mjs +5 -0
  95. package/JavaScript/locales/es.mjs +5 -0
  96. package/JavaScript/locales/fr.mjs +5 -0
  97. package/JavaScript/locales/it.mjs +5 -0
  98. package/JavaScript/locales/pl.mjs +5 -0
  99. package/JavaScript/plugins.d.ts +4 -0
  100. package/JavaScript/protocol.d.ts +1 -1
  101. package/JavaScript/records.d.ts +18 -4
  102. package/README.md +6 -2
  103. package/package.json +5 -1
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"a27c818b731c22e3",install(context){if(installed.has(context.DataGrid.prototype))return;const{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}=context;const LIVE_KEYS=new Set(["stableOrder","flash","batchMs","pollMs","load","announce","pauseWhenHidden"]);const LIVE_MAX_ROWS=100000;function liveOptions(view,options){const read=value=>{if(value===undefined||value===true||value===false)return{};if(!value||typeof value!=="object"||Array.isArray(value)||Object.keys(value).some(key=>!LIVE_KEYS.has(key)))
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"3b3c9833ff68a72b",install(context){if(installed.has(context.DataGrid.prototype))return;const{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}=context;const LIVE_KEYS=new Set(["stableOrder","flash","batchMs","pollMs","load","announce","pauseWhenHidden"]);const LIVE_MAX_ROWS=100000;function liveOptions(view,options){const read=value=>{if(value===undefined||value===true||value===false)return{};if(!value||typeof value!=="object"||Array.isArray(value)||Object.keys(value).some(key=>!LIVE_KEYS.has(key)))
2
2
  throw new Error("CanopyX: live takes stableOrder, flash, batchMs, pollMs, load, announce and pauseWhenHidden.");return value};const merged=options.live===false?{}:{...read(view.live),...read(options.live)},flash=merged.flash;const integer=(value,min,max)=>value===undefined||Number.isInteger(value)&&value>=min&&value<=max;if(["stableOrder","announce","pauseWhenHidden"].some(key=>merged[key]!==undefined&&typeof merged[key]!=="boolean")||
3
3
  !(flash===undefined||typeof flash==="boolean"||flash&&typeof flash==="object"&&Object.keys(flash).every(key=>key==="durationMs")&&integer(flash.durationMs,100,10000))||
4
4
  !integer(merged.batchMs,0,60000)||!(merged.pollMs===undefined||merged.pollMs===0||integer(merged.pollMs,250,86400000))||
@@ -33,7 +33,7 @@ let dirty=order.dirty;const neighbour=(index,step)=>{for(let at=index+step;at>=0
33
33
  let ids=leave.size?order.ids.filter(id=>!leave.has(id)):order.ids;if(enter.length){enter.sort(compare);const merged=[];let i=0,j=0;while(i<ids.length&&j<enter.length)merged.push(compare(rows.get(ids[i]),enter[j])<=0?ids[i++]:enter[j++].id);while(i<ids.length)merged.push(ids[i++]);while(j<enter.length)merged.push(enter[j++].id);ids=merged}
34
34
  this.liveOrder=liveIndexOrder({shape:order.shape,ids,dirty:stable&&dirty});this.view.rows=this.liveRowsOf=[...rows.values()];return{result,changed}}});function liveMerged(before,change){const after={...before,cells:{...before.cells}};Object.assign(after.cells,change.cells||{});for(const name of["tone","className","fields","detail"])if(change[name]!==undefined){if(change[name]===null)delete after[name];else after[name]=change[name]}
35
35
  return after}
36
- const LIVE_REQUEST=DataGrid.prototype.requestPage;DataGrid.prototype.requestPage=function(query,signal){const order=this.liveOrder;if(order&&this.liveOrderSource!==this.source)this.liveOrder=null;if(!this.liveOrder||!this.liveInline()||gridResultShape(query)!==order.shape)return LIVE_REQUEST.call(this,query,signal);const rows=this.liveRows(),items=order.ids.slice(query.offset,query.offset+query.limit).map(id=>rows.get(id));return Promise.resolve({protocol:PROTOCOL,type:"gridPage",view:this.view.id,revision:query.revision||"inline",offset:query.offset,total:rows.size,matched:order.ids.length,items})};Object.assign(DataGrid.prototype,{liveInline(){return this.view.source.kind==="inline"&&!this.opts.source},liveProjected(){const reporting=this.view.reporting;return!!(reporting&&(reporting.grouping||this.acceptedQuery?.groupBy?.length||reporting.aggregates?.length||reporting.detail)||this.opts.detail)},liveAnchor(){const top=this.logicalTop(),index=this.rowAt(top),row=this.rowCache.get(index);return{top,index,id:row&&!row.status?row.key:null,delta:top-this.rowTop(index)}},liveSwap(snapshot,pagesFor,positionOf,changed,removed,shifted=true){const hadFocus=this.canvas.contains(document.activeElement),anchor=this.liveAnchor(),old=new Map();const focused=this.focused,focusIndex=focused?focused._ri:-1,focusId=focused&&!focused.status?focused.key:null;for(const row of this.rowCache.values())old.set(row.key,row);const length=this.pageLength;if(this.paged&&!this.cursor&&this.pageOffset>0&&this.pageOffset>=snapshot.matched)
36
+ const LIVE_REQUEST=DataGrid.prototype.requestPage;DataGrid.prototype.requestPage=function(query,signal){const order=this.liveOrder;if(order&&this.liveOrderSource!==this.source)this.liveOrder=null;if(!this.liveOrder||!this.liveInline()||gridResultShape(query)!==order.shape)return LIVE_REQUEST.call(this,query,signal);const rows=this.liveRows(),items=order.ids.slice(query.offset,query.offset+query.limit).map(id=>rows.get(id));return Promise.resolve({protocol:PROTOCOL,type:"gridPage",view:this.view.id,revision:query.revision||"inline",offset:query.offset,total:rows.size,matched:order.ids.length,items})};Object.assign(DataGrid.prototype,{liveInline(){return this.view.source.kind==="inline"&&!this.opts.source},liveProjected(){const reporting=this.view.reporting;return!!(this.view.footers?.length||reporting&&(reporting.grouping||this.acceptedQuery?.groupBy?.length||reporting.aggregates?.length||reporting.detail)||this.opts.detail)},liveAnchor(){const top=this.logicalTop(),index=this.rowAt(top),row=this.rowCache.get(index);return{top,index,id:row&&!row.status?row.key:null,delta:top-this.rowTop(index)}},liveSwap(snapshot,pagesFor,positionOf,changed,removed,shifted=true){const hadFocus=this.canvas.contains(document.activeElement),anchor=this.liveAnchor(),old=new Map();const focused=this.focused,focusIndex=focused?focused._ri:-1,focusId=focused&&!focused.status?focused.key:null;for(const row of this.rowCache.values())old.set(row.key,row);const length=this.pageLength;if(this.paged&&!this.cursor&&this.pageOffset>0&&this.pageOffset>=snapshot.matched)
37
37
  this.pageOffset=Math.max(0,Math.floor((snapshot.matched-1)/ length) * length);
38
38
  const anchorIndex=anchor.id===null?-1:positionOf(anchor.id),newFocus=focusId===null?-1:positionOf(focusId);const pages=pagesFor(anchorIndex>=0?anchorIndex:anchor.index,newFocus);if(this.pendingPages.size||this.pendingNavigation){this.queryEpoch++;this.pendingPages.clear();this.pendingNavigation=null}
39
39
  this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.snapshot={revision:snapshot.revision,total:snapshot.total,matched:snapshot.matched};const heights=this.autoRows?new Map():null;for(const[offset,items]of[...pages].sort((a,b)=>a[0]- b[0])){items.forEach((item,index)=>{const row=old.get(item.id);if(!row)return;if(heights&&this.rowHeights.has(row._ri))heights.set(offset+index,this.rowHeights.get(row._ri));row.h=item;row._ri=offset+index;row.hpx=this.rowH;this.rowCache.set(row._ri,row)});this.storePage({protocol:PROTOCOL,type:"gridPage",view:this.view.id,revision:snapshot.revision,offset,items})}
@@ -43,17 +43,17 @@ snapshot.matched?this.rowItem(Math.max(this.rowBounds().first,Math.min(focusInde
43
43
  this.syncQuerySummary();this.syncPager();this.syncGridChrome();this.liveAfterChange(changed,removed,positionOf,shifted)},liveAfterChange(changed,removed,positionOf,shifted){const gone=new Set(removed);if(this.querySelection){let touched=false;for(const id of gone)touched=this.selectionExcluded.delete(id)||touched;if(this.querySelection.matched!==this.snapshot.matched||this.querySelection.revision!==this.snapshot.revision){this.querySelection=gridFreeze({...this.querySelection,matched:this.snapshot.matched,revision:this.snapshot.revision});touched=true}
44
44
  if(touched)this.publishQuerySelection?.()}else if(gone.size&&[...this.selected].some(id=>gone.has(id)))this.setSelection([...this.selected].filter(id=>!gone.has(id)));if(this.formatStatsKey!==undefined)this.formatStatsKey=null;VIEW_MODES.refresh?.(this);const dialog=this.recordDrawer,id=dialog?.isConnected?dialog.getAttribute("data-cx-record"):null;if(id&&typeof dialog._cxPaint==="function"&&(changed.has(id)||gone.has(id)||shifted)){const index=gone.has(id)?-1:positionOf(id),row=index>=0?this.rowCache.get(index):null;const record=row?row.h:index<0||!this.liveInline()?null:this.liveRows().get(id);if(record)dialog._cxPaint(row?record:liveCopy(record),index);else if(gone.has(id)){dialog._cxPaint(dialog._cxRecord,null);this.liveNote(this.labels.gridLiveRecordRemoved)}
45
45
  else if(shifted&&!changed.has(id))dialog._cxPaint(dialog._cxRecord,index>=0?index:null)}
46
- this.liveFlash(changed)},async liveRequery(changed,removed){const anchor=this.liveAnchor(),active=document.activeElement,hadFocus=this.canvas.contains(active);const focusedId=this.focused&&!this.focused.status?this.focused.key:null,keep=this.dataLifetime;this.dataLifetime=new AbortController();this.summaryCandidate=null;try{await this.setQuery({...this.acceptedQuery,offset:this.paged?this.pageOffset:0,revision:undefined})}
47
- finally{const current=this.dataLifetime;if(current.signal.aborted||this.destroyed)keep.abort();else current.signal.addEventListener("abort",()=>keep.abort(),{once:true})}
46
+ this.liveFlash(changed)},async liveRequery(changed,removed,ownerSignal){const anchor=this.liveAnchor(),active=document.activeElement,hadFocus=this.canvas.contains(active);const focusedId=this.focused&&!this.focused.status?this.focused.key:null,keep=this.dataLifetime;this.dataLifetime=new AbortController();this.summaryCandidate=null;let queryLifetime,queryEpoch;const cancel=()=>queryLifetime?.abort();try{const query=this.setQuery({...this.acceptedQuery,offset:this.paged?this.pageOffset:0,revision:undefined});queryLifetime=this.dataLifetime;queryEpoch=this.queryEpoch;ownerSignal?.addEventListener("abort",cancel,{once:true});if(ownerSignal?.aborted)cancel();await query}
47
+ finally{ownerSignal?.removeEventListener("abort",cancel);const current=this.dataLifetime;if(this.queryEpoch!==queryEpoch||current.signal.aborted||this.destroyed)keep.abort();else current.signal.addEventListener("abort",()=>keep.abort(),{once:true})}
48
48
  this.setLogicalTop(Math.min(anchor.top,this.total));this.render();for(let wait=0;wait<8&&this.pendingPages.size&&!this.destroyed;wait++)await Promise.race([...this.pendingPages.values()].map(token=>token.promise));const focus=focusedId&&[...this.rowCache.values()].find(row=>row.key===focusedId);if(focus)this.focused=focus;if(hadFocus&&!this.canvas.contains(document.activeElement))(focus&&this.rendered.get(focus)||this.grid).focus({preventScroll:true});const dialog=this.recordDrawer,id=dialog?.isConnected?dialog.getAttribute("data-cx-record"):null,row=id&&[...this.rowCache.values()].find(item=>item.key===id);if(row&&changed.has(id))dialog._cxPaint(row.h,row._ri);else if(id&&new Set(removed).has(id)){dialog._cxPaint(dialog._cxRecord,null);this.liveNote(this.labels.gridLiveRecordRemoved)}
49
49
  if(dialog?.contains(active)&&!dialog.contains(document.activeElement))active.focus?.({preventScroll:true});this.liveAfterChange(changed,removed,()=>-1,false)}});Object.assign(DataGrid.prototype,{liveHeldOffsets(){const offsets=new Set([0]),bounds=this.rowBounds(),size=this.pageSize;if(this.focused&&this.focused._ri>=0)offsets.add(Math.floor(this.focused._ri / size) * size);
50
50
  if(this.paged)offsets.add(Math.floor(this.pageOffset / size) * size);
51
51
  for(const range of this.window?this.window.ranges||[this.window]:[])
52
52
  for(let page=Math.floor(Math.max(bounds.first,range.first)/ size) * size; page <= Math.min(bounds.last, range.last); page += size) offsets.add(page);
53
- return[...offsets].slice(0,4).sort((a,b)=>a-b)},async liveRefreshHost(force){if(this.cursor)return this.liveRefreshCursor();const offsets=this.liveHeldOffsets(),lifetime=this.dataLifetime,epoch=this.queryEpoch,accepted=this.acceptedQuery;const ask=async(offset,snapshot)=>{const query=gridQuery(this.view,{...accepted,offset,limit:this.pageSize,revision:snapshot?snapshot.revision:undefined});const page=validateGridPage(await this.requestPage(query,lifetime.signal),this.view,query,snapshot);if(this.destroyed||epoch!==this.queryEpoch||this.acceptedQuery!==accepted)throw new DOMException("The refresh was superseded.","AbortError");return page};const first=await ask(0,null);if(!force&&(first.revision===this.snapshot.revision||first.revision===this.livePending?.snapshot?.revision))return null;const snapshot={revision:first.revision,total:first.total,matched:first.matched};if(this.liveProjected()){this.livePending=null;this.liveMoved=false;await this.liveRequery(new Map(),[]);return{changed:new Map(),removed:[],orderChanged:false,revision:this.snapshot.revision}}
53
+ return[...offsets].slice(0,4).sort((a,b)=>a-b)},async liveRefreshHost(force,signal=this.dataLifetime.signal){if(this.cursor)return this.liveRefreshCursor(signal);const offsets=this.liveHeldOffsets(),lifetime=this.dataLifetime,epoch=this.queryEpoch,accepted=this.acceptedQuery;const ask=async(offset,snapshot)=>{const query=gridQuery(this.view,{...accepted,offset,limit:this.pageSize,revision:snapshot?snapshot.revision:undefined});const page=validateGridPage(await this.requestPage(query,signal),this.view,query,snapshot);if(signal.aborted||this.destroyed||epoch!==this.queryEpoch||this.acceptedQuery!==accepted)throw new DOMException("The refresh was superseded.","AbortError");return page};const first=await ask(0,null);if(!force&&(first.revision===this.snapshot.revision||first.revision===this.livePending?.snapshot?.revision))return null;const snapshot={revision:first.revision,total:first.total,matched:first.matched};if(this.liveProjected()){this.livePending=null;this.liveMoved=false;await this.liveRequery(new Map(),[],signal);return{changed:new Map(),removed:[],orderChanged:false,revision:this.snapshot.revision}}
54
54
  const pages=new Map([[0,first.items]]);for(const offset of offsets)if(offset&&offset<snapshot.matched)pages.set(offset,(await ask(offset,snapshot)).items);const position=new Map(),fresh=new Map();for(const[offset,items]of pages)items.forEach((item,index)=>{position.set(item.id,offset+index);fresh.set(item.id,item)});const changed=new Map(),held=new Map();for(const row of this.rowCache.values())if(!row.status)held.set(row.key,row);for(const[id,item]of fresh){const row=held.get(id),columns=row?liveChangedColumns(row.h,item):"*";if(columns==="*"||columns.size)changed.set(id,columns)}
55
55
  const seen=[...this.rendered.keys()].filter(row=>!row.status&&row.key).sort((a,b)=>a._ri-b._ri).map(row=>row.key);const before=seen.filter(id=>position.has(id)),after=[...before].sort((a,b)=>position.get(a)- position.get(b));const moved=before.some((id,index)=>id!==after[index]);if(moved&&this.liveOpts.stableOrder&&!force){this.liveSetHeld(fresh,false);this.livePending={snapshot,pages};this.liveSyncPrompt();return{changed,removed:[],orderChanged:true,revision:snapshot.revision}}
56
- this.livePending=null;this.liveMoved=false;this.liveSwap(snapshot,()=>pages,id=>position.get(id)??-1,changed,[]);this.liveSyncPrompt();return{changed,removed:[],orderChanged:false,revision:snapshot.revision}},async liveRefreshCursor(){const query=gridQuery(this.view,{...this.acceptedQuery,cursor:undefined,revision:undefined,limit:this.pageLength});const page=validateGridCursorPage(await this.requestPage(query,this.dataLifetime.signal),this.view,query,null);if(this.destroyed||page.revision===this.snapshot.revision||page.revision===this.livePending?.revision)return null;this.livePending={cursor:true,revision:page.revision};this.liveSyncPrompt();return{changed:new Map(),removed:[],orderChanged:false,newData:true,revision:page.revision}},liveSetHeld(changes,merge){const changed=new Map(),loaded=new Set(),pages=new Set(),query=this.acceptedQuery,used=new Set(query.sort.map(sort=>sort.column));const walk=group=>{if(!group)return;for(const filter of group.filters)used.add(filter.column);group.groups.forEach(walk)};for(const filter of query.filters)used.add(filter.column);walk(query.filterGroup);const searched=!!query.search;let moved=false;for(const row of this.rowCache.values()){const change=!row.status&&changes.get(row.key);if(!change)continue;loaded.add(row.key);const after=merge?liveMerged(row.h,change):liveCopy(change),columns=liveChangedColumns(row.h,after);if(!columns.size&&liveSameRow(row.h,after))continue;row.h=after;changed.set(row.key,columns);pages.add(Math.floor(row._ri / this.pageSize) * this.pageSize);
56
+ this.livePending=null;this.liveMoved=false;this.liveSwap(snapshot,()=>pages,id=>position.get(id)??-1,changed,[]);this.liveSyncPrompt();return{changed,removed:[],orderChanged:false,revision:snapshot.revision}},async liveRefreshCursor(signal=this.dataLifetime.signal){const query=gridQuery(this.view,{...this.acceptedQuery,cursor:undefined,revision:undefined,limit:this.pageLength});const page=validateGridCursorPage(await this.requestPage(query,signal),this.view,query,null);if(signal.aborted)throw new DOMException("The refresh was superseded.","AbortError");if(this.destroyed||page.revision===this.snapshot.revision||page.revision===this.livePending?.revision)return null;this.livePending={cursor:true,revision:page.revision};this.liveSyncPrompt();return{changed:new Map(),removed:[],orderChanged:false,newData:true,revision:page.revision}},liveSetHeld(changes,merge){const changed=new Map(),loaded=new Set(),pages=new Set(),query=this.acceptedQuery,used=new Set(query.sort.map(sort=>sort.column));const walk=group=>{if(!group)return;for(const filter of group.filters)used.add(filter.column);group.groups.forEach(walk)};for(const filter of query.filters)used.add(filter.column);walk(query.filterGroup);const searched=!!query.search;let moved=false;for(const row of this.rowCache.values()){const change=!row.status&&changes.get(row.key);if(!change)continue;loaded.add(row.key);const after=merge?liveMerged(row.h,change):liveCopy(change),columns=liveChangedColumns(row.h,after);if(!columns.size&&liveSameRow(row.h,after))continue;row.h=after;changed.set(row.key,columns);pages.add(Math.floor(row._ri / this.pageSize) * this.pageSize);
57
57
  if(searched||[...columns].some(id=>used.has(id)))moved=true}
58
58
  if(merge&&this.livePending?.pages){for(const items of this.livePending.pages.values())for(let index=0;index<items.length;index++){const item=items[index],change=loaded.has(item.id)&&changes.get(item.id);if(!change)continue;const after=liveMerged(item,change),columns=liveChangedColumns(item,after);items[index]=after;if(!liveSameRow(item,after)&&(searched||[...columns].some(id=>used.has(id))))moved=true}
59
59
  if(moved)this.livePending={refresh:true}}
@@ -68,22 +68,27 @@ this.lifetime.signal.addEventListener("abort",()=>{bar.remove();this.host.classL
68
68
  const wasHidden=this.liveBar.hidden||this.liveBarCursor!==cursor;setText(this.liveBarText,cursor?this.labels.gridLiveNewData:this.labels.gridLiveOrderChanged);setText(this.liveBarButton,cursor?this.labels.gridLiveRefresh:this.labels.gridLiveResort);this.liveBarButton.title=cursor?"":this.labels.gridLiveOrderHint;this.liveBarCursor=cursor;if(this.liveBar.classList.contains("cx-live-float"))this.liveBar.style.top=this.grid.offsetTop+this.head.offsetHeight+6+"px";this.liveBar.hidden=false;if(wasHidden)this.liveNote(cursor?this.labels.gridLiveNewData:this.labels.gridLiveOrderChanged+". "+this.labels.gridLiveOrderHint)},liveFlash(changed){const duration=this.liveOpts?.flashMs;if(!duration||!changed.size)return;const now=performance.now(),flashes=this.liveFlashes||=new Map();for(const[id,columns]of changed){const existing=flashes.get(id),merged=columns==="*"||existing?.columns==="*"?"*":new Set([...(existing?.columns||[]),...columns]);if(merged!=="*"&&!merged.size)continue;flashes.set(id,{columns:merged,start:now,until:now+duration})}
69
69
  clearTimeout(this.liveFlashTimer);this.liveFlashTimer=setTimeout(()=>this.liveFlashExpire(),duration+20);this.version++;this.scheduleRender()},liveFlashExpire(){if(this.destroyed||!this.liveFlashes)return;const now=performance.now();for(const[id,flash]of this.liveFlashes)if(flash.until<=now)this.liveFlashes.delete(id);if(this.liveFlashes.size)this.liveFlashTimer=setTimeout(()=>this.liveFlashExpire(),Math.max(20,Math.min(...[...this.liveFlashes.values()].map(flash=>flash.until))- now+20));this.version++;this.scheduleRender()},liveAnnounce(result){if(!this.liveOpts?.announce||!result.added.length&&!result.removed.length)return;const counts=this.liveCounts||={added:0,updated:0,removed:0};counts.added +=result.added.length;counts.updated +=result.updated.length;counts.removed +=result.removed.length;if(this.liveAnnounceTimer)return;if(!this.liveSpoke||performance.now()- this.liveSpoke>=LIVE_ANNOUNCE_MS){this.liveNote(this.liveCountText());this.liveCoolDown()}
70
70
  else this.liveAnnounceTimer=setTimeout(()=>{this.liveAnnounceTimer=0;this.liveSay(this.liveCountText());this.liveCoolDown()},LIVE_ANNOUNCE_MS -(performance.now()- this.liveSpoke))},liveCountText(){const numbers=new Intl.NumberFormat(this.lang),counts=this.liveCounts;this.liveCounts=null;return counts?fill(this.labels.gridLiveChanged,{added:numbers.format(counts.added),updated:numbers.format(counts.updated),removed:numbers.format(counts.removed)}):""},liveCoolDown(){this.liveSpoke=performance.now();this.liveAnnounceTimer=setTimeout(()=>{this.liveAnnounceTimer=0;if(this.liveCounts&&!this.destroyed){this.liveSay(this.liveCountText());this.liveCoolDown()}},LIVE_ANNOUNCE_MS)}});const LIVE_FILL=DataGrid.prototype.fillRow;DataGrid.prototype.fillRow=function(element,row){LIVE_FILL.call(this,element,row);const flash=this.liveFlashes?.size&&!row.status&&row.key?this.liveFlashes.get(row.key):null,mark=flash?row.key+"@"+flash.start:null;if(element._cxFlash&&element._cxFlashMark===mark&&element._cxFlashLayout===element._layout)return;if(element._cxFlash){for(const cell of element._cxFlash){cell.classList.remove("cx-live-flash");cell.style.removeProperty("animation-delay")}element._cxFlash=null;element._cxFlashMark=null}
71
- if(!flash||!element._cells)return;const now=performance.now();if(flash.until<=now)return;const marked=[];element._cells.forEach((slot,index)=>{const column=this.cols[index];if(!slot||!column||flash.columns!=="*"&&!flash.columns.has(column.id))return;slot.cell.classList.add("cx-live-flash");slot.cell.style.animationDelay=Math.round(flash.start-now)+ "ms";marked.push(slot.cell)});if(marked.length){element._cxFlash=marked;element._cxFlashMark=mark;element._cxFlashLayout=element._layout}};Object.assign(DataGrid.prototype,{startLive(){if(this.view.rowIdentity==="ordinal")throw new Error("CanopyX: ordinal row identity is snapshot-local; keyed live updates require stable row keys.");if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");if(this.liveOpts)return;this.liveOpts=liveOptions(this.view,this.opts);this.liveQueue=new Map();this.liveWaiters=[];this.liveScheduled=new Set();if(this.liveOpts.flashMs)this.host.style.setProperty("--cx-live-flash-ms",this.liveOpts.flashMs+"ms");this.host.addEventListener("canopyx:query",()=>{if(this.liveOrder&&this.liveOrder.shape!==gridResultShape(this.acceptedQuery))this.liveOrder=null;this.livePending=null;this.liveMoved=false;this.liveSyncPrompt()},{signal:this.lifetime.signal});this.lifetime.signal.addEventListener("abort",()=>{clearTimeout(this.liveTimer);clearTimeout(this.liveFlashTimer);clearTimeout(this.liveAnnounceTimer);this.host.style.removeProperty("--cx-live-flash-ms");for(const waiter of this.liveWaiters.splice(0))waiter.reject(new DOMException("Grid was destroyed.","AbortError"))},{once:true});if(this.liveOpts.pollMs)this.livePoll({intervalMs:this.liveOpts.pollMs})},liveStatus(){const queued=new Set(this.liveQueue?.keys());for(const{change}of this.liveScheduled||[])if(change){for(const row of[...change.add,...change.update])queued.add(row.id);change.remove.forEach(id=>queued.add(id))}
71
+ if(!flash||!element._cells)return;const now=performance.now();if(flash.until<=now)return;const marked=[];element._cells.forEach((slot,index)=>{const column=this.cols[index];if(!slot||!column||flash.columns!=="*"&&!flash.columns.has(column.id))return;slot.cell.classList.add("cx-live-flash");slot.cell.style.animationDelay=Math.round(flash.start-now)+ "ms";marked.push(slot.cell)});if(marked.length){element._cxFlash=marked;element._cxFlashMark=mark;element._cxFlashLayout=element._layout}};Object.assign(DataGrid.prototype,{startLive(){if(this.view.rowIdentity==="ordinal")throw new Error("CanopyX: ordinal row identity is snapshot-local; keyed live updates require stable row keys.");if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");if(this.liveOpts)return;this.liveOpts=liveOptions(this.view,this.opts);this.liveQueue=new Map();this.liveWaiters=[];this.liveScheduled=new Set();this.liveProjection=null;if(this.liveOpts.flashMs)this.host.style.setProperty("--cx-live-flash-ms",this.liveOpts.flashMs+"ms");this.host.addEventListener("canopyx:query",()=>{if(this.liveOrder&&this.liveOrder.shape!==gridResultShape(this.acceptedQuery))this.liveOrder=null;this.livePending=null;this.liveMoved=false;this.liveProjection=null;this.liveSyncPrompt()},{signal:this.lifetime.signal});this.lifetime.signal.addEventListener("abort",()=>{clearTimeout(this.liveTimer);clearTimeout(this.liveFlashTimer);clearTimeout(this.liveAnnounceTimer);this.liveProjection=null;this.host.style.removeProperty("--cx-live-flash-ms");for(const waiter of this.liveWaiters.splice(0))waiter.reject(new DOMException("Grid was destroyed.","AbortError"))},{once:true});if(this.liveOpts.pollMs)this.livePoll({intervalMs:this.liveOpts.pollMs})},liveStatus(){const queued=new Set(this.liveQueue?.keys());for(const id of this.liveProjection?.ids||[])queued.add(id);for(const{change}of this.liveScheduled||[])if(change){for(const row of[...change.add,...change.update])queued.add(row.id);change.remove.forEach(id=>queued.add(id))}
72
72
  return gridFreeze({orderChanged:!!(this.liveOrder?.dirty||this.livePending?.pages||this.livePending?.refresh||this.liveMoved),newData:!!this.livePending?.cursor,pending:queued.size,polling:!!this.livePoller?.active,revision:this.snapshot?.revision??null})},liveRun(task){return this.liveChain=(this.liveChain||Promise.resolve()).catch(()=>{}).then(async()=>{this.startLive();await this.liveSettle();return task()})},applyTransaction(input){return this.liveQueueChange(liveTransaction(this,input),"api")},addRows(rows){return this.applyTransaction({add:rows})},updateRows(rows){return this.applyTransaction({update:rows})},removeRows(ids){return this.applyTransaction({remove:ids})},async setRows(rows){if(!this.liveInline())throw new Error("CanopyX: setRows replaces inline rows; a hosted grid's rows change at its source, then refreshRows().");validateGridRows(rows,this.view.columns);const owned=liveCopy(rows);return this.liveQueueChange(null,"api",owned)},liveQueueChange(change,source,replacement){if(this.destroyed)return Promise.reject(new DOMException("Grid was destroyed.","AbortError"));try{this.startLive()}catch(error){return Promise.reject(error)}
73
73
  if(this.view.source.kind==="inline"&&this.opts.source)
74
74
  return Promise.reject(new Error("CanopyX: this grid's rows belong to its own source; change them through it (an enhanced grid's setData, addRows and removeRows)."));if(!this.liveInline()&&(change.add.length||change.remove.length))
75
75
  return Promise.reject(new Error("CanopyX: rows of a hosted grid are added and removed at its source; call refreshRows() after."));const scheduled={change};this.liveScheduled.add(scheduled);let waiter;const promise=new Promise((resolve,reject)=>{waiter={resolve,reject}});this.liveRun(async()=>{if(replacement){await this.liveFlush().catch(()=>{});change=liveTransaction(this,liveDiff(replacement,this.liveRows()))}
76
- this.liveScheduled.delete(scheduled);this.liveEnqueueChange(change,source,waiter)}).catch(error=>{this.liveScheduled.delete(scheduled);waiter.reject(error)});return promise},liveEnqueueChange(change,source,waiter){liveEnqueue(this.liveQueue,change);this.liveWaiters.push(waiter);this.liveSource=this.liveSource&&this.liveSource!==source?"api":source;if(!this.liveOpts.batchMs)this.flushTransactions().catch(()=>{});else if(!this.liveTimer)this.liveTimer=setTimeout(()=>this.flushTransactions().catch(()=>{}),this.liveOpts.batchMs)},flushTransactions(){clearTimeout(this.liveTimer);this.liveTimer=0;return this.liveRun(()=>this.liveFlush())},async liveFlush(){clearTimeout(this.liveTimer);this.liveTimer=0;const queue=this.liveQueue,waiters=this.liveWaiters.splice(0),source=this.liveSource||"api";this.liveQueue=new Map();this.liveSource=null;try{const result=queue.size?await this.liveApply(queue,source):liveResult();waiters.forEach(waiter=>waiter.resolve(result));return result}catch(error){waiters.forEach(waiter=>waiter.reject(error));throw error}},async liveSettle(){if(!this.acceptedQuery&&!this.pendingQuery)await this.ready.catch(()=>{});while(!this.destroyed&&this.pendingQuery)await new Promise(resolve=>setTimeout(resolve,16));if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");if(!this.acceptedQuery)throw new Error("CanopyX: live changes need an accepted query.");if(this.view.rowData&&this.liveInline()){await this.source.decoded;delete this.view.rowData;this.source=inlineGridSource(this.view)}},liveInlinePages(order){const rows=this.liveRows(),size=this.pageSize;return(anchor,focus)=>{const span=Math.ceil((this.grid.clientHeight||600)/ this.rowH) + 30, offsets = new Set();
76
+ this.liveScheduled.delete(scheduled);this.liveEnqueueChange(change,source,waiter)}).catch(error=>{this.liveScheduled.delete(scheduled);waiter.reject(error)});return promise},liveEnqueueChange(change,source,waiter){liveEnqueue(this.liveQueue,change);this.liveWaiters.push(waiter);this.liveSource=this.liveSource&&this.liveSource!==source?"api":source;if(!this.liveOpts.batchMs)this.flushTransactions().catch(()=>{});else if(!this.liveTimer)this.liveTimer=setTimeout(()=>this.flushTransactions().catch(()=>{}),this.liveOpts.batchMs)},flushTransactions(){clearTimeout(this.liveTimer);this.liveTimer=0;return this.liveRun(()=>this.liveFlush())},async liveFlush(){clearTimeout(this.liveTimer);this.liveTimer=0;const queue=this.liveQueue,waiters=this.liveWaiters.splice(0),source=this.liveSource||this.liveProjection?.source||"api";this.liveQueue=new Map();this.liveSource=null;try{const result=queue.size||this.liveProjection?await this.liveApply(queue,source):liveResult();waiters.forEach(waiter=>waiter.resolve(result));return result}catch(error){waiters.forEach(waiter=>waiter.reject(error));throw error}},async liveSettle(){if(!this.acceptedQuery&&!this.pendingQuery)await this.ready.catch(()=>{});while(!this.destroyed&&this.pendingQuery)await new Promise(resolve=>setTimeout(resolve,16));if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");if(!this.acceptedQuery)throw new Error("CanopyX: live changes need an accepted query.");if(this.view.rowData&&this.liveInline()){await this.source.decoded;delete this.view.rowData;this.source=inlineGridSource(this.view)}},liveInlinePages(order){const rows=this.liveRows(),size=this.pageSize;return(anchor,focus)=>{const span=Math.ceil((this.grid.clientHeight||600)/ this.rowH) + 30, offsets = new Set();
77
77
  const[first,last]=this.paged?[this.pageOffset,this.pageOffset+this.pageLength-1]:[Math.max(0,anchor-span),anchor+2*span];for(let page=Math.floor(first / size) * size; page <= Math.min(last, order.ids.length - 1); page += size) offsets.add(page);
78
78
  if(focus>=0)offsets.add(Math.floor(focus / size) * size);
79
- return new Map([...offsets].map(offset=>[offset,order.ids.slice(offset,offset+size).map(id=>liveCopy(rows.get(id)))]))}},liveSwapInline(changed,removed,shifted){const order=this.liveOrder;this.liveSwap({revision:this.snapshot.revision,total:this.liveRows().size,matched:order.ids.length},this.liveInlinePages(order),id=>order.at.get(id)??-1,changed,removed,shifted)},async liveApply(queue,source){let outcome;if(this.liveInline()){const projected=this.liveProjected(),{result,changed}=this.liveApplyRows(queue,!projected);if(changed.size||result.removed.length){if(!this.opts.source)this.source=inlineGridSource(this.view);this.liveOrderSource=this.source;if(projected)await this.liveRequery(changed,result.removed);else this.liveSwapInline(changed,result.removed,result.added.length>0||result.removed.length>0||!this.liveOpts.stableOrder)}
79
+ return new Map([...offsets].map(offset=>[offset,order.ids.slice(offset,offset+size).map(id=>liveCopy(rows.get(id)))]))}},liveSwapInline(changed,removed,shifted){const order=this.liveOrder;this.liveSwap({revision:this.snapshot.revision,total:this.liveRows().size,matched:order.ids.length},this.liveInlinePages(order),id=>order.at.get(id)??-1,changed,removed,shifted)},async liveApply(queue,source,ownerSignal){let outcome;if(this.liveInline()){const projected=this.liveProjected(),before=this.view.rows;let{result,changed}=this.liveApplyRows(queue,!projected);if(changed.size||result.removed.length){if(!this.opts.source)this.source=inlineGridSource(this.view);this.liveOrderSource=this.source;if(projected){this.liveProjection||={rows:new Map(before.map(row=>[row.id,row])),source};if(this.liveProjection.source!==source)this.liveProjection.source="api"}
80
+ else this.liveSwapInline(changed,result.removed,result.added.length>0||result.removed.length>0||!this.liveOpts.stableOrder)}
81
+ if(projected&&this.liveProjection){const pending=this.liveProjection,delta=liveDiff(this.view.rows,pending.rows);source=pending.source;changed=new Map(delta.add.map(row=>[row.id,"*"]));result={...result,added:delta.add.filter(row=>!pending.rows.has(row.id)).map(row=>row.id),updated:delta.add.filter(row=>pending.rows.has(row.id)).map(row=>row.id),removed:delta.remove};pending.ids=new Set([...result.added,...result.updated,...result.removed]);await this.liveRequery(changed,result.removed,ownerSignal);if(this.liveProjection===pending)this.liveProjection=null}
80
82
  outcome={...result,orderChanged:!!this.liveOrder?.dirty}}else{const updates=new Map([...queue.values()].map(change=>[change.id,change.row]));const{changed,moved,loaded}=this.liveSetHeld(updates,true);if(moved)this.liveMoved=true;outcome={added:[],updated:[...changed.keys()],removed:[],missing:[...updates.keys()].filter(id=>!loaded.has(id)),orderChanged:this.liveMoved}}
81
- const recordNote=!!this.liveNotes?.length;this.liveSyncPrompt();if(!recordNote)this.liveAnnounce(outcome);this.liveSpeak();return this.liveReport(outcome,source)},liveReport(outcome,source){const detail=gridFreeze({added:outcome.added||[],updated:outcome.updated||[],removed:outcome.removed||[],missing:outcome.missing||[],orderChanged:!!outcome.orderChanged,newData:!!outcome.newData,revision:outcome.revision??this.snapshot?.revision??null,source});if(detail.added.length||detail.updated.length||detail.removed.length||detail.newData||detail.orderChanged||outcome.refreshed)this.emit("rowsChanged",detail);return detail},refreshRows(){return this.liveRefresh("refresh")},liveRefresh(source){return this.liveRun(async()=>{if(this.liveInline()){if(!this.liveOpts.load)return liveResult();await this.liveFlush().catch(()=>{});let answer=await this.runGridHook(signal=>this.liveOpts.load({signal,query:this.acceptedQuery,rows:this.view.rows.length}),this.dataLifetime.signal);if(answer==null)return liveResult();if(Array.isArray(answer)){validateGridRows(answer,this.view.columns);answer=liveCopy(answer)}
82
- const change=liveTransaction(this,Array.isArray(answer)?liveDiff(answer,this.liveRows()):answer),queue=new Map();liveEnqueue(queue,change);return this.liveApply(queue,source)}
83
- if(this.view.source.kind==="inline")return liveResult();const outcome=await this.liveRefreshHost(false);if(!outcome)return liveResult();const changed=[...outcome.changed].filter(([,columns])=>columns!=="*").map(([id])=>id);this.liveSpeak();return this.liveReport({updated:changed,orderChanged:outcome.orderChanged,newData:outcome.newData,revision:outcome.revision,refreshed:true},source)})},resort(){return this.liveRun(async()=>{const pending=this.livePending,revision=this.snapshot?.revision;if(pending?.cursor){this.livePending=null;this.liveSyncPrompt();await this.setQuery({...this.acceptedQuery,cursor:undefined,revision:undefined},{pageLength:this.pageLength});return}
83
+ const recordNote=!!this.liveNotes?.length;this.liveSyncPrompt();if(!recordNote)this.liveAnnounce(outcome);this.liveSpeak();return this.liveReport(outcome,source)},liveReport(outcome,source){const detail=gridFreeze({added:outcome.added||[],updated:outcome.updated||[],removed:outcome.removed||[],missing:outcome.missing||[],orderChanged:!!outcome.orderChanged,newData:!!outcome.newData,revision:outcome.revision??this.snapshot?.revision??null,source});if(detail.added.length||detail.updated.length||detail.removed.length||detail.newData||detail.orderChanged||outcome.refreshed)this.emit("rowsChanged",detail);return detail},refreshRows(){return this.liveRefresh("refresh")},liveRefresh(source,pollSignal){return this.liveRun(async()=>{if(this.liveInline()){if(!this.liveOpts.load)return this.liveProjection?this.liveFlush():liveResult();await this.liveFlush().catch(()=>{})}
84
+ const dataSignal=this.dataLifetime.signal,controller=new AbortController();const signals=[dataSignal,pollSignal].filter(Boolean),abort=()=>controller.abort();for(const signal of signals){signal.addEventListener("abort",abort,{once:true});if(signal.aborted)abort()}
85
+ try{if(this.liveInline()){let answer=await this.runGridHook(signal=>this.liveOpts.load({signal,query:this.acceptedQuery,rows:this.view.rows.length}),controller.signal);if(controller.signal.aborted)throw new DOMException("Grid poll cancelled.","AbortError");if(answer==null)return liveResult();if(Array.isArray(answer)){validateGridRows(answer,this.view.columns);answer=liveCopy(answer)}
86
+ const change=liveTransaction(this,Array.isArray(answer)?liveDiff(answer,this.liveRows()):answer),queue=new Map();liveEnqueue(queue,change);return await this.liveApply(queue,source,controller.signal)}
87
+ if(this.view.source.kind==="inline")return liveResult();const outcome=await this.liveRefreshHost(false,controller.signal);if(!outcome)return liveResult();const changed=[...outcome.changed].filter(([,columns])=>columns!=="*").map(([id])=>id);this.liveSpeak();return this.liveReport({updated:changed,orderChanged:outcome.orderChanged,newData:outcome.newData,revision:outcome.revision,refreshed:true},source)}catch(error){if(source==="poll"&&error?.name==="AbortError"&&!controller.signal.aborted)throw new Error(error.message,{cause:error});throw error}finally{for(const signal of signals)signal.removeEventListener("abort",abort)}})},resort(){return this.liveRun(async()=>{const pending=this.livePending,revision=this.snapshot?.revision;if(pending?.cursor){this.livePending=null;this.liveSyncPrompt();await this.setQuery({...this.acceptedQuery,cursor:undefined,revision:undefined},{pageLength:this.pageLength});return}
84
88
  if(this.liveInline()){this.liveOrder=null;this.liveMoved=false;if(this.liveProjected())await this.liveRequery(new Map(),[]);else{this.liveOrderOf();this.liveSwapInline(new Map(),[],true)}}else if(pending?.pages){this.livePending=null;this.liveMoved=false;const position=new Map();for(const[offset,items]of pending.pages)items.forEach((item,index)=>position.set(item.id,offset+index));this.liveSwap(pending.snapshot,()=>pending.pages,id=>position.get(id)??-1,new Map(),[])}else{this.liveMoved=false;await this.liveRefreshHost(true)}
85
89
  this.liveSyncPrompt();if(!this.liveInline()&&this.snapshot?.revision!==revision)this.liveReport({refreshed:true,revision:this.snapshot.revision},"refresh");this.liveNote(this.labels.gridLiveSorted);this.liveSpeak()})},async poll(options={}){return this.livePoll(options)},livePoll(options){this.startLive();if(!options||typeof options!=="object"||Array.isArray(options))throw new Error("CanopyX: poll takes options.");const interval=options.intervalMs??this.liveOpts.pollMs,hidden=options.pauseWhenHidden??this.liveOpts.pauseWhenHidden;if(!Number.isInteger(interval)||interval<250||interval>86400000||typeof hidden!=="boolean"||options.load!==undefined&&typeof options.load!=="function")
86
- throw new Error("CanopyX: poll needs intervalMs from 250 to 86400000.");if(options.load)this.liveOpts.load=options.load;if(this.liveInline()&&!this.liveOpts.load)throw new Error("CanopyX: an inline grid polls a load function (live.load or poll({ load })).");this.livePoller?.stop();const lifetime=new AbortController();let timer=0,running=null,paused=false,due=false;const schedule=()=>{clearTimeout(timer);timer=paused||lifetime.signal.aborted?0:setTimeout(tick,interval)};const tick=now=>{clearTimeout(timer);timer=0;if(lifetime.signal.aborted||paused&&!now)return Promise.resolve();if(hidden&&document.hidden&&!now){due=true;return Promise.resolve()}
87
- if(running)return running;return running=this.liveRefresh("poll").then(()=>undefined,error=>{if(error?.name!=="AbortError")this.emit("error",{error})})
88
- .finally(()=>{running=null;schedule()})};const stop=()=>{lifetime.abort();clearTimeout(timer);if(this.livePoller===poller)this.livePoller=null};document.addEventListener("visibilitychange",()=>{if(!document.hidden&&due&&!paused){due=false;tick()}},{signal:lifetime.signal});this.lifetime.signal.addEventListener("abort",stop,{once:true,signal:lifetime.signal});const poller=Object.freeze({pause(){paused=true;clearTimeout(timer);timer=0},resume(){if(!paused||lifetime.signal.aborted)return;paused=false;due=false;tick()},stop,refresh:()=>tick(true),get paused(){return paused},get active(){return!lifetime.signal.aborted&&!paused}});this.livePoller=poller;if(options.immediate)tick();else schedule();return poller}});function liveResult(){return gridFreeze({added:[],updated:[],removed:[],missing:[],orderChanged:false,newData:false,revision:null,source:"api"})}
90
+ throw new Error("CanopyX: poll needs intervalMs from 250 to 86400000.");if(options.onRefresh!==undefined&&typeof options.onRefresh!=="function")throw new Error("CanopyX: poll onRefresh must be a function.");if(options.load)this.liveOpts.load=options.load;if(this.liveInline()&&!this.liveOpts.load)throw new Error("CanopyX: an inline grid polls a load function (live.load or poll({ load })).");this.livePoller?.stop();const lifetime=new AbortController();let timer=0,running=null,cycle=null,paused=false,due=false;const schedule=()=>{clearTimeout(timer);timer=paused||lifetime.signal.aborted||hidden&&document.hidden?0:setTimeout(tick,interval)};const tick=now=>{clearTimeout(timer);timer=0;if(lifetime.signal.aborted||paused&&!now)return Promise.resolve();if(hidden&&document.hidden&&!now){due=true;return Promise.resolve()}
91
+ if(running)return running;due=false;cycle=new AbortController();return running=this.liveRefresh("poll",cycle.signal).then(result=>{if(!lifetime.signal.aborted&&!cycle.signal.aborted&&options.onRefresh){try{options.onRefresh(result)}catch(error){this.emit("error",{error})}}},error=>{if(error?.name!=="AbortError")this.emit("error",{error})})
92
+ .finally(()=>{running=null;cycle=null;if(due&&!paused&&!lifetime.signal.aborted&&!(hidden&&document.hidden))tick();else schedule()})};const stop=()=>{lifetime.abort();cycle?.abort();clearTimeout(timer);if(this.livePoller===poller)this.livePoller=null};document.addEventListener("visibilitychange",()=>{if(!hidden)return;due=true;if(document.hidden){clearTimeout(timer);cycle?.abort()}
93
+ else if(!paused)tick()},{signal:lifetime.signal});this.lifetime.signal.addEventListener("abort",stop,{once:true,signal:lifetime.signal});const poller=Object.freeze({pause(){paused=true;cycle?.abort();clearTimeout(timer);timer=0},resume(){if(!paused||lifetime.signal.aborted)return;paused=false;due=true;tick()},stop,refresh:()=>tick(true),get paused(){return paused},get active(){return!lifetime.signal.aborted&&!paused}});this.livePoller=poller;if(options.immediate)tick();else schedule();return poller}});function liveResult(){return gridFreeze({added:[],updated:[],removed:[],missing:[],orderChanged:false,newData:false,revision:null,source:"api"})}
89
94
  installed.add(context.DataGrid.prototype)}};(global.CanopyXParts||=[]).push(["live",part])})(typeof window!=="undefined"?window:globalThis);
@@ -1,45 +1,45 @@
1
1
  /* The matrix view: a sticky header with column labels written upwards,sticky row headers and totals,windowed cells. */
2
2
  .cx-matrix-host{display:block;}
3
3
  .cx-matrix [hidden]{display:none !important;}
4
- .cx-matrix{display:flex;flex-direction:column;gap:var(--cx-size-8px);box-sizing:border-box;max-height:100%;font:var(--cx-font-size)/1.35 var(--cx-font);color:var(--cx-text);
5
- --mx-line:color-mix(in srgb,var(--cx-line) 70%,var(--cx-surface));--mx-none:color-mix(in srgb,var(--cx-muted) 42%,var(--cx-surface));
6
- --mx-raised:color-mix(in srgb,var(--cx-shadow-ink) 18%,transparent);}
4
+ .cx-matrix{display:flex;flex-direction:column;gap:var(--cx-size-8px);box-sizing:border-box;max-height:100%;font:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem))/1.35 var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));
5
+ --mx-line:color-mix(in srgb,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)) 70%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));--mx-none:color-mix(in srgb,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)) 42%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));
6
+ --mx-raised:color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 18%,transparent);}
7
7
  .cx-mx-bar{position:relative;display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-8px);}
8
- .cx-mx-input{box-sizing:border-box;height:var(--cx-size-32px);padding:0 var(--cx-size-10px);font:inherit;color:var(--cx-text);background:var(--cx-surface);
9
- border:var(--cx-size-1px) solid var(--cx-control-border);border-radius:var(--cx-radius-sm);color-scheme:inherit;}
8
+ .cx-mx-input{box-sizing:border-box;height:var(--cx-size-32px);padding:0 var(--cx-size-10px);font:inherit;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));
9
+ border:var(--cx-size-1px) solid var(--hfx-color-border-control,light-dark(#8a8f98,#6e737c));border-radius:var(--hfx-radius-sm,4px);color-scheme:inherit;}
10
10
  .cx-mx-search{flex:1 1 var(--cx-size-180px);max-width:var(--cx-size-320px);}
11
- .cx-mx-button{box-sizing:border-box;min-height:var(--cx-size-32px);padding:0 var(--cx-size-12px);font:inherit;color:var(--cx-text);background:var(--cx-surface);
12
- border:var(--cx-size-1px) solid var(--cx-control-border);border-radius:var(--cx-radius-sm);cursor:pointer;}
13
- .cx-mx-button:hover{background:var(--cx-hover-bg);}
14
- .cx-mx-button.cx-mx-active{border-color:var(--cx-accent);color:var(--cx-accent-text);}
11
+ .cx-mx-button{box-sizing:border-box;min-height:var(--cx-size-32px);padding:0 var(--cx-size-12px);font:inherit;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));
12
+ border:var(--cx-size-1px) solid var(--hfx-color-border-control,light-dark(#8a8f98,#6e737c));border-radius:var(--hfx-radius-sm,4px);cursor:pointer;}
13
+ .cx-mx-button:hover{background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));}
14
+ .cx-mx-button.cx-mx-active{border-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));}
15
15
  .cx-mx-switch{display:inline-flex;align-items:center;gap:var(--cx-size-6px);min-height:var(--cx-size-24px);cursor:pointer;}
16
- .cx-mx-check{width:var(--cx-size-16px);height:var(--cx-size-16px);margin:0;accent-color:var(--cx-accent);}
17
- .cx-mx-summary{margin-inline-start:auto;color:var(--cx-muted);font-size:var(--cx-size-13px);font-variant-numeric:tabular-nums;}
16
+ .cx-mx-check{width:var(--cx-size-16px);height:var(--cx-size-16px);margin:0;accent-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
17
+ .cx-mx-summary{margin-inline-start:auto;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--cx-size-13px);font-variant-numeric:tabular-nums;}
18
18
  .cx-mx-panel{position:absolute;top:calc(100% + var(--cx-size-4px));inset-inline-start:0;z-index:30;box-sizing:border-box;width:min(var(--cx-size-340px),100%);max-height:var(--cx-size-60vh);
19
- overflow:auto;display:grid;gap:var(--cx-size-10px);padding:var(--cx-size-12px);background:var(--cx-surface);border:var(--cx-size-1px) solid var(--cx-line-strong);
20
- border-radius:var(--cx-radius);box-shadow:0 var(--cx-size-8px) var(--cx-size-24px) color-mix(in srgb,var(--cx-shadow-ink) 16%,transparent);}
21
- .cx-mx-field{display:grid;gap:var(--cx-size-4px);font-size:var(--cx-size-13px);color:var(--cx-muted);}
22
- .cx-mx-field .cx-mx-input{color:var(--cx-text);}
19
+ overflow:auto;display:grid;gap:var(--cx-size-10px);padding:var(--cx-size-12px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));border:var(--cx-size-1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));
20
+ border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));}
21
+ .cx-mx-field{display:grid;gap:var(--cx-size-4px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
22
+ .cx-mx-field .cx-mx-input{color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));}
23
23
  .cx-mx-facet{display:grid;gap:var(--cx-size-4px);margin:0;padding:0;border:0;min-width:0;}
24
- .cx-mx-facet legend{padding:0 0 var(--cx-size-4px);font-size:var(--cx-size-13px);color:var(--cx-muted);}
25
- .cx-mx-keycount{color:var(--cx-muted);font-variant-numeric:tabular-nums;margin-inline-start:var(--cx-size-4px);}
24
+ .cx-mx-facet legend{padding:0 0 var(--cx-size-4px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
25
+ .cx-mx-keycount{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-variant-numeric:tabular-nums;margin-inline-start:var(--cx-size-4px);}
26
26
  .cx-mx-legend{display:flex;flex-wrap:wrap;gap:var(--cx-size-6px) var(--cx-size-16px);font-size:var(--cx-size-13px);}
27
27
  .cx-mx-key{display:inline-flex;align-items:center;gap:var(--cx-size-6px);}
28
- .cx-mx-swatch{display:inline-flex;align-items:center;justify-content:center;width:var(--cx-size-20px);height:var(--cx-size-20px);border-radius:var(--cx-radius-sm);
28
+ .cx-mx-swatch{display:inline-flex;align-items:center;justify-content:center;width:var(--cx-size-20px);height:var(--cx-size-20px);border-radius:var(--hfx-radius-sm,4px);
29
29
  border:var(--cx-size-1px) solid var(--mx-line);flex:none;}
30
- .cx-mx-swatch.cx-mx-none{background:var(--cx-surface);}
30
+ .cx-mx-swatch.cx-mx-none{background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));}
31
31
  .cx-mx-swatch.cx-mx-none::after{content:"";width:var(--cx-size-3px);height:var(--cx-size-3px);border-radius:50%;background:var(--mx-none);}
32
- .cx-mx-scroll{position:relative;flex:0 1 auto;box-sizing:border-box;width:fit-content;max-width:100%;min-height:0;max-height:var(--cx-size-100vh);overflow:auto;background:var(--cx-surface);border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);
32
+ .cx-mx-scroll{position:relative;flex:0 1 auto;box-sizing:border-box;width:fit-content;max-width:100%;min-height:0;max-height:var(--cx-size-100vh);overflow:auto;background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));
33
33
  overscroll-behavior:contain;scrollbar-color:var(--cx-scrollbar-thumb,auto) var(--cx-scrollbar-track,auto);}
34
- .cx-mx-head{position:sticky;top:0;z-index:3;width:var(--mx-content-w);background:var(--cx-head-bg);}
34
+ .cx-mx-head{position:sticky;top:0;z-index:3;width:var(--mx-content-w);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
35
35
  .cx-mx-head.cx-mx-raised{box-shadow:0 var(--cx-size-6px) var(--cx-size-8px) calc(var(--cx-size-6px) * -1) var(--mx-raised);}
36
36
  .cx-mx-band,.cx-mx-hrow,.cx-mx-frow{position:relative;display:flex;}
37
37
  .cx-mx-band{height:var(--mx-band-h);border-bottom:var(--cx-size-1px) solid var(--mx-line);}
38
- .cx-mx-hrow{height:var(--mx-head-h);border-bottom:var(--cx-size-1px) solid var(--cx-line);}
38
+ .cx-mx-hrow{height:var(--mx-head-h);border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
39
39
  .cx-mx-spacer{flex:none;width:var(--mx-cols-w);}
40
40
  .cx-mx-corner{position:sticky;inset-inline-start:0;z-index:2;box-sizing:border-box;flex:none;width:var(--mx-head-w);display:flex;flex-direction:column;justify-content:flex-end;
41
- gap:var(--cx-size-2px);padding:var(--cx-size-6px) var(--cx-size-10px);background:var(--cx-head-bg);border-inline-end:var(--cx-size-1px) solid var(--cx-line);
42
- font-size:var(--cx-size-12px);font-weight:600;color:var(--cx-muted);}
41
+ gap:var(--cx-size-2px);padding:var(--cx-size-6px) var(--cx-size-10px);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-inline-end:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));
42
+ font-size:var(--cx-size-12px);font-weight:600;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
43
43
  .cx-mx-corner-columns{align-self:flex-end;}
44
44
  .cx-mx-corner-columns::after{content:" \2192";}
45
45
  .cx-mx-corner-rows::after{content:" \2193";}
@@ -47,84 +47,84 @@ font-size:var(--cx-size-12px);font-weight:600;color:var(--cx-muted);}
47
47
  .cx-mx-hcell{position:absolute;top:0;bottom:0;box-sizing:border-box;width:var(--mx-cell-w);contain:strict;display:flex;align-items:flex-end;justify-content:center;padding-bottom:var(--cx-size-6px);
48
48
  border-inline-end:var(--cx-size-1px) solid var(--mx-line);font-size:var(--cx-size-12px);}
49
49
  .cx-mx-vlabel{writing-mode:vertical-rl;transform:rotate(180deg);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-height:calc(var(--mx-head-h) - var(--cx-size-12px));}
50
- .cx-mx-bcell{position:absolute;top:0;bottom:0;box-sizing:border-box;display:flex;align-items:center;padding:0 var(--cx-size-4px);border-inline-end:var(--cx-size-1px) solid var(--cx-line);
50
+ .cx-mx-bcell{position:absolute;top:0;bottom:0;box-sizing:border-box;display:flex;align-items:center;padding:0 var(--cx-size-4px);border-inline-end:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));
51
51
  overflow:hidden;font-size:var(--cx-size-12px);font-weight:600;}
52
- .cx-mx-bandcorner,.cx-mx-bandend{background:var(--cx-head-bg);}
52
+ .cx-mx-bandcorner,.cx-mx-bandend{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
53
53
  .cx-mx-bcell .cx-mx-toggle{max-width:100%;overflow:hidden;}
54
54
  .cx-mx-bclip .cx-mx-toggle{visibility:hidden;}
55
55
  .cx-mx-total{position:sticky;inset-inline-end:0;z-index:2;box-sizing:border-box;flex:none;width:var(--mx-total-w);display:flex;align-items:center;justify-content:flex-end;
56
- padding:0 var(--cx-size-10px);background:var(--cx-surface);border-inline-start:var(--cx-size-1px) solid var(--cx-line);font-variant-numeric:tabular-nums;font-weight:600;}
57
- .cx-mx-htotal{background:var(--cx-head-bg);align-items:flex-end;padding-bottom:var(--cx-size-6px);font-size:var(--cx-size-12px);color:var(--cx-muted);}
58
- .cx-mx-total.cx-mx-zero,.cx-mx-fcell.cx-mx-zero{font-weight:400;color:var(--cx-muted);}
56
+ padding:0 var(--cx-size-10px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));border-inline-start:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));font-variant-numeric:tabular-nums;font-weight:600;}
57
+ .cx-mx-htotal{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));align-items:flex-end;padding-bottom:var(--cx-size-6px);font-size:var(--cx-size-12px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
58
+ .cx-mx-total.cx-mx-zero,.cx-mx-fcell.cx-mx-zero{font-weight:400;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
59
59
  .cx-mx-body{position:relative;width:var(--mx-content-w);}
60
60
  .cx-mx-row{position:absolute;top:0;inset-inline-start:0;display:flex;contain:layout style;width:var(--mx-content-w);height:var(--mx-row-h);box-sizing:border-box;border-bottom:var(--cx-size-1px) solid var(--mx-line);}
61
61
  .cx-mx-rowhead{position:sticky;inset-inline-start:0;z-index:2;box-sizing:border-box;flex:none;width:var(--mx-head-w);display:flex;align-items:center;gap:var(--cx-size-6px);
62
- min-width:0;padding:0 var(--cx-size-10px);background:var(--cx-surface);border-inline-end:var(--cx-size-1px) solid var(--cx-line);white-space:nowrap;overflow:hidden;}
62
+ min-width:0;padding:0 var(--cx-size-10px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));border-inline-end:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));white-space:nowrap;overflow:hidden;}
63
63
  .cx-mx-member .cx-mx-rowhead{padding-inline-start:var(--cx-size-24px);}
64
64
  .cx-mx-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;}
65
65
  .cx-mx-rowhead > .cx-mx-label{flex:none;max-width:100%;}
66
- .cx-mx-sub{color:var(--cx-muted);font-size:var(--cx-size-12px);overflow:hidden;text-overflow:ellipsis;}
67
- .cx-mx-heading{background:var(--cx-head-bg);}
68
- .cx-mx-heading .cx-mx-rowhead,.cx-mx-rolledrow .cx-mx-rowhead{width:auto;min-width:var(--mx-head-w);background:var(--cx-head-bg);font-weight:600;}
69
- .cx-mx-heading .cx-mx-total,.cx-mx-rolledrow .cx-mx-total{background:var(--cx-head-bg);}
66
+ .cx-mx-sub{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--cx-size-12px);overflow:hidden;text-overflow:ellipsis;}
67
+ .cx-mx-heading{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
68
+ .cx-mx-heading .cx-mx-rowhead,.cx-mx-rolledrow .cx-mx-rowhead{width:auto;min-width:var(--mx-head-w);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));font-weight:600;}
69
+ .cx-mx-heading .cx-mx-total,.cx-mx-rolledrow .cx-mx-total{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
70
70
  .cx-mx-toggle{display:inline-flex;align-items:center;gap:var(--cx-size-6px);min-width:0;min-height:var(--cx-size-24px);padding:0;font:inherit;color:inherit;background:none;border:0;cursor:pointer;}
71
71
  .cx-mx-toggle::before{content:"";flex:none;width:0;height:0;border-block:var(--cx-size-4px) solid transparent;border-inline-start:var(--cx-size-6px) solid currentColor;transition:transform .12s;}
72
72
  .cx-mx-toggle[aria-expanded="true"]::before{transform:rotate(90deg);}
73
73
  .cx-mx-toggle:dir(rtl)[aria-expanded="true"]::before{transform:rotate(-90deg);}
74
74
  .cx-mx-hcell .cx-mx-toggle{flex-direction:column;}
75
75
  .cx-mx-cell{position:absolute;top:0;box-sizing:border-box;width:var(--mx-cell-w);height:100%;contain:strict;display:flex;align-items:center;justify-content:center;gap:var(--cx-size-2px);
76
- border-inline-end:var(--cx-size-1px) solid var(--mx-line);font-size:var(--cx-size-11px);font-variant-numeric:tabular-nums;cursor:pointer;color:var(--cx-muted);}
77
- .cx-mx-cell.cx-tone-danger{color:var(--cx-tone-danger);}
78
- .cx-mx-cell.cx-tone-warning{color:var(--cx-tone-warning);}
79
- .cx-mx-cell.cx-tone-info{color:var(--cx-tone-info);}
80
- .cx-mx-cell.cx-tone-success{color:var(--cx-tone-success);}
76
+ border-inline-end:var(--cx-size-1px) solid var(--mx-line);font-size:var(--cx-size-11px);font-variant-numeric:tabular-nums;cursor:pointer;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
77
+ .cx-mx-cell.cx-tone-danger{color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));}
78
+ .cx-mx-cell.cx-tone-warning{color:var(--hfx-color-status-warn-fg,light-dark(#8c5c05,#eeb640));}
79
+ .cx-mx-cell.cx-tone-info{color:var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7));}
80
+ .cx-mx-cell.cx-tone-success{color:var(--hfx-color-status-good-fg,light-dark(#177345,#4cc78a));}
81
81
  .cx-mx-cell.cx-toned{color:var(--cx-t);}
82
- .cx-mx-cell.cx-tone-success:not(.cx-mx-attn){color:var(--cx-quiet);}
82
+ .cx-mx-cell.cx-tone-success:not(.cx-mx-attn){color:var(--hfx-color-status-good-solid,light-dark(#1d8a52,#4cc78a));}
83
83
  .cx-mx-cell.cx-mx-none{color:var(--mx-none);}
84
- .cx-mx-cell.cx-mx-attn{background:var(--mx-bg,var(--cx-hover-bg));font-weight:600;}
85
- .cx-mx-attn.cx-tone-danger{--mx-bg:var(--cx-tone-danger-bg);}
86
- .cx-mx-attn.cx-tone-warning{--mx-bg:var(--cx-tone-warning-bg);}
87
- .cx-mx-attn.cx-tone-info{--mx-bg:var(--cx-tone-info-bg);}
88
- .cx-mx-attn.cx-tone-success{--mx-bg:var(--cx-tone-success-bg);}
89
- .cx-mx-attn.cx-toned{color:var(--cx-t);--mx-bg:var(--cx-t-bg,color-mix(in srgb,var(--cx-t) 12%,var(--cx-surface)));}
90
- .cx-host[data-cx-theme="dark"] .cx-mx-attn.cx-tone-danger{--mx-bg:color-mix(in srgb,var(--cx-tone-danger-bg) 62%,var(--cx-surface));}
91
- @media (prefers-color-scheme:dark){.cx-host[data-cx-theme="auto"] .cx-mx-attn.cx-tone-danger{--mx-bg:color-mix(in srgb,var(--cx-tone-danger-bg) 62%,var(--cx-surface));}}
84
+ .cx-mx-cell.cx-mx-attn{background:var(--mx-bg,var(--hfx-color-hover,light-dark(#f5f5f5,#232529)));font-weight:600;}
85
+ .cx-mx-attn.cx-tone-danger{--mx-bg:var(--hfx-color-status-bad-bg,light-dark(#f9e4e4,#3c272a));}
86
+ .cx-mx-attn.cx-tone-warning{--mx-bg:var(--hfx-color-status-warn-bg,light-dark(#f8efde,#3b3322));}
87
+ .cx-mx-attn.cx-tone-info{--mx-bg:var(--hfx-color-status-info-bg,light-dark(#e4ecfa,#262f41));}
88
+ .cx-mx-attn.cx-tone-success{--mx-bg:var(--hfx-color-status-good-bg,light-dark(#e2f0e9,#1f362f));}
89
+ .cx-mx-attn.cx-toned{color:var(--cx-t);--mx-bg:var(--cx-t-bg,color-mix(in srgb,var(--cx-t) 12%,var(--hfx-color-surface,light-dark(#ffffff,#16181c))));}
90
+ .cx-host[data-cx-theme="dark"] .cx-mx-attn.cx-tone-danger{--mx-bg:color-mix(in srgb,var(--hfx-color-status-bad-bg,light-dark(#f9e4e4,#3c272a)) 62%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));}
91
+ @media (prefers-color-scheme:dark){.cx-host[data-cx-theme="auto"] .cx-mx-attn.cx-tone-danger{--mx-bg:color-mix(in srgb,var(--hfx-color-status-bad-bg,light-dark(#f9e4e4,#3c272a)) 62%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));}}
92
92
  .cx-mx-cell.cx-mx-self{cursor:default;background:repeating-linear-gradient(135deg,transparent 0 var(--cx-size-4px),var(--mx-line) var(--cx-size-4px) var(--cx-size-5px));}
93
93
  .cx-mx-cell.cx-mx-rolled{box-shadow:inset 0 0 0 var(--cx-size-1px) var(--mx-line);}
94
94
  .cx-mx-canvas{position:absolute;top:0;cursor:pointer;}
95
95
  .cx-mx-cell.cx-mx-focus{z-index:1;background:transparent;border:0;cursor:pointer;}
96
- .cx-mx-hover{position:absolute;top:0;z-index:1;box-sizing:border-box;width:var(--mx-cell-w);height:100%;pointer-events:none;box-shadow:inset 0 0 0 var(--cx-size-2px) var(--cx-accent);}
96
+ .cx-mx-hover{position:absolute;top:0;z-index:1;box-sizing:border-box;width:var(--mx-cell-w);height:100%;pointer-events:none;box-shadow:inset 0 0 0 var(--cx-size-2px) var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
97
97
  .cx-mx-gridline{color:var(--mx-line);}
98
98
  .cx-mx-symbol{width:var(--cx-size-14px);height:var(--cx-size-14px);flex:none;}
99
99
  .cx-mx-swatch .cx-mx-symbol{width:var(--cx-size-13px);height:var(--cx-size-13px);}
100
100
  .cx-mx-value{overflow:hidden;white-space:nowrap;}
101
- .cx-mx-foot{position:sticky;bottom:0;z-index:3;width:var(--mx-content-w);background:var(--cx-head-bg);border-top:var(--cx-size-1px) solid var(--cx-line-strong);}
101
+ .cx-mx-foot{position:sticky;bottom:0;z-index:3;width:var(--mx-content-w);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-top:var(--cx-size-1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));}
102
102
  .cx-mx-foot.cx-mx-raised{box-shadow:0 calc(var(--cx-size-6px) * -1) var(--cx-size-8px) calc(var(--cx-size-6px) * -1) var(--mx-raised);}
103
103
  .cx-mx-frow{height:var(--mx-row-h);}
104
- .cx-mx-foothead{background:var(--cx-head-bg);font-weight:600;}
104
+ .cx-mx-foothead{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));font-weight:600;}
105
105
  .cx-mx-fcell{position:absolute;top:0;bottom:0;box-sizing:border-box;width:var(--mx-cell-w);contain:strict;display:flex;align-items:center;justify-content:center;
106
106
  border-inline-end:var(--cx-size-1px) solid var(--mx-line);font-size:var(--cx-size-11px);font-weight:600;font-variant-numeric:tabular-nums;}
107
- .cx-mx-foot .cx-mx-total{background:var(--cx-head-bg);}
108
- .cx-matrix :is(.cx-mx-cell,.cx-mx-rowhead,.cx-mx-hcell,.cx-mx-total,.cx-mx-fcell,.cx-mx-corner):focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:calc(var(--cx-size-2px) * -1);z-index:4;}
109
- .cx-mx-empty{padding:var(--cx-size-24px);text-align:center;color:var(--cx-muted);border:var(--cx-size-1px) dashed var(--cx-line);border-radius:var(--cx-radius);}
107
+ .cx-mx-foot .cx-mx-total{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
108
+ .cx-matrix :is(.cx-mx-cell,.cx-mx-rowhead,.cx-mx-hcell,.cx-mx-total,.cx-mx-fcell,.cx-mx-corner):focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:calc(var(--cx-size-2px) * -1);z-index:4;}
109
+ .cx-mx-empty{padding:var(--cx-size-24px);text-align:center;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));border:var(--cx-size-1px) dashed var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));}
110
110
  .cx-mx-tip{position:absolute;z-index:20;box-sizing:border-box;max-width:var(--cx-size-320px);padding:var(--cx-size-8px) var(--cx-size-10px);pointer-events:none;
111
- background:var(--cx-surface);border:var(--cx-size-1px) solid var(--cx-line-strong);border-radius:var(--cx-radius);font-size:var(--cx-size-13px);
112
- box-shadow:0 var(--cx-size-4px) var(--cx-size-16px) color-mix(in srgb,var(--cx-shadow-ink) 14%,transparent);}
111
+ background:var(--hfx-color-surface-raised,light-dark(#ffffff,#1e2126));border:var(--cx-size-1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));font-size:var(--cx-size-13px);
112
+ box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));}
113
113
  .cx-matrix{position:relative;}
114
114
  .cx-mx-tiptitle{font-weight:600;margin-bottom:var(--cx-size-4px);}
115
115
  .cx-mx-tiplist,.cx-mx-details{display:grid;grid-template-columns:auto 1fr;gap:var(--cx-size-2px) var(--cx-size-10px);margin:0;}
116
- .cx-mx-tiplist dt,.cx-mx-details dt{color:var(--cx-muted);}
116
+ .cx-mx-tiplist dt,.cx-mx-details dt{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
117
117
  .cx-mx-tiplist dd,.cx-mx-details dd{margin:0;overflow-wrap:anywhere;}
118
- .cx-mx-dialog{box-sizing:border-box;width:min(var(--cx-size-420px),calc(100vw - var(--cx-size-32px)));padding:var(--cx-size-16px);color:var(--cx-text);background:var(--cx-surface);
119
- border:var(--cx-size-1px) solid var(--cx-line-strong);border-radius:var(--cx-radius);}
120
- .cx-mx-dialog::backdrop{background:color-mix(in srgb,var(--cx-shadow-ink) 35%,transparent);}
118
+ .cx-mx-dialog{box-sizing:border-box;width:min(var(--cx-size-420px),calc(100vw - var(--cx-size-32px)));padding:var(--cx-size-16px);color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));
119
+ border:var(--cx-size-1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));}
120
+ .cx-mx-dialog::backdrop{background:var(--hfx-color-overlay,light-dark(rgba(22,24,28,0.42),rgba(0,0,0,0.66)));}
121
121
  .cx-mx-dialoghead{display:flex;align-items:center;gap:var(--cx-size-10px);margin-bottom:var(--cx-size-12px);}
122
122
  .cx-mx-dialogtitle{margin:0;font-size:var(--cx-size-17px);}
123
123
  .cx-mx-dialog .cx-mx-button{margin-top:var(--cx-size-16px);}
124
124
  .cx-mx-cards{display:grid;align-content:start;gap:var(--cx-size-8px);flex:0 1 auto;min-height:0;max-height:var(--cx-size-100vh);overflow:auto;overscroll-behavior:contain;}
125
125
  .cx-mx-cardlist,.cx-mx-cardcells{list-style:none;margin:0;padding:0;display:grid;gap:var(--cx-size-8px);}
126
- .cx-mx-card{padding:var(--cx-size-10px) var(--cx-size-12px);border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);background:var(--cx-surface);}
127
- .cx-mx-cardgroup{padding:var(--cx-size-4px) 0 0;font-size:var(--cx-size-13px);font-weight:600;color:var(--cx-muted);}
126
+ .cx-mx-card{padding:var(--cx-size-10px) var(--cx-size-12px);border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));}
127
+ .cx-mx-cardgroup{padding:var(--cx-size-4px) 0 0;font-size:var(--cx-size-13px);font-weight:600;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
128
128
  .cx-mx-cardhead{display:flex;align-items:center;justify-content:space-between;gap:var(--cx-size-8px);font-weight:600;}
129
129
  .cx-mx-card .cx-mx-total{position:static;width:auto;padding:0;border:0;background:none;}
130
130
  .cx-mx-cardcells{gap:var(--cx-size-4px);margin-top:var(--cx-size-6px);}
@@ -141,23 +141,23 @@ border:var(--cx-size-1px) solid var(--cx-line-strong);border-radius:var(--cx-rad
141
141
  .cx-matrix .cx-mx-print{display:block;}
142
142
  .cx-matrix-host{max-height:none !important;}
143
143
  .cx-mx-printtable{border-collapse:collapse;font-size:var(--cx-size-11px);-webkit-print-color-adjust:exact;print-color-adjust:exact;}
144
- .cx-mx-printtable :is(th,td){border:var(--cx-size-1px) solid var(--cx-line);padding:var(--cx-size-2px) var(--cx-size-4px);text-align:center;}
145
- .cx-mx-printtable thead th{background:var(--cx-head-bg);}
144
+ .cx-mx-printtable :is(th,td){border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));padding:var(--cx-size-2px) var(--cx-size-4px);text-align:center;}
145
+ .cx-mx-printtable thead th{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
146
146
  .cx-mx-printtable :is(th[scope="row"],th[scope="rowgroup"]){text-align:start;}
147
147
  .cx-mx-printtable caption{text-align:start;font-weight:600;padding-bottom:var(--cx-size-6px);}
148
- .cx-mx-printgroup > th,.cx-mx-printgroup > td,.cx-mx-printrolled > th{background:var(--cx-head-bg);font-weight:600;}
149
- .cx-mx-printcount{font-weight:400;color:var(--cx-muted);}
148
+ .cx-mx-printgroup > th,.cx-mx-printgroup > td,.cx-mx-printrolled > th{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));font-weight:600;}
149
+ .cx-mx-printcount{font-weight:400;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
150
150
  .cx-mx-printmember{padding-inline-start:var(--cx-size-16px) !important;font-weight:400;}
151
- .cx-mx-printcell{color:var(--cx-muted);}
152
- .cx-mx-printcell.cx-tone-danger{color:var(--cx-tone-danger);}
153
- .cx-mx-printcell.cx-tone-warning{color:var(--cx-tone-warning);}
154
- .cx-mx-printcell.cx-tone-info{color:var(--cx-tone-info);}
155
- .cx-mx-printcell.cx-tone-success{color:var(--cx-quiet);}
151
+ .cx-mx-printcell{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
152
+ .cx-mx-printcell.cx-tone-danger{color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));}
153
+ .cx-mx-printcell.cx-tone-warning{color:var(--hfx-color-status-warn-fg,light-dark(#8c5c05,#eeb640));}
154
+ .cx-mx-printcell.cx-tone-info{color:var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7));}
155
+ .cx-mx-printcell.cx-tone-success{color:var(--hfx-color-status-good-solid,light-dark(#1d8a52,#4cc78a));}
156
156
  .cx-mx-printcell.cx-toned{color:var(--cx-t);}
157
- .cx-mx-printcell.cx-mx-attn{background:var(--mx-bg,var(--cx-hover-bg));font-weight:700;}
158
- .cx-mx-printcell.cx-mx-attn.cx-tone-success{color:var(--cx-tone-success);}
157
+ .cx-mx-printcell.cx-mx-attn{background:var(--mx-bg,var(--hfx-color-hover,light-dark(#f5f5f5,#232529)));font-weight:700;}
158
+ .cx-mx-printcell.cx-mx-attn.cx-tone-success{color:var(--hfx-color-status-good-fg,light-dark(#177345,#4cc78a));}
159
159
  .cx-mx-printnone{color:var(--mx-none);}
160
- .cx-mx-printself{background:var(--cx-hover-bg);}
160
+ .cx-mx-printself{background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));}
161
161
  }
162
162
  @media (forced-colors:active){
163
163
  .cx-mx-cell.cx-mx-attn{border:var(--cx-size-1px) solid CanvasText;}
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"16ab7faa98c96b46",install(context){if(installed.has(context.MATRIX_IMPL))return;const{MATRIX_IMPL,h,setText,fill,plural,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}=context;const MATRIX_LABELS={matrixRows:"Rows",matrixColumns:"Columns",matrixSearch:"Find rows and columns",matrixSortBy:"Sort by",matrixGroupBy:"Group by",matrixByLabel:"Name",matrixByTotal:"Total",matrixAsListed:"As listed",matrixNoGrouping:"No groups",matrixDescending:"Descending",matrixOnlyProblems:"Only problems",matrixHideEmpty:"Hide empty rows and columns",matrixSize:"{rows} × {columns}",matrixShown:"Rows: {rows} of {totalRows}, columns: {columns} of {totalColumns}",matrixAttention:"Need attention: {count}",matrixLegend:"States",matrixFilter:"Filter",matrixClearFilters:"Clear filters",matrixNoMatches:"No rows or columns match.",matrixSelf:"Same item",matrixNoData:"No data",matrixCell:"{row} and {column}: {state}",matrixTotal:"Total",matrixItemTotal:"{item}: {count}",matrixExpandGroup:"Expand {group}",matrixCollapseGroup:"Collapse {group}",matrixGroupCount:"{count}",matrixCellCount:"Cells: {count}",matrixDetails:"Details",matrixClose:"Close",matrixValue:"Value",matrixState:"State",matrixAllClear:"Nothing needs attention",matrixShowMore:"Show more"};function matrixLabels(...sources){const labels={...MATRIX_LABELS};for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))matrixFail("labels must be an object of strings");for(const[name,text]of Object.entries(source)){if(!Object.hasOwn(labels,name)){if(/^matrix[A-Z]/.test(name)) matrixFail("there is no matrix label '" + name + "'"); continue; }
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"da5c61ff2cb9ebda",install(context){if(installed.has(context.MATRIX_IMPL))return;const{MATRIX_IMPL,h,setText,fill,plural,foldText,numberFormat,gridFreeze,toneOf,applyTone,toneColors,AxisWindow,PROTOCOL}=context;const MATRIX_LABELS={matrixRows:"Rows",matrixColumns:"Columns",matrixSearch:"Find rows and columns",matrixSortBy:"Sort by",matrixGroupBy:"Group by",matrixByLabel:"Name",matrixByTotal:"Total",matrixAsListed:"As listed",matrixNoGrouping:"No groups",matrixDescending:"Descending",matrixOnlyProblems:"Only problems",matrixHideEmpty:"Hide empty rows and columns",matrixSize:"{rows} × {columns}",matrixShown:"Rows: {rows} of {totalRows}, columns: {columns} of {totalColumns}",matrixAttention:"Need attention: {count}",matrixLegend:"States",matrixFilter:"Filter",matrixClearFilters:"Clear filters",matrixNoMatches:"No rows or columns match.",matrixSelf:"Same item",matrixNoData:"No data",matrixCell:"{row} and {column}: {state}",matrixTotal:"Total",matrixItemTotal:"{item}: {count}",matrixExpandGroup:"Expand {group}",matrixCollapseGroup:"Collapse {group}",matrixGroupCount:"{count}",matrixCellCount:"Cells: {count}",matrixDetails:"Details",matrixClose:"Close",matrixValue:"Value",matrixState:"State",matrixAllClear:"Nothing needs attention",matrixShowMore:"Show more"};function matrixLabels(...sources){const labels={...MATRIX_LABELS};for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))matrixFail("labels must be an object of strings");for(const[name,text]of Object.entries(source)){if(!Object.hasOwn(labels,name)){if(/^matrix[A-Z]/.test(name)) matrixFail("there is no matrix label '" + name + "'"); continue; }
2
2
  if(typeof text!=="string"||!/\S/.test(text)) matrixFail("label '" + name + "' must be a string with visible text");
3
3
  labels[name]=text}}
4
4
  return Object.freeze(labels)}
@@ -62,8 +62,7 @@ const MATRIX_ROW_HEIGHTS={compact:26,normal:30,comfortable:36},MATRIX_TOTAL_WIDT
62
62
  emit(name,detail,callback,cancelable){const event=new CustomEvent("canopyx:"+name,{detail,bubbles:true,cancelable:!!cancelable});const proceed=this.host.dispatchEvent(event);if(typeof this.options[callback]==="function"){try{this.options[callback](detail,event)}catch(error){this.reportError(error,callback)}}
63
63
  return proceed&&!event.defaultPrevented}
64
64
  reportError(error,hook){this.host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook},bubbles:true}))}
65
- build(){const host=this.host,doc=this.doc,signal=this.lifetime.signal;if(!host.hasAttribute("data-cx-theme")){host.setAttribute("data-cx-theme","auto");this.addedTheme=true}
66
- const root=this.root=h("div","cx-matrix cx-mx-"+doc.density);this.bar=h("div","cx-mx-bar");this.legend=h("div","cx-mx-legend");this.legend.setAttribute("role","list");this.legend.setAttribute("aria-label",this.labels.matrixLegend);this.legend.hidden=!doc.legend;const scroll=this.scroll=h("div","cx-mx-scroll");scroll.setAttribute("role","grid");scroll.setAttribute("aria-label",doc.label);this.head=h("div","cx-mx-head");this.head.setAttribute("role","rowgroup");this.band=h("div","cx-mx-band");this.band.setAttribute("role","row");this.headRow=h("div","cx-mx-hrow");this.headRow.setAttribute("role","row");this.corner=h("div","cx-mx-corner");this.corner.setAttribute("role","columnheader");this.corner.setAttribute("aria-colindex","1");this.headSpacer=h("div","cx-mx-spacer");this.headTotal=h("div","cx-mx-total cx-mx-htotal");this.headTotal.setAttribute("role","columnheader");this.band.setAttribute("aria-rowindex","1");this.headRow.append(this.corner,this.headSpacer,this.headTotal);this.bandCorner=h("div","cx-mx-corner cx-mx-bandcorner");this.bandSpacer=h("div","cx-mx-spacer");this.bandEnd=h("div","cx-mx-total cx-mx-bandend");this.band.append(this.bandCorner,this.bandSpacer,this.bandEnd);this.head.append(this.band,this.headRow);this.body=h("div","cx-mx-body");this.body.setAttribute("role","rowgroup");this.foot=h("div","cx-mx-foot");this.foot.setAttribute("role","rowgroup");this.footRow=h("div","cx-mx-frow");this.footRow.setAttribute("role","row");this.footHeader=h("div","cx-mx-rowhead cx-mx-foothead");this.footHeader.setAttribute("role","rowheader");this.footHeader.setAttribute("aria-colindex","1");this.footSpacer=h("div","cx-mx-spacer");this.footGrand=h("div","cx-mx-total cx-mx-grand");this.footGrand.setAttribute("role","gridcell");this.footRow.append(this.footHeader,this.footSpacer,this.footGrand);this.foot.appendChild(this.footRow);this.empty=h("div","cx-mx-empty");this.empty.hidden=true;scroll.append(this.head,this.body,this.foot);this.live=h("div","cx-sr-only");this.live.setAttribute("aria-live","polite");this.tip=h("div","cx-mx-tip");this.tip.setAttribute("aria-hidden","true");this.tip.hidden=true;this.cards=h("div","cx-mx-cards");this.cards.hidden=true;this.cards.tabIndex=0;this.cards.setAttribute("role","region");this.cards.setAttribute("aria-label",doc.label);this.print=h("div","cx-mx-print");root.append(this.bar,this.legend,scroll,this.empty,this.cards,this.live,this.tip,this.print);host.appendChild(root);this.buildBar();scroll.addEventListener("scroll",()=>{this.hideTip();this.scheduleRender()},{passive:true,signal});scroll.addEventListener("keydown",event=>this.onKey(event),{signal});scroll.addEventListener("click",event=>this.onClick(event),{signal});scroll.addEventListener("focusin",event=>this.onFocus(event),{signal});scroll.addEventListener("pointermove",event=>this.onPointer(event),{signal});scroll.addEventListener("pointerleave",()=>this.hideTip(),{signal});global.addEventListener("beforeprint",()=>this.renderPrint(),{signal});this.resize=new ResizeObserver(()=>{if(this.destroyed)return;const focused=this.scroll.contains(document.activeElement);this.layout();this.render();if(focused&&!this.scroll.contains(document.activeElement)){if(!this.scroll.hidden)this.moveTo(this.focus.row,this.focus.column,true,false);else if(!this.cards.hidden)this.cards.focus({preventScroll:true})}});this.refreshChrome();this.resize.observe(host);const restyle=()=>{if(!this.destroyed){this.lookCache=null;this.scheduleRender()}};this.themeWatch=new MutationObserver(restyle);this.themeWatch.observe(host,{attributes:true,attributeFilter:["data-cx-theme","class","style"]});for(const query of["(prefers-color-scheme: dark)","(forced-colors: active)"])global.matchMedia?.(query).addEventListener?.("change",restyle,{signal})}
65
+ build(){const host=this.host,doc=this.doc,signal=this.lifetime.signal;const root=this.root=h("div","cx-matrix cx-mx-"+doc.density);this.bar=h("div","cx-mx-bar");this.legend=h("div","cx-mx-legend");this.legend.setAttribute("role","list");this.legend.setAttribute("aria-label",this.labels.matrixLegend);this.legend.hidden=!doc.legend;const scroll=this.scroll=h("div","cx-mx-scroll");scroll.setAttribute("role","grid");scroll.setAttribute("aria-label",doc.label);this.head=h("div","cx-mx-head");this.head.setAttribute("role","rowgroup");this.band=h("div","cx-mx-band");this.band.setAttribute("role","row");this.headRow=h("div","cx-mx-hrow");this.headRow.setAttribute("role","row");this.corner=h("div","cx-mx-corner");this.corner.setAttribute("role","columnheader");this.corner.setAttribute("aria-colindex","1");this.headSpacer=h("div","cx-mx-spacer");this.headTotal=h("div","cx-mx-total cx-mx-htotal");this.headTotal.setAttribute("role","columnheader");this.band.setAttribute("aria-rowindex","1");this.headRow.append(this.corner,this.headSpacer,this.headTotal);this.bandCorner=h("div","cx-mx-corner cx-mx-bandcorner");this.bandSpacer=h("div","cx-mx-spacer");this.bandEnd=h("div","cx-mx-total cx-mx-bandend");this.band.append(this.bandCorner,this.bandSpacer,this.bandEnd);this.head.append(this.band,this.headRow);this.body=h("div","cx-mx-body");this.body.setAttribute("role","rowgroup");this.foot=h("div","cx-mx-foot");this.foot.setAttribute("role","rowgroup");this.footRow=h("div","cx-mx-frow");this.footRow.setAttribute("role","row");this.footHeader=h("div","cx-mx-rowhead cx-mx-foothead");this.footHeader.setAttribute("role","rowheader");this.footHeader.setAttribute("aria-colindex","1");this.footSpacer=h("div","cx-mx-spacer");this.footGrand=h("div","cx-mx-total cx-mx-grand");this.footGrand.setAttribute("role","gridcell");this.footRow.append(this.footHeader,this.footSpacer,this.footGrand);this.foot.appendChild(this.footRow);this.empty=h("div","cx-mx-empty");this.empty.hidden=true;scroll.append(this.head,this.body,this.foot);this.live=h("div","cx-sr-only");this.live.setAttribute("aria-live","polite");this.tip=h("div","cx-mx-tip");this.tip.setAttribute("aria-hidden","true");this.tip.hidden=true;this.cards=h("div","cx-mx-cards");this.cards.hidden=true;this.cards.tabIndex=0;this.cards.setAttribute("role","region");this.cards.setAttribute("aria-label",doc.label);this.print=h("div","cx-mx-print");root.append(this.bar,this.legend,scroll,this.empty,this.cards,this.live,this.tip,this.print);host.appendChild(root);this.buildBar();scroll.addEventListener("scroll",()=>{this.hideTip();this.scheduleRender()},{passive:true,signal});scroll.addEventListener("keydown",event=>this.onKey(event),{signal});scroll.addEventListener("click",event=>this.onClick(event),{signal});scroll.addEventListener("focusin",event=>this.onFocus(event),{signal});scroll.addEventListener("pointermove",event=>this.onPointer(event),{signal});scroll.addEventListener("pointerleave",()=>this.hideTip(),{signal});global.addEventListener("beforeprint",()=>this.renderPrint(),{signal});this.resize=new ResizeObserver(()=>{if(this.destroyed)return;const focused=this.scroll.contains(document.activeElement);this.layout();this.render();if(focused&&!this.scroll.contains(document.activeElement)){if(!this.scroll.hidden)this.moveTo(this.focus.row,this.focus.column,true,false);else if(!this.cards.hidden)this.cards.focus({preventScroll:true})}});this.refreshChrome();this.resize.observe(host);const restyle=()=>{if(!this.destroyed){this.lookCache=null;this.scheduleRender()}};this.themeWatch=new MutationObserver(restyle);const themeAttributes=["data-theme","data-cx-theme","data-cx-fallback-mode","data-hfx-style","data-hfx-mode","data-hfx-density","data-bs-theme","data-hfx-theme","data-hfx-tokens","class","style"];for(let owner=host;owner;owner=owner.parentElement)this.themeWatch.observe(owner,{attributes:true,attributeFilter:themeAttributes});for(const query of["(prefers-color-scheme: dark)","(forced-colors: active)"])global.matchMedia?.(query).addEventListener?.("change",restyle,{signal})}
67
66
  refreshChrome(){const doc=this.doc,labels=this.labels;this.scroll.setAttribute("aria-label",doc.label);this.cards.setAttribute("aria-label",doc.label);this.legend.setAttribute("aria-label",labels.matrixLegend);this.legend.hidden=!doc.legend;setText(this.headTotal,labels.matrixTotal);setText(this.footHeader,labels.matrixTotal);setText(this.empty,labels.matrixNoMatches);const columnsTitle=h("span","cx-mx-corner-columns"),rowsTitle=h("span","cx-mx-corner-rows");setText(columnsTitle,doc.columnTitle||labels.matrixColumns);setText(rowsTitle,doc.rows.title||labels.matrixRows);this.corner.replaceChildren(columnsTitle,rowsTitle);this.refreshBar?.()}
68
67
  derive(announce,anchor=this.captureFocus()){const focused=this.scroll.contains(document.activeElement);this.model.derive(this.query);this.restoreFocus(anchor);this.syncBar();this.paintLegend();this.layout();this.recycleAll();this.render();if(focused&&!this.scroll.hidden)this.moveTo(this.focus.row,this.focus.column,true,false);if(announce)setText(this.live,this.summaryText())}
69
68
  layout(){const doc=this.doc,width=this.host.clientWidth||800,phone=width<=640;this.phone=phone;this.root.classList.toggle("cx-mx-phone",phone);this.rtl=getComputedStyle(this.root).direction==="rtl";this.rowH=MATRIX_ROW_HEIGHTS[doc.density]+(phone?4:0);this.cellW=doc.cellWidth;const measure=this.measurer||=document.createElement("canvas").getContext("2d");const style=getComputedStyle(this.root),font=style.fontWeight+" "+style.fontSize+" "+style.fontFamily;const widest=(items,extra=0)=>{let max=0;if(measure){measure.font=font;for(const item of items)max=Math.max(max,measure.measureText(item.label).width+extra)}return max};const grouped=!!this.query.group.rows;const secondary=!phone&&this.model.rows.some(entry=>entry.kind==="item"&&entry.item.secondary)?Math.min(140,widest(this.model.rows.filter(entry=>entry.kind==="item"&&entry.item.secondary).map(entry=>({label:entry.item.secondary})))*0.88+6):0;const rowNeed=Math.ceil(widest(this.model.rows)+ secondary+28 +(grouped?14:0));this.rowHeadW=Math.min(phone?Math.max(96,Math.floor(width*0.42)):280,Math.max(phone?96:120,rowNeed));this.headH=Math.min(160,Math.max(56,Math.ceil(widest(this.model.columns)+ 20)));this.bandH=this.query.group.columns?28:0;this.totalW=doc.rowTotals?phone?48:MATRIX_TOTAL_WIDTH:0;this.footH=doc.columnTotals?this.rowH:0;const geometry=[this.rowH,this.rowHeadW,this.cellW,this.headH,this.bandH,this.totalW,this.rtl,phone].join(":");if(this.geometry!==undefined&&this.geometry!==geometry)this.recycleAll();this.geometry=geometry;this.rowWindow.reset(this.rowH,this.model.rows.length);this.columnWindow.reset(this.cellW,this.model.columns.length);const contentW=this.rowHeadW+this.columnWindow.total+this.totalW;const root=this.root.style;root.setProperty("--mx-row-h",this.rowH+"px");root.setProperty("--mx-cell-w",this.cellW+"px");root.setProperty("--mx-head-w",this.rowHeadW+"px");root.setProperty("--mx-head-h",this.headH+"px");root.setProperty("--mx-band-h",this.bandH+"px");root.setProperty("--mx-total-w",this.totalW+"px");root.setProperty("--mx-content-w",contentW+"px");root.setProperty("--mx-cols-w",this.columnWindow.total+"px");this.body.style.height=this.rowWindow.total+"px";this.band.hidden=!this.bandH;this.foot.hidden=!this.footH;this.headTotal.hidden=this.bandEnd.hidden=!this.totalW;this.footGrand.hidden=!this.totalW;const nothing=!this.model.rows.length||!this.model.columns.length;this.empty.hidden=!nothing;this.scroll.hidden=nothing;const cards=phone&&doc.phone==="cards";this.cards.hidden=!cards||nothing;if(cards)this.scroll.hidden=true;this.scroll.setAttribute("aria-rowcount",String(this.model.rows.length +(this.bandH?2:1)+(this.footH?1:0)));this.headRow.setAttribute("aria-rowindex",this.bandH?"2":"1");this.headTotal.setAttribute("aria-colindex",String(this.model.columns.length+2));this.scroll.setAttribute("aria-colcount",String(this.model.columns.length+1 +(this.totalW?1:0)));if(cards)this.renderCards();this.fitHeight()}
@@ -157,5 +156,5 @@ return result},applyState(state,derive=true){if(!state||typeof state!=="object")
157
156
  if(state.attentionOnly!==undefined)next.attentionOnly=!!state.attentionOnly;if(state.hideEmpty!==undefined)next.hideEmpty=!!state.hideEmpty;for(const axis of MATRIX_AXES){if(state.filters&&state.filters[axis]!==undefined)next.filters[axis]=this.checkFilters(axis,state.filters[axis]);if(state.sort&&state.sort[axis]!==undefined)next.sort[axis]=this.checkSort(axis,state.sort[axis]);if(state.group&&state.group[axis]!==undefined){const group=state.group[axis];if(group!==null&&!this.axisData(axis).attributeById.has(group))throw new Error("CanopyX: a matrix groups by one of its attributes.");if(group!==next.group[axis])next.collapsed[axis]=[];next.group[axis]=group}
158
157
  if(state.collapsed&&state.collapsed[axis]!==undefined){if(!Array.isArray(state.collapsed[axis])||state.collapsed[axis].some(key=>typeof key!=="string"))throw new Error("CanopyX: collapsed groups are a list of group keys.");next.collapsed[axis]=[...new Set(state.collapsed[axis])]}}
159
158
  this.query=next;if(derive){this.derive(true);this.stateChanged()}},setQuery(partial){this.applyState(partial)},sort(axis,by,direction="asc"){this.applyState({sort:{[matrixAxisName(axis)]:by==null?null:{by,direction}}})},group(axis,attribute){this.applyState({group:{[matrixAxisName(axis)]:attribute??null}})},filter(axis,attribute,values){this.applyState({filters:{[matrixAxisName(axis)]:{...this.query.filters[axis],[attribute]:values??null}}})},getState(){const query=this.query,copy=value=>JSON.parse(JSON.stringify(value));return gridFreeze({search:query.search,attentionOnly:query.attentionOnly,hideEmpty:query.hideEmpty,filters:copy(query.filters),sort:copy(query.sort),group:copy(query.group),collapsed:copy(query.collapsed)})},stateChanged(){this.emit("matrixState",this.getState(),"onStateChange")},getVisible(){const ids=entries=>entries.filter(entry=>entry.kind!=="heading").flatMap(entry=>entry.members.map(item=>item.id));return gridFreeze({rows:ids(this.model.rows),columns:ids(this.model.columns)})},focusCell(row,column){const r=this.model.rows.findIndex(entry=>entry.kind!=="heading"&&entry.members.some(item=>item.id===row));const c=this.model.columns.findIndex(entry=>entry.members.some(item=>item.id===column));if(r<0||c<0)return false;this.moveTo(r,c);return true},update(view){const doc=matrixDocument(view),state=JSON.parse(JSON.stringify(this.getState())),focus=this.captureFocus();this.doc=doc;this.labels=matrixLabels(doc.labels,this.options.labels);this.model=new MatrixModel(doc,this.format);this.query=this.model.initialQuery();for(const axis of MATRIX_AXES){const attributes=this.axisData(axis).attributeById;state.filters[axis]=Object.fromEntries(Object.entries(state.filters[axis]).filter(([id])=>attributes.has(id)));const sort=state.sort[axis];if(sort&&!["#label","#total"].includes(sort.by)&&!attributes.has(sort.by))state.sort[axis]=null;if(state.group[axis]!==null&&!attributes.has(state.group[axis])){state.group[axis]=null;state.collapsed[axis]=[]}}
160
- this.applyState(state,false);this.root.className="cx-matrix cx-mx-"+doc.density;this.source=view;this.closePanel(false);this.refreshChrome();this.geometry=undefined;this.derive(false,focus)}});function matrixCreate(host,options){const view=new MatrixView(host,options);const impl={ready:Promise.resolve().then(()=>{if(view.destroyed)return impl;host.setAttribute("data-cx-ready","");view.emit("matrixReady",{matrix:view.doc.id},"onReady");return impl}),document:()=>view.source||view.options.view,sort:(axis,by,direction)=>view.sort(axis,by,direction),group:(axis,attribute)=>view.group(axis,attribute),filter:(axis,attribute,values)=>view.filter(axis,attribute,values),setSearch:text=>view.setQuery({search:text}),setAttentionOnly:on=>view.setQuery({attentionOnly:!!on}),getState:()=>view.getState(),setState:state=>view.applyState(state),getVisible:()=>view.getVisible(),focusCell:(row,column)=>view.focusCell(row,column),update:next=>view.update(next),destroy:()=>{if(view.destroyed)return;view.destroyed=true;view.lifetime.abort();view.resize?.disconnect();view.themeWatch?.disconnect();cancelAnimationFrame(view.frame);cancelAnimationFrame(view.fitFrame);clearTimeout(view.searchTimer);clearTimeout(view.tipTimer);view.root.remove();host.removeAttribute("data-cx-ready");if(view.addedTheme)host.removeAttribute("data-cx-theme");if(view.fitInline!==undefined){host.style.maxHeight=view.fitInline;if(!host.getAttribute("style"))host.removeAttribute("style")}}};return impl}
159
+ this.applyState(state,false);this.root.className="cx-matrix cx-mx-"+doc.density;this.source=view;this.closePanel(false);this.refreshChrome();this.geometry=undefined;this.derive(false,focus)}});function matrixCreate(host,options){const view=new MatrixView(host,options);const impl={ready:Promise.resolve().then(()=>{if(view.destroyed)return impl;host.setAttribute("data-cx-ready","");view.emit("matrixReady",{matrix:view.doc.id},"onReady");return impl}),document:()=>view.source||view.options.view,sort:(axis,by,direction)=>view.sort(axis,by,direction),group:(axis,attribute)=>view.group(axis,attribute),filter:(axis,attribute,values)=>view.filter(axis,attribute,values),setSearch:text=>view.setQuery({search:text}),setAttentionOnly:on=>view.setQuery({attentionOnly:!!on}),getState:()=>view.getState(),setState:state=>view.applyState(state),getVisible:()=>view.getVisible(),focusCell:(row,column)=>view.focusCell(row,column),update:next=>view.update(next),destroy:()=>{if(view.destroyed)return;view.destroyed=true;view.lifetime.abort();view.resize?.disconnect();view.themeWatch?.disconnect();cancelAnimationFrame(view.frame);cancelAnimationFrame(view.fitFrame);clearTimeout(view.searchTimer);clearTimeout(view.tipTimer);view.root.remove();host.removeAttribute("data-cx-ready");if(view.fitInline!==undefined){host.style.maxHeight=view.fitInline;if(!host.getAttribute("style"))host.removeAttribute("style")}}};return impl}
161
160
  MATRIX_IMPL.create=matrixCreate;installed.add(context.MATRIX_IMPL)}};(global.CanopyXParts||=[]).push(["matrix",part])})(typeof window!=="undefined"?window:globalThis);