@evotecit/canopyx 0.3.6 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/CanopyX.Html/Assets/canopyx-calendar.js +4 -3
  2. package/CanopyX.Html/Assets/canopyx-detail-rows.js +2 -2
  3. package/CanopyX.Html/Assets/canopyx-filter-editor.js +2 -1
  4. package/CanopyX.Html/Assets/canopyx-formatting.js +7 -6
  5. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +62 -40
  6. package/CanopyX.Html/Assets/canopyx-grid.css +22 -0
  7. package/CanopyX.Html/Assets/canopyx-grid.js +62 -40
  8. package/CanopyX.Html/Assets/canopyx-interactive.js +4 -4
  9. package/CanopyX.Html/Assets/canopyx-labels-de.js +3 -1
  10. package/CanopyX.Html/Assets/canopyx-labels-es.js +3 -1
  11. package/CanopyX.Html/Assets/canopyx-labels-fr.js +3 -1
  12. package/CanopyX.Html/Assets/canopyx-labels-it.js +3 -1
  13. package/CanopyX.Html/Assets/canopyx-labels-pl.js +3 -1
  14. package/CanopyX.Html/Assets/canopyx-live.js +4 -3
  15. package/CanopyX.Html/Assets/canopyx-matrix.js +3 -3
  16. package/CanopyX.Html/Assets/canopyx-module.mjs +4 -4
  17. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +64 -42
  18. package/CanopyX.Html/Assets/canopyx-reporting.css +22 -0
  19. package/CanopyX.Html/Assets/canopyx-reporting.js +64 -42
  20. package/CanopyX.Html/Assets/canopyx-tree-tools.js +7 -6
  21. package/CanopyX.Html/Assets/canopyx.js +4 -4
  22. package/JavaScript/grid.d.ts +6 -0
  23. package/JavaScript/locales/de.mjs +3 -1
  24. package/JavaScript/locales/es.mjs +3 -1
  25. package/JavaScript/locales/fr.mjs +3 -1
  26. package/JavaScript/locales/it.mjs +3 -1
  27. package/JavaScript/locales/pl.mjs +3 -1
  28. package/JavaScript/protocol.d.ts +1 -1
  29. package/README.md +6 -2
  30. package/package.json +1 -1
@@ -12,6 +12,7 @@ const labels = Object.freeze({
12
12
  searchWordTooShort: "Ein Wort mit mindestens {min} Zeichen eingeben",
13
13
  searchFailed: "Suche fehlgeschlagen: {error}",
14
14
  columns: "Spalten",
15
+ hiddenColumns: "[one]+{count} Spalte[other]+{count} Spalten",
15
16
  gridFilters: "Filter",
16
17
  gridFitContent: "An Inhalt anpassen",
17
18
  gridUnpin: "Fixierung aufheben",
@@ -244,7 +245,7 @@ const labels = Object.freeze({
244
245
  gridExportCancelled: "Export abgebrochen",
245
246
  gridCancelExport: "Export abbrechen",
246
247
  gridPrint: "Drucken",
247
- gridCloseRecord: "Datensatzdetails schließen",
248
+ gridCloseRecord: "Schließen",
248
249
  gridContains: "enthält",
249
250
  gridStartsWith: "beginnt mit",
250
251
  gridIn: "ist einer der Werte",
@@ -689,6 +690,7 @@ const labels = Object.freeze({
689
690
  matrixItemTotal: "{item}: {count}",
690
691
  matrixExpandGroup: "{group} aufklappen",
691
692
  matrixCollapseGroup: "{group} zuklappen",
693
+ matrixGroupHeadingCount: "{count}",
692
694
  matrixGroupCount: "Elemente: {count}",
693
695
  matrixDetails: "Details",
694
696
  matrixClose: "Schließen",
@@ -12,6 +12,7 @@ const labels = Object.freeze({
12
12
  searchWordTooShort: "Escriba una palabra de al menos {min} caracteres",
13
13
  searchFailed: "Error al buscar: {error}",
14
14
  columns: "Columnas",
15
+ hiddenColumns: "[one]+{count} columna[other]+{count} columnas",
15
16
  gridFilters: "Filtros",
16
17
  gridFitContent: "Ajustar al contenido",
17
18
  gridUnpin: "Desfijar",
@@ -244,7 +245,7 @@ const labels = Object.freeze({
244
245
  gridExportCancelled: "Exportación cancelada",
245
246
  gridCancelExport: "Cancelar exportación",
246
247
  gridPrint: "Imprimir",
247
- gridCloseRecord: "Cerrar detalles del registro",
248
+ gridCloseRecord: "Cerrar",
248
249
  gridContains: "contiene",
249
250
  gridStartsWith: "empieza por",
250
251
  gridIn: "es uno de estos valores",
@@ -689,6 +690,7 @@ const labels = Object.freeze({
689
690
  matrixItemTotal: "{item}: {count}",
690
691
  matrixExpandGroup: "Expandir {group}",
691
692
  matrixCollapseGroup: "Contraer {group}",
693
+ matrixGroupHeadingCount: "{count}",
692
694
  matrixGroupCount: "Elementos: {count}",
693
695
  matrixDetails: "Detalles",
694
696
  matrixClose: "Cerrar",
@@ -12,6 +12,7 @@ const labels = Object.freeze({
12
12
  searchWordTooShort: "Saisissez un mot d'au moins {min} caractères",
13
13
  searchFailed: "Échec de la recherche : {error}",
14
14
  columns: "Colonnes",
15
+ hiddenColumns: "[one]+{count} colonne[other]+{count} colonnes",
15
16
  gridFilters: "Filtres",
16
17
  gridFitContent: "Ajuster au contenu",
17
18
  gridUnpin: "Désépingler",
@@ -244,7 +245,7 @@ const labels = Object.freeze({
244
245
  gridExportCancelled: "Exportation annulée",
245
246
  gridCancelExport: "Annuler l'exportation",
246
247
  gridPrint: "Imprimer",
247
- gridCloseRecord: "Fermer les détails de l'enregistrement",
248
+ gridCloseRecord: "Fermer",
248
249
  gridContains: "contient",
249
250
  gridStartsWith: "commence par",
250
251
  gridIn: "est l'une des valeurs",
@@ -689,6 +690,7 @@ const labels = Object.freeze({
689
690
  matrixItemTotal: "{item} : {count}",
690
691
  matrixExpandGroup: "Développer {group}",
691
692
  matrixCollapseGroup: "Réduire {group}",
693
+ matrixGroupHeadingCount: "{count}",
692
694
  matrixGroupCount: "Éléments : {count}",
693
695
  matrixDetails: "Détails",
694
696
  matrixClose: "Fermer",
@@ -12,6 +12,7 @@ const labels = Object.freeze({
12
12
  searchWordTooShort: "Digita una parola di almeno {min} caratteri",
13
13
  searchFailed: "Ricerca non riuscita: {error}",
14
14
  columns: "Colonne",
15
+ hiddenColumns: "[one]+{count} colonna[other]+{count} colonne",
15
16
  gridFilters: "Filtri",
16
17
  gridFitContent: "Adatta al contenuto",
17
18
  gridUnpin: "Sblocca",
@@ -244,7 +245,7 @@ const labels = Object.freeze({
244
245
  gridExportCancelled: "Esportazione annullata",
245
246
  gridCancelExport: "Annulla esportazione",
246
247
  gridPrint: "Stampa",
247
- gridCloseRecord: "Chiudi i dettagli del record",
248
+ gridCloseRecord: "Chiudi",
248
249
  gridContains: "contiene",
249
250
  gridStartsWith: "inizia con",
250
251
  gridIn: "è uno tra",
@@ -689,6 +690,7 @@ const labels = Object.freeze({
689
690
  matrixItemTotal: "{item}: {count}",
690
691
  matrixExpandGroup: "Espandi {group}",
691
692
  matrixCollapseGroup: "Comprimi {group}",
693
+ matrixGroupHeadingCount: "{count}",
692
694
  matrixGroupCount: "Elementi: {count}",
693
695
  matrixDetails: "Dettagli",
694
696
  matrixClose: "Chiudi",
@@ -12,6 +12,7 @@ const labels = Object.freeze({
12
12
  searchWordTooShort: "Wpisz słowo o długości co najmniej {min} znaków",
13
13
  searchFailed: "Nie udało się wyszukać: {error}",
14
14
  columns: "Kolumny",
15
+ hiddenColumns: "[one]+{count} kolumna[few]+{count} kolumny[many]+{count} kolumn[other]+{count} kolumny",
15
16
  gridFilters: "Filtry",
16
17
  gridFitContent: "Dopasuj do zawartości",
17
18
  gridUnpin: "Odepnij",
@@ -244,7 +245,7 @@ const labels = Object.freeze({
244
245
  gridExportCancelled: "Eksport anulowany",
245
246
  gridCancelExport: "Anuluj eksport",
246
247
  gridPrint: "Drukuj",
247
- gridCloseRecord: "Zamknij szczegóły rekordu",
248
+ gridCloseRecord: "Zamknij",
248
249
  gridContains: "zawiera",
249
250
  gridStartsWith: "zaczyna się od",
250
251
  gridIn: "jest jedną z wartości",
@@ -689,6 +690,7 @@ const labels = Object.freeze({
689
690
  matrixItemTotal: "{item}: {count}",
690
691
  matrixExpandGroup: "Rozwiń {group}",
691
692
  matrixCollapseGroup: "Zwiń {group}",
693
+ matrixGroupHeadingCount: "{count}",
692
694
  matrixGroupCount: "Elementy: {count}",
693
695
  matrixDetails: "Szczegóły",
694
696
  matrixClose: "Zamknij",
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"e49f69556b65916b",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:"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)))
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))||
@@ -68,8 +68,9 @@ 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.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))}
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"));this.startLive();if(this.view.source.kind==="inline"&&this.opts.source)
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))}
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
+ if(this.view.source.kind==="inline"&&this.opts.source)
73
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))
74
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()))}
75
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();
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"a02d6881b70019b4",install(context){if(installed.has(context.MATRIX_IMPL))return;const{MATRIX_IMPL,h,setText,fill,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:"Items: {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:"b7324bd75b73b9a3",install(context){if(installed.has(context.MATRIX_IMPL))return;const{MATRIX_IMPL,h,setText,fill,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}",matrixGroupHeadingCount:"{count}",matrixGroupCount:"Items: {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)}
@@ -76,7 +76,7 @@ else if(row._index!==r)this.placeRow(row,r);this.drawRow(row,entry,columns.first
76
76
  for(const[key,row]of this.rowsMounted)if(!keep.has(key)){this.releaseRow(row);this.rowsMounted.delete(key)}
77
77
  this.syncTabStop()},newRow(){const row=h("div","cx-mx-row"),head=h("div","cx-mx-rowhead"),spacer=h("div","cx-mx-spacer"),total=h("div","cx-mx-total");row.setAttribute("role","row");head.setAttribute("role","rowheader");head.setAttribute("aria-colindex","1");total.setAttribute("role","gridcell");row.append(head,spacer,total);row._head=head;row._total=total;return row},placeRow(row,r){row._index=r;row.style.transform="translateY("+this.rowWindow.offset(r)+ "px)";row.setAttribute("aria-rowindex",String(r +(this.bandH?3:2)));row._head._r=r;row._total._r=r},fillRow(row,entry,r){row._key=entry.key;row._entry=entry;this.placeRow(row,r);row.className="cx-mx-row" +(entry.kind==="heading"?" cx-mx-heading":entry.kind==="rollup"?" cx-mx-rolledrow":entry.band?" cx-mx-member":"");const head=row._head,labels=this.labels;head.replaceChildren();head._c=-1;head.tabIndex=-1;if(entry.kind==="item"){const item=entry.item,text=item.href?h("a","cx-mx-label cx-link"):h("span","cx-mx-label");if(item.href){text.href=item.href;text.tabIndex=-1}
78
78
  setText(text,item.label);head.appendChild(text);if(item.secondary){const sub=h("span","cx-mx-sub");setText(sub,item.secondary);head.appendChild(sub)}
79
- head.title=item.secondary?item.label+" — "+item.secondary:item.label}else{const toggle=h("button","cx-mx-toggle"),open=entry.kind==="heading";toggle.type="button";toggle.tabIndex=-1;toggle.setAttribute("aria-expanded",String(open));toggle.setAttribute("aria-label",fill(open?labels.matrixCollapseGroup:labels.matrixExpandGroup,{group:entry.label}));toggle._group={axis:"rows",key:entry.group.key};const label=h("span","cx-mx-label"),count=h("span","cx-mx-sub");setText(label,entry.label);setText(count,fill(labels.matrixGroupCount,{count:this.format.format(entry.members.length)}));toggle.append(label,count);head.appendChild(toggle);head.removeAttribute("title")}
79
+ head.title=item.secondary?item.label+" — "+item.secondary:item.label}else{const toggle=h("button","cx-mx-toggle"),open=entry.kind==="heading";toggle.type="button";toggle.tabIndex=-1;toggle.setAttribute("aria-expanded",String(open));toggle.setAttribute("aria-label",fill(open?labels.matrixCollapseGroup:labels.matrixExpandGroup,{group:entry.label}));toggle._group={axis:"rows",key:entry.group.key};const label=h("span","cx-mx-label"),count=h("span","cx-mx-sub");setText(label,entry.label);setText(count,fill(labels.matrixGroupHeadingCount,{count:this.format.format(entry.members.length)}));toggle.append(label,count);head.appendChild(toggle);head.removeAttribute("title")}
80
80
  const total=row._total;total.hidden=!this.totalW;if(this.totalW)this.paintTotal(total,entry,r,this.model.columns.length)},paintTotal(element,entry,r,c){const value=entry.total||0;setText(element,this.format.format(value));element.classList.toggle("cx-mx-zero",!value);element.setAttribute("aria-label",fill(this.labels.matrixItemTotal,{item:entry.label,count:this.format.format(value)}));element._r=r;element._c=c;element.tabIndex=-1;element.setAttribute("aria-colindex",String(this.model.columns.length+2))},paintHeader(columnList){const wanted=new Set(columnList),mounted=this.headMounted,model=this.model;for(const[c,element]of mounted)if(!wanted.has(c)||element._key!==model.columns[c]?.key){element.remove();mounted.delete(c)}
81
81
  for(const c of columnList){const entry=model.columns[c];if(!entry||mounted.has(c))continue;const element=h("div","cx-mx-hcell" +(entry.kind==="rollup"?" cx-mx-rolledcol":""));element.setAttribute("role","columnheader");element.setAttribute("aria-colindex",String(c+2));element.style.insetInlineStart=this.rowHeadW+this.columnWindow.offset(c)+ "px";element._r=-1;element._c=c;element._key=entry.key;element.tabIndex=-1;if(entry.kind==="rollup"){const toggle=h("button","cx-mx-toggle");toggle.type="button";toggle.tabIndex=-1;toggle.setAttribute("aria-expanded","false");toggle.setAttribute("aria-label",fill(this.labels.matrixExpandGroup,{group:entry.label}));toggle._group={axis:"columns",key:entry.group.key};const text=h("span","cx-mx-vlabel");setText(text,entry.label);toggle.appendChild(text);element.appendChild(toggle)}else{const item=entry.item,text=h(item.href?"a":"span","cx-mx-vlabel" +(item.href?" cx-link":""));if(item.href){text.href=item.href;text.tabIndex=-1}
82
82
  setText(text,item.label);element.appendChild(text);element.title=item.secondary?item.label+" — "+item.secondary:item.label}
@@ -85,7 +85,7 @@ for(const[key,element]of mounted)if(!seen.has(key)){element.remove();mounted.del
85
85
  for(const c of columnList){const entry=model.columns[c];if(!entry||mounted.has(c))continue;const element=h("div","cx-mx-fcell");element.setAttribute("role","gridcell");element.style.insetInlineStart=this.rowHeadW+this.columnWindow.offset(c)+ "px";this.paintTotal(element,entry,model.rows.length,c);element.setAttribute("aria-colindex",String(c+2));element._key=entry.key;mounted.set(c,element);this.footRow.appendChild(element)}
86
86
  if(this.totalW)this.paintTotal(this.footGrand,{label:this.labels.matrixTotal,total:model.grandTotal},model.rows.length,model.columns.length);this.footHeader._r=model.rows.length;this.footHeader._c=-1}});const MATRIX_PATHS=new Map(),MATRIX_TILE=16;function matrixPath(name){if(!MATRIX_PATHS.has(name))MATRIX_PATHS.set(name,name==="dot"?null:new Path2D(MATRIX_SYMBOL_PATHS[name]));return MATRIX_PATHS.get(name)}
87
87
  Object.assign(MatrixView.prototype,{looks(){if(this.lookCache&&this.lookCache.doc===this.doc)return this.lookCache.items;const items=new Map(),probe=h("span","cx-mx-cell"),forced=global.matchMedia?.("(forced-colors: active)").matches;probe.style.display="none";this.root.appendChild(probe);const read=(cls,tone)=>{probe.className=cls;toneColors(probe,tone);const style=getComputedStyle(probe),fill=style.backgroundColor;return{ink:style.color,fill:/rgba\(\d+, \d+, \d+, 0\)|transparent/.test(fill) ? null : fill, font: style.fontWeight + " " + style.fontSize + " " + style.fontFamily };
88
- };this.doc.states.forEach((state,index)=>{const tone=toneOf(state.tone),look=read("cx-mx-cell" +(state.attention?" cx-mx-attn":"")+ tone.cls,tone);items.set(index,Object.assign(look,{symbol:state.symbol,name:state.label,attention:state.attention,forced}))});items.set(MATRIX_NONE,Object.assign(read("cx-mx-cell cx-mx-none",toneOf(null)),{symbol:null,name:this.labels.matrixNoData,none:true}));items.set(MATRIX_SELF,Object.assign(read("cx-mx-cell cx-mx-self",toneOf(null)),{symbol:null,name:this.labels.matrixSelf,self:true}));probe.className="cx-mx-gridline";this.lineColor=getComputedStyle(probe).color;probe.remove();this.lookCache={doc:this.doc,items};this.cellName=matrixTemplate(this.labels.matrixCell);this.canvasVersion=(this.canvasVersion||0)+ 1;return items},drawRow(row,entry,first,last){const ratio=global.devicePixelRatio||1,tiles=row._tiles||=new Map(),version=this.canvasVersion+":"+ratio+":"+entry.key;this.looks();const from=last>=first?Math.floor(first / MATRIX_TILE) : 0, to = last >= first ? Math.floor(last / MATRIX_TILE) : -1;
88
+ };this.doc.states.forEach((state,index)=>{const tone=toneOf(state.tone),look=read("cx-mx-cell" +(state.attention?" cx-mx-attn":"")+ tone.cls,tone);items.set(index,Object.assign(look,{symbol:state.symbol,name:state.label,attention:state.attention,forced}))});items.set(MATRIX_NONE,Object.assign(read("cx-mx-cell cx-mx-none",toneOf(null)),{symbol:null,name:this.labels.matrixNoData,none:true}));items.set(MATRIX_SELF,Object.assign(read("cx-mx-cell cx-mx-self",toneOf(null)),{symbol:null,name:this.labels.matrixSelf,self:true}));probe.className="cx-mx-gridline";this.lineColor=getComputedStyle(probe).color;probe.remove();this.lookCache={doc:this.doc,items};this.cellName=matrixTemplate(this.labels.matrixCell);this.canvasVersion=(this.canvasVersion||0)+ 1;return items},drawRow(row,entry,first,last){this.looks();const ratio=global.devicePixelRatio||1,tiles=row._tiles||=new Map(),version=this.canvasVersion+":"+ratio+":"+entry.key;const from=last>=first?Math.floor(first / MATRIX_TILE) : 0, to = last >= first ? Math.floor(last / MATRIX_TILE) : -1;
89
89
  for(const[index,tile]of tiles)if(index<from||index>to){tiles.delete(index);tile.remove();if(this.tilePool.length<400)this.tilePool.push(tile)}
90
90
  for(let index=from;index<=to;index++){let tile=tiles.get(index);if(!tile){tile=this.tilePool.pop();if(!tile){tile=h("canvas","cx-mx-canvas");tile.setAttribute("aria-hidden","true")}
91
91
  tile._drawn=null;tiles.set(index,tile);row.insertBefore(tile,row._total)}
@@ -62,7 +62,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
62
62
  const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
63
63
  let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
64
64
  return forms[rules.select(Number(count))]??forms.other??template}
65
- let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
65
+ let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
66
66
  if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
67
67
  if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
68
68
  return Object.freeze(labels)}
@@ -76,7 +76,7 @@ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.
76
76
  catch(_){trustPolicy=null}}
77
77
  return trustPolicy?trustPolicy["create"+kind](value):value}
78
78
  function hostHtml(element,html,sanitize,kind){const text=String(html??""),value=sanitize?sanitize(text,{kind}):text;if(value?.nodeType)element.replaceChildren(value);else if(typeof value==="string")element.innerHTML=trusted("HTML",value);else if(global.trustedTypes?.isHTML?.(value))element.innerHTML=value;else throw new Error("CanopyX: invalid sanitizeHtml result.")}
79
- DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridMore:"More",gridPrint:"Print",gridDetails:"Record details",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close record details"}));DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{recordBack:"Back",recordBackTo:"Back to {record}",recordTrail:"Record trail",recordShowing:"Showing {record}",recordTabs:"Record views",recordSections:"Jump to a section",recordOtherFields:"Other fields",recordShowEmpty:"Show empty fields ({count})",recordHideEmpty:"Hide empty fields",recordActions:"Record actions",recordCopyValues:"Copy values",recordCopyJson:"Copy as JSON",recordCopyLink:"Copy link",recordCopied:"Copied to the clipboard",recordPrint:"Print record",recordExportCsv:"Export CSV",recordExportJson:"Export JSON",recordOpenAll:"Open all in grid",recordLoadMore:"Load more",recordCount:"{shown} of {total}",recordItems:"{count} items",recordMore:"+{count}",recordShowAll:"Show all {count}",recordRetry:"Retry",recordLoadFailed:"Could not load the record details: {error}",recordUnavailable:"Record {id} is not available here.",recordField:"Field",recordValue:"Value",recordSection:"Section",recordBefore:"Before",recordAfter:"After",recordAdded:"Added",recordRemoved:"Removed",recordChanged:"{count} changed fields"}));function boundedPattern(source,exact=true,whole=false){const bad=()=>{throw new Error("CanopyX: pattern requires literals, character classes and at most one variable repetition anchored at the start; groups, alternatives and backreferences are unsupported.")};if(typeof source!=="string"||source.length>256)bad();let width=0,variable=0;for(let i=0;i<source.length;){const unit=source[i++];if(unit==="^"&&i===1||unit==="$"&&i===source.length)continue;if(unit==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbBnrtfv\\.^$*+?{}\[\]()|/]$/.test(escape)) bad();
79
+ DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridMore:"More",gridPrint:"Print",gridDetails:"Record details",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close"}));DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{recordBack:"Back",recordBackTo:"Back to {record}",recordTrail:"Record trail",recordShowing:"Showing {record}",recordTabs:"Record views",recordSections:"Jump to a section",recordOtherFields:"Other fields",recordShowEmpty:"Show empty fields ({count})",recordHideEmpty:"Hide empty fields",recordActions:"Record actions",recordCopyValues:"Copy values",recordCopyJson:"Copy as JSON",recordCopyLink:"Copy link",recordCopied:"Copied to the clipboard",recordPrint:"Print record",recordExportCsv:"Export CSV",recordExportJson:"Export JSON",recordOpenAll:"Open all in grid",recordLoadMore:"Load more",recordCount:"{shown} of {total}",recordItems:"{count} items",recordMore:"+{count}",recordShowAll:"Show all {count}",recordRetry:"Retry",recordLoadFailed:"Could not load the record details: {error}",recordUnavailable:"Record {id} is not available here.",recordField:"Field",recordValue:"Value",recordSection:"Section",recordBefore:"Before",recordAfter:"After",recordAdded:"Added",recordRemoved:"Removed",recordChanged:"{count} changed fields"}));function boundedPattern(source,exact=true,whole=false){const bad=()=>{throw new Error("CanopyX: pattern requires literals, character classes and at most one variable repetition anchored at the start; groups, alternatives and backreferences are unsupported.")};if(typeof source!=="string"||source.length>256)bad();let width=0,variable=0;for(let i=0;i<source.length;){const unit=source[i++];if(unit==="^"&&i===1||unit==="$"&&i===source.length)continue;if(unit==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbBnrtfv\\.^$*+?{}\[\]()|/]$/.test(escape)) bad();
80
80
  }else if(unit==="["){let closed=false;while(i<source.length){const c=source[i++];if(c==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbnrtfv\\.^$*+?{}\[\]()|/-]$/.test(escape)) bad(); }
81
81
  else if(c==="]"){closed=true;break}}
82
82
  if(!closed)bad()}else if("()|^$*+?{}]".includes(unit))bad();let count=1;if(i<source.length&&"*+?".includes(source[i])){variable++;i++}
@@ -336,7 +336,7 @@ function hostRenderers(renderers,columns,plugins){if(![Object.prototype,null].in
336
336
  Object.keys(renderers).some(id=>typeof renderers[id]!=="function"||!columns.some(column=>column.id===id)))
337
337
  throw new Error("CanopyX: invalid column renderers.");const named=Object.assign(Object.create(null),...plugins.map(item=>item.cellRenderers));return Object.assign(Object.create(null),...columns.filter(column=>typeof column.renderer==="string"&&named[column.renderer])
338
338
  .map(column=>({[column.id]:named[column.renderer]})),renderers)}
339
- function disposeHostSlot(slot){const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
339
+ function disposeHostSlot(slot){slot.childSlots?.forEach(disposeHostSlot);const lifetime=slot.hostLifetime;if(!lifetime)return;delete slot.hostLifetime;lifetime.dispose()}
340
340
  function disposeRowHostCells(row){row._cells?.forEach(disposeHostSlot)}
341
341
  class HostCellContext{#controller;#cleanups;constructor(slot,column,level,expanded,index){slot.hostLifetime=this;this.column=column;this.level=level;this.expanded=expanded;this.index=index}
342
342
  get signal(){this.#controller||=new AbortController();if(this.#cleanups===null)this.#controller.abort();return this.#controller.signal}
@@ -506,7 +506,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
506
506
  active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
507
507
  close()}else{return}
508
508
  e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
509
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["1e7e68d65a0c7aeb","canopyx-tree-tools.6f6db0b476335e64.js","canopyx-tree-tools.ef7a3fb9c9115a82.css"],"export":["8b99c0b7b0ec37c5","canopyx-export.6989ea36f5d6da7b.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
509
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["4c6c4101089c4444","canopyx-tree-tools.510207e8f47014fd.js","canopyx-tree-tools.ef7a3fb9c9115a82.css"],"export":["8b99c0b7b0ec37c5","canopyx-export.6989ea36f5d6da7b.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
510
510
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
511
511
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
512
512
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}