@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
@@ -24,14 +24,15 @@ function checkPage(doc,node){checkDocument(doc,"page");if(!Array.isArray(doc.ite
24
24
  if(!Object.hasOwn(doc,"next"))throw new Error("CanopyX: page continuation is required.");if(doc.next!==null)requireIdentifier(doc.next,"page continuation");const parent=node?node.id:null;if(doc.parent!==parent)throw new Error("CanopyX: page parent does not match the requested node.");return doc}
25
25
  function isCellObject(cell){return cell!==null&&typeof cell==="object"}
26
26
  function cellValue(cell){return isCellObject(cell)?(cell.value===undefined?null:cell.value):(cell===undefined?null:cell)}
27
- const NO_TONE={cls:"",host:null};const tones=new Map();function toneOf(name){let tone=typeof name==="string"?tones.get(name):NO_TONE;if(!tone){if(!/^[a-z][a-z0-9-]{0,31}$/.test(name) || name.endsWith("-bg")) {
27
+ const NO_TONE={cls:"",host:null};const tones=new Map();function toneVariable(name,background=false,fallback){const role={success:"good",warning:"warn",danger:"bad"}[name]||name;const key="--hfx-color-status-"+role +(background?"-bg":"-fg");return "var("+key +(STATUS_FALLBACKS[key]||fallback?"," +(STATUS_FALLBACKS[key]||fallback):"")+ ")"}
28
+ function toneOf(name){let tone=typeof name==="string"?tones.get(name):NO_TONE;if(!tone){if(!/^[a-z][a-z0-9-]{0,31}$/.test(name) || name.endsWith("-bg")) {
28
29
  return NO_TONE}
29
30
  const host=!/^(neutral|info|success|warning|danger|muted)$/.test(name);
30
31
  tone={cls:" cx-tone-"+name +(host?" cx-toned":""),host:host?name:null};if(tones.size<256)tones.set(name,tone)}
31
32
  return tone}
32
33
  function applyTone(element,base,tone){element.className=base+tone.cls;toneColors(element,tone)}
33
34
  function toneColors(element,tone){if((element._tone||null)===tone.host){return}
34
- element._tone=tone.host;if(tone.host){element.style.setProperty("--cx-t","var(--cx-tone-"+tone.host+")");element.style.setProperty("--cx-t-bg","var(--cx-tone-"+tone.host+"-bg)")}else{element.style.removeProperty("--cx-t");element.style.removeProperty("--cx-t-bg")}}
35
+ element._tone=tone.host;if(tone.host){element.style.setProperty("--cx-t",toneVariable(tone.host));element.style.setProperty("--cx-t-bg",toneVariable(tone.host,true))}else{element.style.removeProperty("--cx-t");element.style.removeProperty("--cx-t-bg")}}
35
36
  function pad2(value){return value<10?"0"+value:String(value)}
36
37
  const dateTexts=new Map();function dateText(value){let texts=dateTexts.get(value);if(texts===undefined){const time=Date.parse(value);const d=new Date(time);texts=isNaN(time)?null:[String(d.getUTCFullYear()).padStart(4,"0")+ "-"+pad2(d.getUTCMonth()+ 1)+ "-"+pad2(d.getUTCDate())+ " "+pad2(d.getUTCHours())+ ":"+pad2(d.getUTCMinutes()),String(d.getFullYear()).padStart(4,"0")+ "-"+pad2(d.getMonth()+ 1)+ "-"+pad2(d.getDate())+ " "+pad2(d.getHours())+ ":"+pad2(d.getMinutes())];if(dateTexts.size>=DATE_CACHE)dateTexts.clear();dateTexts.set(value,texts)}
37
38
  return texts}
@@ -88,6 +89,12 @@ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.
88
89
  catch(_){trustPolicy=null}}
89
90
  return trustPolicy?trustPolicy["create"+kind](value):value}
90
91
  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.")}
92
+ const STATUS_FALLBACKS={"--hfx-color-status-bad-bg":"light-dark(#f9e4e4,#3c272a)","--hfx-color-status-bad-fg":"light-dark(#b8292a,#f47171)","--hfx-color-status-good-bg":"light-dark(#e2f0e9,#1f362f)","--hfx-color-status-good-fg":"light-dark(#177345,#4cc78a)","--hfx-color-status-info-bg":"light-dark(#e4ecfa,#262f41)","--hfx-color-status-info-fg":"light-dark(#2b5fc0,#74a2f7)","--hfx-color-status-neutral-bg":"light-dark(#eeeff0,#2a2c31)","--hfx-color-status-neutral-fg":"light-dark(#5b6069,#a0a5ae)","--hfx-color-status-warn-bg":"light-dark(#f8efde,#3b3322)","--hfx-color-status-warn-fg":"light-dark(#8c5c05,#eeb640)"};const MODE_ATTRIBUTES=["data-theme","data-cx-theme","data-hfx-mode","data-bs-theme","data-hfx-theme","data-hfx-tokens"];const THEME_ATTRIBUTES=[...MODE_ATTRIBUTES,"data-hfx-style","data-hfx-density","data-cx-fallback-mode","style","class"];function watchTheme(host,signal){const attributes=THEME_ATTRIBUTES;const previous=host.getAttribute("data-cx-fallback-mode");const refresh=()=>{const parent=host.parentElement&&getComputedStyle(host.parentElement);const inherited=parent?.colorScheme;let mode=null;if(!parent?.getPropertyValue("--hfx-color-surface").trim()){outer:for(let owner=host;owner;owner=owner.parentElement)for(const attribute of MODE_ATTRIBUTES){const value=owner.getAttribute(attribute);if(value==="light"||value==="dark"){mode=value;break outer}}}
93
+ if(parent?.getPropertyValue("--hfx-color-surface").trim()||!mode&&inherited&&inherited!=="normal"){if(host.hasAttribute("data-cx-fallback-mode"))host.removeAttribute("data-cx-fallback-mode")}else if(host.getAttribute("data-cx-fallback-mode")!==(mode||"auto"))host.setAttribute("data-cx-fallback-mode",mode||"auto")};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:attributes});refresh();const dispose=()=>{observer.disconnect();if(previous===null)host.removeAttribute("data-cx-fallback-mode");else host.setAttribute("data-cx-fallback-mode",previous)};signal?.addEventListener("abort",dispose,{once:true});return dispose}
94
+ function overlayTheme(host,element,inherit=false){for(const name of["data-hfx-style","data-hfx-mode","data-hfx-density"]){const owner=host.closest("["+name+"]");if(owner&&!inherit)element.setAttribute(name,owner.getAttribute(name));else element.removeAttribute(name)}
95
+ const theme=getComputedStyle(host),parent=inherit&&host.parentElement&&getComputedStyle(host.parentElement);element.style.colorScheme=theme.colorScheme;const copied=[];for(const name of theme)if((name.startsWith("--cx-")||name.startsWith("--hfx-"))&&(!parent||theme.getPropertyValue(name)!==parent.getPropertyValue(name))){element.style.setProperty(name,theme.getPropertyValue(name));copied.push(name)}
96
+ return copied}
97
+ function watchOverlayTheme(host,element,signal){if(signal?.aborted)return()=>{};let copied=[];const refresh=()=>{for(const name of copied)element.style.removeProperty(name);copied=overlayTheme(host,element,element.parentElement===host.parentElement)};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:THEME_ATTRIBUTES});const media=["(prefers-color-scheme:dark)","(prefers-contrast:more)","(forced-colors:active)"].map(query=>matchMedia(query));for(const query of media)query.addEventListener("change",refresh);const dispose=()=>{observer.disconnect();for(const query of media)query.removeEventListener("change",refresh);signal?.removeEventListener("abort",dispose)};signal?.addEventListener("abort",dispose,{once:true});dispose.refresh=refresh;refresh();return dispose}
91
98
  DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"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();
92
99
  }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(); }
93
100
  else if(c==="]"){closed=true;break}}
@@ -204,7 +211,7 @@ throw new Error("CanopyX: unknown source kind '"+kind+"'.")}
204
211
  async function remoteJson(url,type,timeoutMs,lifetime,signal){const controller=new AbortController();const signals=Array.from(new Set([lifetime,signal].filter(Boolean)));const abort=()=>controller.abort();signals.forEach((item)=>{if(item.aborted)abort();else item.addEventListener("abort",abort,{once:true})});let timedOut=false;const timer=setTimeout(()=>{timedOut=true;abort()},timeoutMs);try{const response=await fetch(url,{headers:{Accept:"application/json"},signal:controller.signal});if(!response.ok){if(response.body)await response.body.cancel().catch(()=>{});throw new Error(response.status+" "+response.statusText)}
205
212
  return checkDocument(await response.json(),type)}catch(error){if(timedOut)throw new Error("CanopyX: remote request timed out after "+timeoutMs+" milliseconds.");throw error}finally{abort();clearTimeout(timer);signals.forEach((item)=>item.removeEventListener("abort",abort))}}
206
213
  class TreeGrid{constructor(host,options){const view=checkDocument(options.view,"view");requireIdentifier(view.id,"view ID");if(view.columns.some(column=>column.format!==undefined))throw new Error("CanopyX: number formats apply to flat grids only.");this.host=host;this.view=view;this.opts=options;for(const name of["isSelectable","beforeSelect","sanitizeHtml"]){if(options[name]!==undefined&&typeof options[name]!=="function")throw new Error("CanopyX: "+name+" must be a function.")}
207
- this.id="cx" + ++instanceSeq;this.lifetime=new AbortController();this.source=options.source||sourceFor(view,{signal:this.lifetime.signal,timeoutMs:options.requestTimeoutMs});this.queryAware=this.source.queryAware===true;this.dataLifetime=new AbortController();this.acceptedQuery=Object.freeze({version:1,sort:null,filters:Object.freeze([])});this.datasetRevision=null;this.rowH=view.rowHeight||28;this.pageSize=view.pageSize||100;this.retainedNodeLimit=options.retainedNodeLimit===undefined?1024:options.retainedNodeLimit;if(!validStructuralCount(this.retainedNodeLimit))throw new Error("CanopyX: retainedNodeLimit must be a nonnegative 32-bit integer.");this.inactiveNodeLimit=options.inactiveNodeLimit===undefined?4096:options.inactiveNodeLimit;if(!validStructuralCount(this.inactiveNodeLimit))throw new Error("CanopyX: inactiveNodeLimit must be a nonnegative 32-bit integer.");this.multi=view.selection==="multiple";this.lang=document.documentElement.lang||undefined;this.labels=labelsFor(view.labels,options.labels);this.tools=Object.assign({},view.toolbar,options.toolbar);if(Object.entries(this.tools).some(([name,value])=>!/^(search|filters|columns|views|export|more|matches|layout)$/.test(name) || typeof value !== "boolean"))
214
+ this.id="cx" + ++instanceSeq;this.lifetime=new AbortController();this.source=options.source||sourceFor(view,{signal:this.lifetime.signal,timeoutMs:options.requestTimeoutMs});this.queryAware=this.source.queryAware===true;this.dataLifetime=new AbortController();this.acceptedQuery=Object.freeze({version:1,sort:null,filters:Object.freeze([])});this.datasetRevision=null;this.rowH=view.rowHeight||40;this.pageSize=view.pageSize||100;this.retainedNodeLimit=options.retainedNodeLimit===undefined?1024:options.retainedNodeLimit;if(!validStructuralCount(this.retainedNodeLimit))throw new Error("CanopyX: retainedNodeLimit must be a nonnegative 32-bit integer.");this.inactiveNodeLimit=options.inactiveNodeLimit===undefined?4096:options.inactiveNodeLimit;if(!validStructuralCount(this.inactiveNodeLimit))throw new Error("CanopyX: inactiveNodeLimit must be a nonnegative 32-bit integer.");this.multi=view.selection==="multiple";this.lang=document.documentElement.lang||undefined;this.labels=labelsFor(view.labels,options.labels);this.tools=Object.assign({},view.toolbar,options.toolbar);if(Object.entries(this.tools).some(([name,value])=>!/^(search|filters|columns|views|export|more|matches|layout)$/.test(name) || typeof value !== "boolean"))
208
215
  throw new Error("CanopyX: toolbar options are booleans by control name.");this.local=view.timeZone==="local";this.fmt=formatting(this.lang,this.local,this.labels);this.kind="tree";this.plugins=viewPlugins(options,this.kind);const renderers=hostRenderers(options.renderers||{},view.columns,this.plugins);if(!options.formatLink!==!options.parseLink){throw new Error("CanopyX: formatLink and parseLink define one link scheme and are given together.")}
209
216
  this.columns=view.columns.map((column,index)=>({...column,hidden:index>0&&!!column.hidden,render:Object.hasOwn(renderers,column.id)?renderers[column.id]:null}));this.columns.forEach(prepareWidth);this.columns.forEach(validateColumnValues);this.keyMap=new Map();this.root={key:null,h:null,parent:null,level:0,idx:0,expanded:true,children:null,total:null,next:null,loading:false,error:null};if(!options.source&&(!view.source||view.source.kind==="inline")){this.root.inlineItems=view.roots||[]}
210
217
  this.rows=[];this.tops=[0];this.total=0;this.version=1;this.rendered=new Map();this.pool=[];this.focused=null;this.selected=new Set();this.anchor=null;this.filter=null;this.declaredFilter=null;this.filterExpand=false;this.activeFilters=new Set();this.sortState=null;this.typeBuf="";this.typeAt=0;this.rafId=0;this.iconTemplates=this.buildIcons(view.icons||{});this.initializing=true;this.prepareViewModes();this.build();this.buildToolbar();if(view.deepLink)loadPart(LINKS).catch(()=>{});this.ready=this.modesReady?Promise.all([this.init(),this.modesReady]).then(([result])=>result):this.init()}
@@ -271,8 +278,7 @@ value.sort===undefined||typeof value!=="object")throw new Error("CanopyX: query
271
278
  const named=new Set(value.filters);if(named.size!==value.filters.length||value.filters.some(id=>!(grid.view.filters||[]).some(f=>f.id===id)))
272
279
  throw new Error("CanopyX: query filters must be unique declared IDs.");const filters=Object.freeze((grid.view.filters||[]).filter(f=>named.has(f.id)).map(f=>f.id));return Object.freeze({version:1,sort,filters})}
273
280
  function snapshotRevision(value,expected){requireIdentifier(value&&value.revision,"dataset revision");if(expected!=null&&value.revision!==expected)throw new Error("CanopyX: dataset revision changed; reload the roots before continuing.");return value.revision}
274
- Object.assign(TreeGrid.prototype,{getQuery(){return{version:1,sort:this.sortState&&Object.assign({},this.sortState),filters:Array.from(this.activeFilters)}},sourceRequest(signal){return this.queryAware?{signal:signal||this.dataLifetime.signal,query:this.acceptedQuery,revision:this.datasetRevision}:{signal}},syncQueryControls(){this.toolbar.querySelectorAll("[data-cx-filter]").forEach(input=>{input.checked=this.activeFilters.has(input.getAttribute("data-cx-filter"))})},querySortHeader(id){const query=this.pendingQuery||this.acceptedQuery,state=query.sort&&query.sort.column===id?query.sort.direction:null;this.sort(id,state==="asc"?"desc":state==="desc"?null:"asc").catch(()=>{})}});Object.assign(TreeGrid.prototype,{retireWrapper(w){w._invalidated=true;this.retirePage(w);if(this.inlineRetained&&this.inlineRetained.get(w.key)===w)this.inlineRetained.delete(w.key);if(this.inactiveCache)this.inactiveCache.delete(w);if(this.keyMap.get(w.key)===w)this.keyMap.delete(w.key);w.children=null;w.inlineCache=null;w.inlineOrder=null;const selected=this.selected.delete(w);if(this.anchor===w)this.anchor=null;return selected?w:null}});Object.assign(TreeGrid.prototype,{build(){const host=this.host;host.classList.add("cx-host");if(!host.hasAttribute("data-cx-theme")){host.setAttribute("data-cx-theme","auto")}
275
- host.style.setProperty("--cx-row-h",this.rowH+"px");this.setTreeColumnPinned(this.view.pinTreeColumn);this.toolbar=h("div","cx-toolbar");this.toolbar.hidden=true;const grid=this.grid=h("div","cx-grid");grid.id=this.id;grid.setAttribute("role","treegrid");grid.setAttribute("aria-label",this.view.label);if(this.multi){grid.setAttribute("aria-multiselectable","true")}
281
+ Object.assign(TreeGrid.prototype,{getQuery(){return{version:1,sort:this.sortState&&Object.assign({},this.sortState),filters:Array.from(this.activeFilters)}},sourceRequest(signal){return this.queryAware?{signal:signal||this.dataLifetime.signal,query:this.acceptedQuery,revision:this.datasetRevision}:{signal}},syncQueryControls(){this.toolbar.querySelectorAll("[data-cx-filter]").forEach(input=>{input.checked=this.activeFilters.has(input.getAttribute("data-cx-filter"))})},querySortHeader(id){const query=this.pendingQuery||this.acceptedQuery,state=query.sort&&query.sort.column===id?query.sort.direction:null;this.sort(id,state==="asc"?"desc":state==="desc"?null:"asc").catch(()=>{})}});Object.assign(TreeGrid.prototype,{retireWrapper(w){w._invalidated=true;this.retirePage(w);if(this.inlineRetained&&this.inlineRetained.get(w.key)===w)this.inlineRetained.delete(w.key);if(this.inactiveCache)this.inactiveCache.delete(w);if(this.keyMap.get(w.key)===w)this.keyMap.delete(w.key);w.children=null;w.inlineCache=null;w.inlineOrder=null;const selected=this.selected.delete(w);if(this.anchor===w)this.anchor=null;return selected?w:null}});Object.assign(TreeGrid.prototype,{build(){const host=this.host;host.classList.add("cx-host");watchTheme(host,this.lifetime.signal);host.style.setProperty("--cx-row-h",this.rowH+"px");this.setTreeColumnPinned(this.view.pinTreeColumn);this.toolbar=h("div","cx-toolbar");this.toolbar.hidden=true;const grid=this.grid=h("div","cx-grid");grid.id=this.id;grid.setAttribute("role","treegrid");grid.setAttribute("aria-label",this.view.label);if(this.multi){grid.setAttribute("aria-multiselectable","true")}
276
282
  this.head=h("div","cx-head");this.head.setAttribute("role","rowgroup");this.headRow=h("div","cx-hrow");this.headRow.setAttribute("role","row");this.headRow.setAttribute("aria-rowindex","1");this.head.appendChild(this.headRow);this.canvas=h("div","cx-canvas");this.canvas.setAttribute("role","rowgroup");grid.appendChild(this.head);grid.appendChild(this.canvas);this.live=h("div","cx-live cx-sr-only");this.live.setAttribute("aria-live","polite");this.outline=h("div","cx-outline");host.appendChild(this.toolbar);host.appendChild(grid);host.appendChild(this.live);host.appendChild(this.outline);this.buildHeader();this.onScroll=()=>{this.scheduleRender();this.stateChanged()};this.onPrint=()=>{const table=this.outlineElement();this.outline.replaceChildren(...table?[table]:[])};grid.addEventListener("scroll",this.onScroll,{passive:true});grid.addEventListener("click",(e)=>this.onClick(e));grid.addEventListener("dblclick",(e)=>this.onDblClick(e));grid.addEventListener("pointerover",(e)=>this.cellTip(e));grid.addEventListener("keydown",(e)=>this.onKey(e));this.canvas.addEventListener("focusin",(e)=>{const rowEl=e.target.closest(".cx-row");if(rowEl&&rowEl._w&&this.focused!==rowEl._w){this.focusRevision=(this.focusRevision||0)+ 1;this.focused=rowEl._w;this.scheduleRender()}});this.canvas.addEventListener("focusout",(e)=>this.settleCell(e.relatedTarget));global.addEventListener("beforeprint",this.onPrint);this.onHash=(e)=>{const href=global.location.href;const last=this.locationEvent;this.locationEvent=last&&last.href===href&&last.type!==e.type?null:{href,type:e.type};if(this.locationEvent)this.readLocation()};global.addEventListener("hashchange",this.onHash);global.addEventListener("popstate",this.onHash);const viewWidth=()=>{if(grid.clientWidth)host.style.setProperty("--cx-view-w",grid.clientWidth+"px")};viewWidth();this.resizeObserver=new ResizeObserver(()=>{viewWidth();this.scheduleRender()});this.resizeObserver.observe(grid)},visibleColumns(){return this.columns.filter((column)=>!column.hidden)},buildHeader(){const active=document.activeElement;const focusedColumn=active&&this.headRow.contains(active)?active.closest(".cx-hcell").getAttribute("data-cx-column"):null;const focusedResize=active&&active.classList.contains("cx-resize");const nextCols=this.visibleColumns();const layoutChanged=!this.cols||this.cols.length!==nextCols.length||nextCols.some((column,i)=>column!==this.cols[i]);this.cols=nextCols;this.columnIndex=this.cols.map((column)=>this.columns.indexOf(column));if(layoutChanged){this.layout=(this.layout||0)+ 1;this.version++}
277
283
  this.grid.setAttribute("aria-colcount",String(this.cols.length));this.headRow.textContent="";this.headCells=this.cols.map((column,i)=>{const cell=h("div","cx-hcell cx-kind-" +(column.kind||"text"));cell.setAttribute("role","columnheader");cell.setAttribute("aria-label",column.title);if(column.headerDescription)cell.setAttribute("aria-description",column.headerDescription);cell.title=column.headerDescription??column.title;cell.setAttribute("data-cx-column",column.id);cell.setAttribute("aria-colindex",String(i+1));if(column.sortable){const sorted=this.sortState&&this.sortState.column===column.id?this.sortState.direction:null;cell.setAttribute("aria-sort",sorted==="asc"?"ascending":sorted==="desc"?"descending":"none");const button=h("button","cx-sort");button.type="button";button.title=column.headerDescription??column.title;setText(button,column.title);button.addEventListener("click",(event)=>this.queryAware?this.querySortHeader(column.id,event):this.sort(column.id,sorted==="asc"?"desc":sorted==="desc"?null:"asc"));cell.appendChild(button)}else{const title=h("span","cx-htext");title.title=column.headerDescription??column.title;setText(title,column.title);cell.appendChild(title)}
278
284
  const grip=h("span","cx-resize");grip.setAttribute("aria-label",fill(this.labels.resizeColumn,{column:column.title}));grip.tabIndex=0;grip.setAttribute("role","separator");grip.setAttribute("aria-orientation","vertical");grip.setAttribute("aria-valuemin",column.minW);grip.setAttribute("aria-valuemax",column.maxW);grip.addEventListener("keydown",(e)=>{if(!["ArrowLeft","ArrowRight","Home"].includes(e.key))return;e.preventDefault();e.stopPropagation();column.width=columnWidth(column,e.key==="Home"?40:column.width +(e.key==="ArrowLeft"?-1:1)*(e.shiftKey?50:10));this.applyWidths();this.stateChanged()});grip.addEventListener("pointerdown",(e)=>this.startResize(e,column));cell.appendChild(grip);this.headRow.appendChild(cell);return cell});this.applyWidths();if(focusedColumn){const index=this.cols.findIndex((c)=>c.id===focusedColumn);const button=index>=0?this.headCells[index].querySelector(focusedResize?".cx-resize":".cx-sort"):null;if(button){button.focus()}}},rowCount(){return this.rows.length},rowItem(index){return this.rows[index]},rowTop(index){return this.tops[index]},rowAt(y){const tops=this.tops;let lo=0;let hi=this.rows.length-1;while(lo<hi){const mid=(lo+hi+1)>>1;if(tops[mid]<=y){lo=mid}else{hi=mid-1}}
@@ -519,7 +525,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
519
525
  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=""}
520
526
  close()}else{return}
521
527
  e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const 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)}}}
522
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["c68e6612a9ea6eb0","canopyx-tree-tools.b8ee5c807c1d4fcd.js","canopyx-tree-tools.aae203232147f116.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.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":["dd1076d5684bfc6e","canopyx-layouts.670fd555e6e08904.js","canopyx-layouts.b1df38a90cb3215d.css"],"record-panel":["e78e0e62d74d6811","canopyx-record-panel.2fe5e43bb99cc818.js","canopyx-record-panel.f3691d54cefaab04.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
528
+ const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"record-panel":["82aa828bc880087b","canopyx-record-panel.e0736e2285995701.js","canopyx-record-panel.4b9f1a99c5b76321.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
523
529
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
524
530
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
525
531
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -529,7 +535,7 @@ const load=(element,attribute,file,kind)=>new Promise((resolve,reject)=>{const u
529
535
  .catch(error=>{part.styleReady=null;throw error}));const code=PART_CODE.get(part.name)?.version===part.version||(part.scriptReady||=load(script,"src",hashed?scriptFile:"canopyx-"+part.name+".js","script")
530
536
  .finally(()=>script.remove()).catch(error=>{part.scriptReady=null;throw error}));await Promise.all([style,code])}}
531
537
  const code=PART_CODE.get(part.name);if(code?.version!==part.version)throw new Error("CanopyX: "+part.label+" and runtime must come from the same build.");for(const name of code.requires||[])await loadPart(part.parts[name]);code.install(part.context())}).catch(error=>{part.ready=null;throw error})}
532
- const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};const TREE_TOOLS=definePart(TreeGrid,"tree-tools","tree tools",()=>({TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,exportTimeout,exportFormatsOf:EXPORT_IMPL.formatsOf,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField,columnNumericTone,columnValueTone}));const SEARCH_IMPL={},SEARCH_PART=definePart(TreeGrid,"search","sidecar search",()=>({SEARCH_IMPL,checkDocument,badIndex,isCount,isIdentifier,recentCache,packBytes,shardKey,foldText,trimSeparators,rankHits,validateSearchHit,PACK_CACHE,PACK_CACHE_BYTES,SHARD_CACHE,ENTRY_CACHE,ENTRY_BATCH,SEARCH_CANDIDATES}));async function requirePart(name){await this.toolsReady;const part=Object.hasOwn(this.parts,name)?this.parts[name]:null;if(!part)throw new Error("CanopyX: unknown part '"+name+"'.");return loadPart(part)}
538
+ const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};const TREE_TOOLS=definePart(TreeGrid,"tree-tools","tree tools",()=>({TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,exportTimeout,exportFormatsOf:EXPORT_IMPL.formatsOf,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField,columnNumericTone,columnValueTone,overlayTheme}));const SEARCH_IMPL={},SEARCH_PART=definePart(TreeGrid,"search","sidecar search",()=>({SEARCH_IMPL,checkDocument,badIndex,isCount,isIdentifier,recentCache,packBytes,shardKey,foldText,trimSeparators,rankHits,validateSearchHit,PACK_CACHE,PACK_CACHE_BYTES,SHARD_CACHE,ENTRY_CACHE,ENTRY_BATCH,SEARCH_CANDIDATES}));async function requirePart(name){await this.toolsReady;const part=Object.hasOwn(this.parts,name)?this.parts[name]:null;if(!part)throw new Error("CanopyX: unknown part '"+name+"'.");return loadPart(part)}
533
539
  TreeGrid.prototype.requirePart=requirePart;function readStateColumn(c,seen){requireIdentifier(c&&c.id,"state column ID");if(seen.has(c.id)||!Number.isFinite(c.width)||c.width<40||c.width>MAX_COLUMN_WIDTH||typeof c.hidden!=="boolean")
534
540
  throw new Error("CanopyX: invalid state column.");seen.add(c.id);return{id:c.id,width:c.width,hidden:c.hidden}}
535
541
  function statePaths(value){if(!Array.isArray(value))throw new Error("CanopyX: state paths must be arrays.");return value.map(path=>{if(!Array.isArray(path)||!path.length)throw new Error("CanopyX: state paths cannot be empty.");return path.map(id=>{requireIdentifier(id,"state path ID");return id})})}
@@ -543,9 +549,9 @@ catch(error){/* Nodes removed since the snapshot are skipped. */ }
543
549
  }},applyStatePosition(state,current){if(!state.version)return;const valid=path=>{const w=path&&this.keyMap.get(path[path.length-1]);return w&&JSON.stringify(this.pathOf(w))===JSON.stringify(path)?w:null};this.setSelection(state.selection.map(valid).filter(Boolean).map(w=>w.key));if(this.destroyed||current.signal.aborted)return;const focused=valid(state.focus);if(focused&&this.indexOf(focused)>=0)this.setFocus(focused,false);const anchor=state.anchor&&valid(state.anchor.path);if(anchor)this.restoreScrollAnchor({id:anchor.key,offset:state.anchor.offset})}});const PLUGINS=new Map();function plugin(value){const item=Object.freeze({...value}),fn=handler=>typeof handler==="function";const entry=menu=>action=>action&&typeof action.label==="string"&&
544
550
  (fn(action.run)&&action.render===undefined||menu&&fn(action.render)&&action.run===undefined);if(!value||!partName(item.name)||Object.hasOwn(PARTS,item.name)||[item.init,item.destroy].some(hook=>hook!==undefined&&!fn(hook))||
545
551
  ["requires","views","toolbarItems","menuItems","exportFormats","recordActions"].some(key=>item[key]!==undefined&&!Array.isArray(item[key]))||
546
- ["cellRenderers","columnTypes","editors","events","aggregates","detailRenderers","drawerSections"].some(key=>item[key]!==undefined&&Object(item[key])!==item[key])||
552
+ ["cellRenderers","columnTypes","editors","events","aggregates","detailRenderers","drawerSections","filterOperators","sortComparators"].some(key=>item[key]!==undefined&&Object(item[key])!==item[key])||
547
553
  !(item.requires||[]).every(partName)||!(item.views||[]).every(kind=>kind==="tree"||kind==="grid")||
548
- ![...Object.values(item.cellRenderers||{}),...Object.values(item.events||{}),...Object.values(item.detailRenderers||{}),...Object.values(item.drawerSections||{})].every(fn)||
554
+ ![...Object.values(item.cellRenderers||{}),...Object.values(item.events||{}),...Object.values(item.detailRenderers||{}),...Object.values(item.drawerSections||{}),...Object.values(item.filterOperators||{}),...Object.values(item.sortComparators||{})].every(fn)||
549
555
  !(item.toolbarItems||[]).every(entry())||!(item.recordActions||[]).every(entry())||!(item.menuItems||[]).every(entry(true)))
550
556
  throw new Error("CanopyX: invalid plugin '"+item.name+"'.");item.exportFormats?.forEach(exportFormat);return item}
551
557
  function use(value){const item=plugin(value);if(PLUGINS.has(item.name))throw new Error("CanopyX: plugin '"+item.name+"' is already registered.");PLUGINS.set(item.name,item);const formats=item.exportFormats?.map(registerExportFormat)||[];return()=>{if(PLUGINS.get(item.name)===item){PLUGINS.delete(item.name);formats.forEach(dispose=>dispose())}}}
@@ -583,14 +589,27 @@ finally{navigation.dispose()}
583
589
  if(navigation.cancelled())return null;if(this.queryAware)snapshotRevision(doc,this.datasetRevision);checkDocument(doc,"counts");this.applyCounts(Object.assign({},doc,{items:doc.items.filter(item=>{const captured=mine.get(item.id);return captured&&this.keyMap.get(item.id)===captured.w&&captured.w.countRevision===captured.revision})}),true);return doc}});const LINKS=definePart(TreeGrid,"links","deep links",()=>({TreeGrid,navigationScope}));for(const name of["openDeepLink","writeDeepLink"])TreeGrid.prototype[name]=function(...args){return this.view.deepLink?loadPart(LINKS).then(()=>this[name](...args),error=>this.emit("error",{error})):Promise.resolve()};TreeGrid.prototype.readLocation=function(){if(this.destroyed)return Promise.resolve();if(this.initializing){if(this.linkOpening&&this.currentLink()!==this.link){this.linkOpening.abort();this.link=null;// Deferred reopening must not reuse the canceled link if the address changes back.
584
590
  }
585
591
  this.linkChanged=this.dataLifetime.signal;return this.ready.then(()=>undefined,()=>undefined)}
586
- return this.openDeepLink()};DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{linkFilteredBy:"Filtered by {source}: {values}",linkRemoveFilter:"Remove the filter from {source}: {values}",linkFiltered:"Filtered by {source}: {count} rows",linkHighlighted:"{count} rows highlighted from {source}",linkHighlightedRows:"{count} rows highlighted",linkCleared:"Linked filters removed"}));const LINK_IMPL={TreeGrid,queryOwn:Symbol("own conditions")},LINK_PART=definePart(TreeGrid,"link","linked views",()=>({LINK_IMPL,h,setText,filterChipContent,fill,numberFormat,cellValue,setAttr,cellMatches}));const LINK_METHODS=["setExternalFilter","clearExternalFilters","setHighlight","clearHighlight","startLinkEvents"];function linkMethods(View){for(const name of LINK_METHODS)(View.prototype[name]=function(...args){return this.destroyed?Promise.resolve(/Highlight/.test(name) ? 0 : name === "startLinkEvents" ? undefined : false) : loadPart(LINK_PART).then(() => this[name](...args));
592
+ return this.openDeepLink()};function sharedDensity(host){const value=host.closest("[data-hfx-density]")?.getAttribute("data-hfx-density");return value==="compact"||value==="comfortable"?value:null}
593
+ function watchSharedDensity(view){let previous=sharedDensity(view.host);const metrics=()=>{if(previous)view.host.style.setProperty("--cx-compact",previous==="compact"?"1":"0");else view.host.style.removeProperty("--cx-compact")};metrics();const observer=new MutationObserver(()=>{const current=sharedDensity(view.host);if(current===previous||view.destroyed)return;previous=current;metrics();refreshSharedDensity(view)});for(let owner=view.host;owner;owner=owner.parentElement){observer.observe(owner,{attributes:true,attributeFilter:["data-hfx-density"]})}
594
+ view.lifetime.signal.addEventListener("abort",()=>observer.disconnect(),{once:true})}
595
+ function layoutAnchor(view){const rows=view.rowProjection||view,top=view.logicalTop(),count=rows.rowCount();if(!count)return null;const index=rows.rowAt(top),height=(view.autoRows?null:view.rowH)||1;const offset=Math.max(0,top-rows.rowTop(index));return{index,offset,share:Math.max(0,Math.min(1,offset / height)) };
596
+ }
597
+ function layoutRows(view,anchor){const rows=view.rowProjection||view;for(const row of[...view.rowCache.values(),...view.placeholders.values()])row.hpx=view.rowH;if(view.autoRows){for(const[index,height]of view.rowHeights)if(height<view.rowH)view.rowHeights.set(index,view.rowH);view.rowOffsets=null;view.measureNeeded=true;view.render()}
598
+ else{const bounds=view.rowBounds(),count=view.rowProjection?rows.rowCount():Math.max(0,bounds.last-bounds.first+1);view.total=count*view.rowH;view.syncScrollRange(anchor?rows.rowTop(anchor.index)+ anchor.share*view.rowH:0)}
599
+ if(anchor&&view.autoRows){const top=rows.rowTop(anchor.index),height=rows.rowTop(anchor.index+1)- top;view.setLogicalTop(top+Math.min(anchor.offset,Math.max(0,height-1)))}
600
+ view.render()}
601
+ function layoutApplyTree(view){const before=view.rowH,after=densityRowHeight(view,view.density);if(before!==after){const anchor=view.captureScrollAnchor();view.rowH=after;const status=row=>{if(row&&row.hpx===before)row.hpx=after};status(view.root._status);for(const row of view.keyMap.values()){if(!row.h?.detail&&row.hpx===before)row.hpx=after;status(row._status)}
602
+ for(const row of view.rows)if(row.status)status(row);view.retop();if(anchor)view.restoreScrollAnchor(anchor)}
603
+ view.fitKey=null;view.version++;if(view.fitReady)view.applyWidths();view.render()}
604
+ function refreshSharedDensity(view){if(!view.grid)return;if(view.kind==="grid"){view.fitKey=null;view.fitFont=null;if(view.layoutMode==="cards"&&VIEW_MODES.refreshCardDensity)VIEW_MODES.refreshCardDensity(view);else{const anchor=layoutAnchor(view);view.rowH=densityRowHeight(view,view.density);view.version++;layoutRows(view,anchor);view.applyWidths()}}else layoutApplyTree(view);view.host.style.setProperty("--cx-row-h",view.rowH+"px");view.fitHeight?.()}
605
+ DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{linkFilteredBy:"Filtered by {source}: {values}",linkRemoveFilter:"Remove the filter from {source}: {values}",linkFiltered:"Filtered by {source}: {count} rows",linkHighlighted:"{count} rows highlighted from {source}",linkHighlightedRows:"{count} rows highlighted",linkCleared:"Linked filters removed"}));const LINK_IMPL={TreeGrid,queryOwn:Symbol("own conditions")},LINK_PART=definePart(TreeGrid,"link","linked views",()=>({LINK_IMPL,h,setText,filterChipContent,fill,numberFormat,cellValue,setAttr,cellMatches}));const LINK_METHODS=["setExternalFilter","clearExternalFilters","setHighlight","clearHighlight","startLinkEvents"];function linkMethods(View){for(const name of LINK_METHODS)(View.prototype[name]=function(...args){return this.destroyed?Promise.resolve(/Highlight/.test(name) ? 0 : name === "startLinkEvents" ? undefined : false) : loadPart(LINK_PART).then(() => this[name](...args));
587
606
  }).linkStub=true;View.prototype.getExternalFilters=function(){return(this.linkCommitted||[]).map(item=>JSON.parse(JSON.stringify(item)))};View.prototype.getHighlight=function(){return Array.from(this.linkHighlight||[])};View.prototype.linkStart=function(){if(this.opts.linkEvents===true)return loadPart(LINK_PART).then(()=>this.linkWatch()).catch(error=>{this.emit("error",{error});throw error})}}
588
607
  linkMethods(TreeGrid);function linkGridPart(View){(Object.hasOwn(View.prototype,"parts")?View.prototype.parts:View.prototype.parts={}).link=LINK_PART}
589
608
  function linkReady(grid,ready){return Promise.all([ready,grid.linkStart()]).then(([result])=>result)}
590
609
  function linkApi(grid){const api={};for(const name of LINK_METHODS.concat("getExternalFilters","getHighlight"))api[name]=(...args)=>grid[name](...args);return api}
591
610
  const RECORD_IMPL={},RECORD_PART=definePart(TreeGrid,"record-panel","record panel",()=>({RECORD_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,badgeElement,loadSidecar,requireIdentifier,validateGridRows,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField,columnNumericTone,columnValueTone,validateColumnValues}));function loadRecordPanel(){return loadPart(RECORD_PART)}
592
611
  const RECORD_STRUCTURE=["items","fields","records","events","changes","ref"];TreeGrid.prototype.recordNeeded=function(node){return!!this.view.record||!!node&&(!!node.fields||Object.values(node.cells||{}).some(cell=>isCellObject(cell)&&RECORD_STRUCTURE.some(name=>cell[name]!==undefined)))};TreeGrid.prototype.openRecord=function(id,options){return loadRecordPanel().then(()=>RECORD_IMPL.open(this,id,options))};function recordStart(grid){if(grid.view.record?.deepLink)loadRecordPanel().then(()=>RECORD_IMPL.start(grid),error=>grid.emit("error",{error}))}
593
- DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{matchesHighlight:"Highlight matches",matchesCount:"[one]{count} match[other]{count} matches",matchesPosition:"{current} of {count}",matchesNone:"No matches",matchesLoaded:"[one]{count} match in loaded rows[other]{count} matches in loaded rows",matchesPrevious:"Previous match",matchesNext:"Next match",matchesAnnounce:"Match {current} of {count}, {column}",layoutMenu:"Layout",layoutFit:"Fit to width",layoutScroll:"All columns, scroll sideways",layoutCards:"Cards",layoutDensity:"Density",layoutCompact:"Compact",layoutNormal:"Normal",layoutComfortable:"Comfortable",layoutChanged:"Layout: {mode}, {density}",layoutSort:"Sort by"}));const LAYOUT_MODES=["fit","scroll","cards"],LAYOUT_DENSITIES=["compact","default","comfortable"];const DENSITY_STEP={tree:{compact:-4,default:0,comfortable:8},grid:{compact:-6,default:0,comfortable:8}};const VIEW_MODES={};const HIGHLIGHT_KEYS=["enabled","search","filters","matchCase","ignoreAccents","minLength","filterTones"];function readSearchHighlight(value,columns){if(value===undefined||value===false)return null;const options=value===true?{}:value,tone=name=>typeof name==="string"&&/^[a-z][a-z0-9-]{0,31}$/.test(name) && !name.endsWith("-bg");
612
+ DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{matchesHighlight:"Highlight matches",matchesCount:"[one]{count} match[other]{count} matches",matchesPosition:"{current} of {count}",matchesNone:"No matches",matchesLoaded:"[one]{count} match in loaded rows[other]{count} matches in loaded rows",matchesPrevious:"Previous match",matchesNext:"Next match",matchesAnnounce:"Match {current} of {count}, {column}",layoutMenu:"Layout",layoutFit:"Fit to width",layoutScroll:"All columns, scroll sideways",layoutCards:"Cards",layoutDensity:"Density",layoutCompact:"Compact",layoutNormal:"Normal",layoutComfortable:"Comfortable",layoutChanged:"Layout: {mode}, {density}",layoutSort:"Sort by"}));const LAYOUT_MODES=["fit","scroll","cards"],LAYOUT_DENSITIES=["compact","default","comfortable"];const DENSITY_STEP={tree:{compact:-8,default:0,comfortable:0},grid:{compact:-8,default:0,comfortable:0}};const VIEW_MODES={};const HIGHLIGHT_KEYS=["enabled","search","filters","matchCase","ignoreAccents","minLength","filterTones"];function readSearchHighlight(value,columns){if(value===undefined||value===false)return null;const options=value===true?{}:value,tone=name=>typeof name==="string"&&/^[a-z][a-z0-9-]{0,31}$/.test(name) && !name.endsWith("-bg");
594
613
  if(!options||typeof options!=="object"||Array.isArray(options)||Object.keys(options).some(key=>!HIGHLIGHT_KEYS.includes(key))||
595
614
  HIGHLIGHT_KEYS.slice(0,5).some(key=>options[key]!==undefined&&typeof options[key]!=="boolean")||
596
615
  options.minLength!==undefined&&(!Number.isInteger(options.minLength)||options.minLength<1||options.minLength>32)||
@@ -606,12 +625,12 @@ function readModeState(view,state){const result={};if(state.layout!==undefined){
606
625
  throw new Error("CanopyX: invalid saved layout.");if(options)result.layout={mode:options.modes.includes(layout.mode)?layout.mode:options.mode,density:layout.density}}
607
626
  if(state.highlight!==undefined){if(typeof state.highlight!=="boolean")throw new Error("CanopyX: invalid saved highlight choice.");if(view.highlightOptions)result.highlight=state.highlight}
608
627
  return result}
609
- function densityRowHeight(view,density){const steps=DENSITY_STEP[view.kind];return Math.max(20,Math.min(64,view.baseRowH+steps[density]- steps[view.declaredDensity]))}
610
- const VIEW_MODE_METHODS={prepareViewModes(){const view=this.view,columns=this.columns||view.columns;this.highlightOptions=readSearchHighlight(view.searchHighlight,columns);this.declaredDensity=this.kind==="grid"?view.density||"default":"default";this.layoutOptions=readLayout(view.layout,this.kind,this.declaredDensity);this.baseRowH=this.rowH;this.adoptModes({layout:this.layoutOptions||{mode:"fit",density:this.declaredDensity},highlight:!!this.highlightOptions?.enabled})},adoptModes(choice){if(choice.layout){this.layoutMode=choice.layout.mode;this.density=choice.layout.density}
628
+ function densityRowHeight(view,density){const shared=sharedDensity(view.host);if(shared)return shared==="compact"?32:40;const steps=DENSITY_STEP[view.kind];return Math.max(20,Math.min(64,view.baseRowH+steps[density]- steps[view.declaredDensity]))}
629
+ const VIEW_MODE_METHODS={prepareViewModes(){const view=this.view,columns=this.columns||view.columns;this.highlightOptions=readSearchHighlight(view.searchHighlight,columns);this.declaredDensity=this.kind==="grid"?view.density||"default":"default";this.layoutOptions=readLayout(view.layout,this.kind,this.declaredDensity);this.baseRowH=this.rowH;this.adoptModes({layout:this.layoutOptions||{mode:"fit",density:this.declaredDensity},highlight:!!this.highlightOptions?.enabled});watchSharedDensity(this)},adoptModes(choice){if(choice.layout){this.layoutMode=choice.layout.mode;this.density=choice.layout.density}
611
630
  if(choice.highlight!==undefined)this.highlightOn=choice.highlight;this.rowH=densityRowHeight(this,this.density);if(this.layoutMode==="fit")this.host.removeAttribute("data-cx-layout");else this.host.setAttribute("data-cx-layout",this.layoutMode)},modeState(state){if(this.layoutOptions)state.layout={mode:this.layoutMode,density:this.density};if(this.highlightOptions)state.highlight=!!this.highlightOn;return state},applyModeState(state){if(state.layout&&(state.layout.mode!==this.layoutMode||state.layout.density!==this.density))
612
631
  this.setLayout(state.layout).catch(error=>this.emit("error",{error}));if(state.highlight!==undefined&&state.highlight!==!!this.highlightOn)
613
632
  this.setSearchHighlight(state.highlight).catch(error=>this.emit("error",{error}))},startViewModes(){const parts=[this.highlightOptions&&"highlight",this.layoutOptions&&"layouts"].filter(Boolean);return Promise.all(parts.map(name=>this.requirePart(name).then(()=>this.destroyed||VIEW_MODES[name+"Start"](this))
614
- .catch(error=>this.emit("error",{error}))))},getLayout(){return Object.freeze({mode:this.layoutMode,density:this.density,modes:this.layoutOptions?this.layoutOptions.modes:Object.freeze(["fit"])})},setLayout(change){if(!this.layoutOptions)return Promise.reject(new Error("CanopyX: this view declares no layout modes."));return this.requirePart("layouts").then(()=>VIEW_MODES.setLayout(this,change))},getMatches(){return VIEW_MODES.matches?VIEW_MODES.matches(this):Object.freeze({enabled:!!this.highlightOn,total:0,current:0,complete:true})},setSearchHighlight(enabled){if(typeof enabled!=="boolean")return Promise.reject(new Error("CanopyX: the highlight switch is a boolean."));if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.setHighlight(this,enabled))},nextMatch(options){return this.stepMatch(1,options)},previousMatch(options){return this.stepMatch(-1,options)},stepMatch(direction,options){if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.step(this,direction,options?.focus!==false))}};Object.assign(TreeGrid.prototype,VIEW_MODE_METHODS);const viewModeContext=()=>({VIEW_MODES,TreeGrid,h,setText,fill,numberFormat,foldText,cellText,cellValue,isCellObject,setAttr,toneOf,watchFlyout,densityRowHeight,MAX_PROTOCOL_INTEGER,LAYOUT_DENSITIES,plural,svgIcon});definePart(TreeGrid,"highlight","search highlighting",viewModeContext);definePart(TreeGrid,"layouts","layout modes",viewModeContext);const MODES_TOOLBAR=TreeGrid.prototype.buildToolbar;TreeGrid.prototype.buildToolbar=function(){MODES_TOOLBAR.call(this);if(this.highlightOptions||this.layoutOptions)this.modesReady=Promise.resolve(this.toolsReady).then(()=>this.destroyed||this.startViewModes());this.lifetime.signal.addEventListener("abort",()=>this.host.removeAttribute("data-cx-layout"),{once:true})};Object.assign(TreeGrid.prototype,{destroy(){if(this.destroyed)return;this.destroyed=true;for(const row of[...this.rendered.values(),...this.pool])disposeRowHostCells(row);this.lifetime.abort();this.dataLifetime.abort();if(this.queryController)this.queryController.abort();if(this.restoreController)this.restoreController.abort();if(this.cancelResize)this.cancelResize();clearTimeout(this.saveTimer);clearTimeout(this.layoutTimer);if(this.cancelSearch)this.cancelSearch();if(this.disposeSearchFlyout)this.disposeSearchFlyout();cancelAnimationFrame(this.rafId);this.resizeObserver.disconnect();if(this.detailObserver)this.detailObserver.disconnect();this.grid.removeEventListener("scroll",this.onScroll);this.grid.removeEventListener("wheel",this.onScaledWheel);this.grid.removeEventListener("touchstart",this.onScaledTouchStart);this.grid.removeEventListener("touchmove",this.onScaledTouchMove);this.grid.removeEventListener("touchend",this.onScaledTouchEnd);this.grid.removeEventListener("touchcancel",this.onScaledTouchEnd);global.removeEventListener("beforeprint",this.onPrint);global.removeEventListener("hashchange",this.onHash);global.removeEventListener("popstate",this.onHash);if(this.linkOpening)this.linkOpening.abort();[this.toolbar,this.grid,this.live,this.outline].forEach(element=>element.remove());this.host.classList.remove("cx-pin-tree");this.host.removeAttribute("data-cx-ready");this.host.removeAttribute("data-canopyx-mounted");this.keyMap.clear();this.selected.clear();this.rendered.clear();this.pool.length=0;if(this.inactiveCache)this.inactiveCache.clear();if(this.inlineRetained)this.inlineRetained.clear();this.rows=[];this.tops=[0];this.total=0;this.root.children=null;this.root.inlineCache=null;this.root.inlineOrder=null;this.focused=null;this.anchor=null;this.source=null;this.touchScroll=null;this.opts={};for(const column of this.columns)column.render=null;this.filter=null;this.declaredFilter=null;this.pendingRestorationToggles=null;this.scrolledCell=null;this.focusHandoff=null;this.cancelResize=null;this.cancelSearch=null;this.disposeSearchFlyout=null;this.canvas.replaceChildren();this.outline.replaceChildren()}});function checkIntentPath(path){if(!Array.isArray(path)||!path.length)throw new Error("CanopyX: checking needs a complete node-ID path.");const seen=new Set();return path.map(id=>{requireIdentifier(id,"checking path ID");if(seen.has(id))throw new Error("CanopyX: a checking path cannot repeat an ID.");seen.add(id);return id})}
633
+ .catch(error=>this.emit("error",{error}))))},getLayout(){return Object.freeze({mode:this.layoutMode,density:this.density,modes:this.layoutOptions?this.layoutOptions.modes:Object.freeze(["fit"])})},setLayout(change){if(!this.layoutOptions)return Promise.reject(new Error("CanopyX: this view declares no layout modes."));return this.requirePart("layouts").then(()=>VIEW_MODES.setLayout(this,change))},getMatches(){return VIEW_MODES.matches?VIEW_MODES.matches(this):Object.freeze({enabled:!!this.highlightOn,total:0,current:0,complete:true})},setSearchHighlight(enabled){if(typeof enabled!=="boolean")return Promise.reject(new Error("CanopyX: the highlight switch is a boolean."));if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.setHighlight(this,enabled))},nextMatch(options){return this.stepMatch(1,options)},previousMatch(options){return this.stepMatch(-1,options)},stepMatch(direction,options){if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.step(this,direction,options?.focus!==false))}};Object.assign(TreeGrid.prototype,VIEW_MODE_METHODS);const viewModeContext=()=>({VIEW_MODES,TreeGrid,h,setText,fill,numberFormat,foldText,cellText,cellValue,isCellObject,setAttr,toneOf,toneVariable,watchFlyout,densityRowHeight,layoutAnchor,layoutRows,layoutApplyTree,MAX_PROTOCOL_INTEGER,LAYOUT_DENSITIES,plural,svgIcon});definePart(TreeGrid,"highlight","search highlighting",viewModeContext);definePart(TreeGrid,"layouts","layout modes",viewModeContext);const MODES_TOOLBAR=TreeGrid.prototype.buildToolbar;TreeGrid.prototype.buildToolbar=function(){MODES_TOOLBAR.call(this);if(this.highlightOptions||this.layoutOptions)this.modesReady=Promise.resolve(this.toolsReady).then(()=>this.destroyed||this.startViewModes());this.lifetime.signal.addEventListener("abort",()=>this.host.removeAttribute("data-cx-layout"),{once:true})};Object.assign(TreeGrid.prototype,{destroy(){if(this.destroyed)return;this.destroyed=true;for(const row of[...this.rendered.values(),...this.pool])disposeRowHostCells(row);this.lifetime.abort();this.dataLifetime.abort();if(this.queryController)this.queryController.abort();if(this.restoreController)this.restoreController.abort();if(this.cancelResize)this.cancelResize();clearTimeout(this.saveTimer);clearTimeout(this.layoutTimer);if(this.cancelSearch)this.cancelSearch();if(this.disposeSearchFlyout)this.disposeSearchFlyout();cancelAnimationFrame(this.rafId);this.resizeObserver.disconnect();if(this.detailObserver)this.detailObserver.disconnect();this.grid.removeEventListener("scroll",this.onScroll);this.grid.removeEventListener("wheel",this.onScaledWheel);this.grid.removeEventListener("touchstart",this.onScaledTouchStart);this.grid.removeEventListener("touchmove",this.onScaledTouchMove);this.grid.removeEventListener("touchend",this.onScaledTouchEnd);this.grid.removeEventListener("touchcancel",this.onScaledTouchEnd);global.removeEventListener("beforeprint",this.onPrint);global.removeEventListener("hashchange",this.onHash);global.removeEventListener("popstate",this.onHash);if(this.linkOpening)this.linkOpening.abort();[this.toolbar,this.grid,this.live,this.outline].forEach(element=>element.remove());this.host.classList.remove("cx-pin-tree");this.host.removeAttribute("data-cx-ready");this.host.removeAttribute("data-canopyx-mounted");this.keyMap.clear();this.selected.clear();this.rendered.clear();this.pool.length=0;if(this.inactiveCache)this.inactiveCache.clear();if(this.inlineRetained)this.inlineRetained.clear();this.rows=[];this.tops=[0];this.total=0;this.root.children=null;this.root.inlineCache=null;this.root.inlineOrder=null;this.focused=null;this.anchor=null;this.source=null;this.touchScroll=null;this.opts={};for(const column of this.columns)column.render=null;this.filter=null;this.declaredFilter=null;this.pendingRestorationToggles=null;this.scrolledCell=null;this.focusHandoff=null;this.cancelResize=null;this.cancelSearch=null;this.disposeSearchFlyout=null;this.canvas.replaceChildren();this.outline.replaceChildren()}});function checkIntentPath(path){if(!Array.isArray(path)||!path.length)throw new Error("CanopyX: checking needs a complete node-ID path.");const seen=new Set();return path.map(id=>{requireIdentifier(id,"checking path ID");if(seen.has(id))throw new Error("CanopyX: a checking path cannot repeat an ID.");seen.add(id);return id})}
615
634
  function checkBranch(){return{value:null,mask:0,children:new Map()}}
616
635
  class CheckIntents{constructor(items,mode){if(!Array.isArray(items))throw new Error("CanopyX: checkIntents must be an array.");this.mode=mode;this.root=checkBranch();for(const item of items){if(!item||typeof item.checked!=="boolean")throw new Error("CanopyX: a checking intent needs a boolean checked value.");const path=checkIntentPath(item.path);let branch=this.root;for(const id of path){if(!branch.children.has(id))branch.children.set(id,checkBranch());branch=branch.children.get(id)}
617
636
  if(branch.value!==null)throw new Error("CanopyX: a checking path cannot have duplicate intents.");branch.value=item.checked}
@@ -507,6 +507,11 @@ const labels = Object.freeze({
507
507
  calendarOccurrenceTitle: "Wiederkehrenden Termin ändern",
508
508
  calendarOccurrenceReadOnly: "Dieser Teil der Serie kann nicht gespeichert werden, weil einige Werte schreibgeschützt sind.",
509
509
  calendarThisEvent: "Nur dieser Termin",
510
+ calendarEditOccurrence: "Dieses Vorkommen bearbeiten",
511
+ calendarRemoveOccurrence: "Dieses Vorkommen entfernen",
512
+ calendarOccurrenceScope: "Nur {date} ändert sich; andere Termine von {title} bleiben unverändert.",
513
+ calendarSharedResources: "{count} {resources}",
514
+ calendarResourceWindow: "{resources} {start}–{end} von {total}",
510
515
  calendarThisAndFollowing: "Dieser und alle folgenden Termine",
511
516
  calendarAllEvents: "Alle Termine",
512
517
  calendarSources: "Kalender",
@@ -507,6 +507,11 @@ const labels = Object.freeze({
507
507
  calendarOccurrenceTitle: "Cambiar un evento periódico",
508
508
  calendarOccurrenceReadOnly: "No se puede guardar esta parte de la serie porque algunos valores son de solo lectura.",
509
509
  calendarThisEvent: "Este evento",
510
+ calendarEditOccurrence: "Editar esta ocurrencia",
511
+ calendarRemoveOccurrence: "Eliminar esta ocurrencia",
512
+ calendarOccurrenceScope: "Solo cambia {date}; las otras fechas de {title} se mantienen.",
513
+ calendarSharedResources: "{count} {resources}",
514
+ calendarResourceWindow: "{resources} {start}–{end} de {total}",
510
515
  calendarThisAndFollowing: "Este evento y los siguientes",
511
516
  calendarAllEvents: "Todos los eventos",
512
517
  calendarSources: "Calendarios",
@@ -507,6 +507,11 @@ const labels = Object.freeze({
507
507
  calendarOccurrenceTitle: "Modifier un événement récurrent",
508
508
  calendarOccurrenceReadOnly: "Cette partie de la série ne peut pas être enregistrée, car certaines valeurs sont en lecture seule.",
509
509
  calendarThisEvent: "Cet événement",
510
+ calendarEditOccurrence: "Modifier cette occurrence",
511
+ calendarRemoveOccurrence: "Supprimer cette occurrence",
512
+ calendarOccurrenceScope: "Seul le {date} change ; les autres dates de {title} restent inchangées.",
513
+ calendarSharedResources: "{count} {resources}",
514
+ calendarResourceWindow: "{resources} {start}–{end} sur {total}",
510
515
  calendarThisAndFollowing: "Cet événement et les suivants",
511
516
  calendarAllEvents: "Tous les événements",
512
517
  calendarSources: "Calendriers",
@@ -507,6 +507,11 @@ const labels = Object.freeze({
507
507
  calendarOccurrenceTitle: "Modifica un evento ricorrente",
508
508
  calendarOccurrenceReadOnly: "Questa parte della serie non può essere salvata perché alcuni valori sono di sola lettura.",
509
509
  calendarThisEvent: "Questo evento",
510
+ calendarEditOccurrence: "Modifica questa occorrenza",
511
+ calendarRemoveOccurrence: "Rimuovi questa occorrenza",
512
+ calendarOccurrenceScope: "Cambia solo {date}; le altre date di {title} restano invariate.",
513
+ calendarSharedResources: "{count} {resources}",
514
+ calendarResourceWindow: "{resources} {start}–{end} di {total}",
510
515
  calendarThisAndFollowing: "Questo evento e i successivi",
511
516
  calendarAllEvents: "Tutti gli eventi",
512
517
  calendarSources: "Calendari",
@@ -507,6 +507,11 @@ const labels = Object.freeze({
507
507
  calendarOccurrenceTitle: "Zmień wydarzenie cykliczne",
508
508
  calendarOccurrenceReadOnly: "Nie można zapisać tej części serii, ponieważ niektóre wartości są tylko do odczytu.",
509
509
  calendarThisEvent: "To wydarzenie",
510
+ calendarEditOccurrence: "Edytuj to wystąpienie",
511
+ calendarRemoveOccurrence: "Usuń to wystąpienie",
512
+ calendarOccurrenceScope: "Zmienia się tylko {date}; pozostałe daty wydarzenia {title} pozostają bez zmian.",
513
+ calendarSharedResources: "{count} {resources}",
514
+ calendarResourceWindow: "{resources} {start}–{end} z {total}",
510
515
  calendarThisAndFollowing: "To i następne wydarzenia",
511
516
  calendarAllEvents: "Wszystkie wydarzenia",
512
517
  calendarSources: "Kalendarze",
@@ -1,30 +1,30 @@
1
1
  /* The Layout menu: radio groups for the mode and the density. */
2
2
  .cx-chrome .cx-grid-layout > .cx-grid-panel{display:block;width:var(--cx-size-244px);padding:var(--cx-size-6px) var(--cx-size-8px);}
3
3
  .cx-layout-group{padding:var(--cx-size-4px) 0;}
4
- .cx-layout-group + .cx-layout-group{border-top:var(--cx-size-1px) solid var(--cx-line);margin-top:var(--cx-size-4px);padding-top:var(--cx-size-8px);}
5
- .cx-layout-title{padding:0 var(--cx-size-6px) var(--cx-size-4px);font-size:var(--cx-size-12px);font-weight:700;color:var(--cx-muted);}
6
- .cx-layout-choice{display:flex;align-items:center;gap:var(--cx-size-8px);min-height:var(--cx-size-32px);padding:0 var(--cx-size-6px);border-radius:var(--cx-radius-sm);cursor:pointer;}
7
- .cx-layout-choice:hover{background:var(--cx-hover-bg);}
8
- .cx-layout-choice input{flex:none;width:var(--cx-size-16px);height:var(--cx-size-16px);margin:0;accent-color:var(--cx-accent);}
9
- .cx-layout-choice:has(input:focus-visible){outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:calc(-1 * var(--cx-size-2px));}
4
+ .cx-layout-group + .cx-layout-group{border-top:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));margin-top:var(--cx-size-4px);padding-top:var(--cx-size-8px);}
5
+ .cx-layout-title{padding:0 var(--cx-size-6px) var(--cx-size-4px);font-size:var(--cx-size-12px);font-weight:700;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
6
+ .cx-layout-choice{display:flex;align-items:center;gap:var(--cx-size-8px);min-height:var(--cx-size-32px);padding:0 var(--cx-size-6px);border-radius:var(--hfx-radius-sm,4px);cursor:pointer;}
7
+ .cx-layout-choice:hover{background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));}
8
+ .cx-layout-choice input{flex:none;width:var(--cx-size-16px);height:var(--cx-size-16px);margin:0;accent-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
9
+ .cx-layout-choice:has(input:focus-visible){outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:calc(-1 * var(--cx-size-2px));}
10
10
  .cx-chrome.cx-phone .cx-grid-layout > summary{width:var(--cx-size-44px);font-size:0;padding:0;}
11
11
  .cx-chrome.cx-phone .cx-layout-choice{min-height:var(--cx-size-44px);}
12
- .cx-layouts:not(.cx-data-grid)[data-cx-density="compact"]{--cx-font-size:13px;--cx-cell-px:6px;}
13
- .cx-layouts:not(.cx-data-grid)[data-cx-density="comfortable"]{--cx-cell-px:12px;}
12
+ .cx-layouts:not(.cx-data-grid)[data-cx-density="compact"]{}
13
+ .cx-layouts:not(.cx-data-grid)[data-cx-density="comfortable"]{}
14
14
  .cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-hcell:first-child,.cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-row > .cx-tree{position:sticky;left:0;z-index:1;}
15
- .cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-hcell:first-child{z-index:2;background:var(--cx-head-bg);}
15
+ .cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-hcell:first-child{z-index:2;background:var(--hfx-table-header-background,var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317)));}
16
16
  .cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-row > .cx-tree{background:inherit;}
17
17
  .cx-data-grid[data-cx-layout="cards"] .cx-grid{overflow-x:hidden;}
18
18
  .cx-data-grid[data-cx-layout="cards"] :is(.cx-canvas,.cx-head){width:100% !important;min-width:0;}
19
19
  .cx-data-grid[data-cx-layout="cards"] .cx-head{display:none;}
20
20
  .cx-chrome .cx-grid-sort > .cx-grid-panel{display:block;width:var(--cx-size-280px);padding:var(--cx-size-6px) var(--cx-size-8px);}
21
21
  .cx-sort-list{display:flex;flex-direction:column;gap:var(--cx-size-2px);}
22
- .cx-grid-sort .cx-grid-selection-controls{padding:var(--cx-size-4px) var(--cx-size-6px) var(--cx-size-8px);margin-bottom:var(--cx-size-6px);border-bottom:var(--cx-size-1px) solid var(--cx-line);}
22
+ .cx-grid-sort .cx-grid-selection-controls{padding:var(--cx-size-4px) var(--cx-size-6px) var(--cx-size-8px);margin-bottom:var(--cx-size-6px);border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
23
23
  .cx-sort-choice{display:flex;align-items:center;gap:var(--cx-size-4px);min-height:var(--cx-size-32px);}
24
- .cx-chrome .cx-sort-choice .cx-sort-column{flex:1;min-width:0;justify-content:start;border:0;border-radius:var(--cx-radius-sm);background:transparent;overflow:hidden;text-overflow:ellipsis;}
25
- .cx-chrome .cx-sort-choice span.cx-sort-column{padding:0 var(--cx-size-11px);color:var(--cx-muted);}
26
- .cx-chrome .cx-sort-choice .cx-sort-column[aria-pressed="true"]{color:var(--cx-accent-text);background:var(--cx-accent-soft);font-weight:600;}
27
- .cx-chrome .cx-sort-choice .cx-sort-menu{flex:none;border:0;background:transparent;color:var(--cx-text-2);}
24
+ .cx-chrome .cx-sort-choice .cx-sort-column{flex:1;min-width:0;justify-content:start;border:0;border-radius:var(--hfx-radius-sm,4px);background:transparent;overflow:hidden;text-overflow:ellipsis;}
25
+ .cx-chrome .cx-sort-choice span.cx-sort-column{padding:0 var(--cx-size-11px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
26
+ .cx-chrome .cx-sort-choice .cx-sort-column[aria-pressed="true"]{color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));font-weight:600;}
27
+ .cx-chrome .cx-sort-choice .cx-sort-menu{flex:none;border:0;background:transparent;color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
28
28
  .cx-chrome.cx-phone .cx-grid-sort > summary{width:var(--cx-size-44px);font-size:0;padding:0;}
29
29
  .cx-chrome.cx-phone .cx-sort-choice{min-height:var(--cx-size-44px);}
30
30
  .cx-chrome.cx-phone .cx-sort-choice .cx-button{min-height:var(--cx-size-44px);}
@@ -37,12 +37,12 @@ grid-auto-flow:row dense;align-content:start;column-gap:var(--cx-size-16px);row-
37
37
  width:auto !important;height:auto;min-width:0;padding:0;position:relative !important;left:auto !important;right:auto !important;box-shadow:none;background:transparent;
38
38
  flex-direction:column;align-items:flex-start;justify-content:center;gap:var(--cx-size-1px);text-align:left;
39
39
  }
40
- .cx-data-grid[data-cx-layout="cards"] .cx-row:not(.cx-status):not(.cx-grid-group) > .cx-cell:first-child{grid-column:1/-1;height:var(--cx-card-title);flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--cx-size-6px);font-weight:600;font-size:calc(var(--cx-font-size) + 1px);}
40
+ .cx-data-grid[data-cx-layout="cards"] .cx-row:not(.cx-status):not(.cx-grid-group) > .cx-cell:first-child{grid-column:1/-1;height:var(--cx-card-title);flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--cx-size-6px);font-weight:600;font-size:calc(var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem)) + 1px);}
41
41
  .cx-data-grid[data-cx-layout="cards"] .cx-row:not(.cx-status):not(.cx-grid-group) > .cx-cell[data-cx-card="wide"]{grid-column:span var(--cx-card-span,1);}
42
- .cx-data-grid[data-cx-layout="cards"] .cx-cell[data-cx-label]::before{content:attr(data-cx-label) / "";display:block;flex:none;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--cx-size-11d5px);font-weight:600;line-height:1.35;color:var(--cx-muted);}
42
+ .cx-data-grid[data-cx-layout="cards"] .cx-cell[data-cx-label]::before{content:attr(data-cx-label) / "";display:block;flex:none;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--cx-size-11d5px);font-weight:600;line-height:1.35;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
43
43
  .cx-data-grid[data-cx-layout="cards"] .cx-cell > :is(.cx-text,.cx-presenter-text){max-width:100%;}
44
44
  .cx-data-grid[data-cx-layout="cards"] .cx-row:not(.cx-status):not(.cx-grid-group) > .cx-cell:first-child::before{content:none;}
45
- .cx-data-grid[data-cx-layout="cards"] .cx-row[aria-selected="true"]{box-shadow:inset var(--cx-size-3px) 0 0 var(--cx-accent);}
45
+ .cx-data-grid[data-cx-layout="cards"] .cx-row[aria-selected="true"]{box-shadow:inset var(--cx-size-3px) 0 0 var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
46
46
  @media (forced-colors:active){
47
47
  .cx-data-grid[data-cx-layout="cards"] .cx-row[aria-selected="true"]{forced-color-adjust:none;box-shadow:inset var(--cx-size-3px) 0 0 Highlight;}
48
48
  }
@@ -1,22 +1,14 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"dd1076d5684bfc6e",install(context){if(installed.has(context.VIEW_MODES))return;const{VIEW_MODES,TreeGrid,h,setText,fill,numberFormat,foldText,cellText,cellValue,isCellObject,setAttr,toneOf,watchFlyout,densityRowHeight,MAX_PROTOCOL_INTEGER,LAYOUT_DENSITIES,plural,svgIcon}=context;const CARD_METRICS={compact:{pad:8,field:36,gap:4,title:24},default:{pad:12,field:40,gap:6,title:26},comfortable:{pad:16,field:44,gap:8,title:28}};const CARD_FIELD=140,CARD_GUTTER=16,CARD_COLUMN_GAP=16,CARD_WIDE=["longText","tags","list"];function cardWide(column){return!!column.wrap||!!column.flex||CARD_WIDE.includes(column.presenter?.kind)}
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"606fcf6dcd00d420",install(context){if(installed.has(context.VIEW_MODES))return;const{VIEW_MODES,TreeGrid,h,setText,fill,numberFormat,foldText,cellText,cellValue,isCellObject,setAttr,toneOf,watchFlyout,densityRowHeight,layoutAnchor,layoutRows,layoutApplyTree,MAX_PROTOCOL_INTEGER,LAYOUT_DENSITIES,plural,svgIcon}=context;const CARD_METRICS={compact:{pad:8,field:36,gap:4,title:24},default:{pad:12,field:40,gap:6,title:26},comfortable:{pad:16,field:44,gap:8,title:28}};const CARD_FIELD=140,CARD_GUTTER=16,CARD_COLUMN_GAP=16,CARD_WIDE=["longText","tags","list"];function cardWide(column){return!!column.wrap||!!column.flex||CARD_WIDE.includes(column.presenter?.kind)}
2
2
  function cardGeometry(view){const metrics={...CARD_METRICS[view.density]},width=Math.max(0,(view.grid.clientWidth||view.host.clientWidth)- 2*CARD_GUTTER);const fields=(view.cols||[]).slice(1),most=Math.max(1,Math.floor((width+CARD_COLUMN_GAP)/ (CARD_FIELD + CARD_COLUMN_GAP)));
3
3
  const font=parseFloat(getComputedStyle(view.grid).fontSize),clampLines=column=>Math.min(column.maxLines??2,2);if(fields.some(column=>column.wrap))metrics.field=Math.max(metrics.field,Math.ceil(11.5*1.35+1+font*1.4*Math.max(...fields.filter(column=>column.wrap).map(clampLines))));if(view.cols?.[0]?.wrap)metrics.title=Math.max(metrics.title,Math.ceil((font+1)*1.4*clampLines(view.cols[0])));const slots=fields.reduce((sum,field)=>sum +(cardWide(field)&&most>1?2:1),0)||1;const columns=Math.min(most,Math.ceil(slots / Math.ceil(slots / most))), span = Math.min(2, columns), rows = [];
4
4
  for(const field of fields){const size=cardWide(field)?span:1;for(let row=0,placed=false;!placed;row++){const cells=rows[row]||=new Array(columns).fill(false);for(let at=0;at+size<=columns&&!placed;at++)if(cells.slice(at,at+size).every(used=>!used)){cells.fill(true,at,at+size);placed=true}}}
5
5
  const lines=rows.length;return{columns,span,metrics,height:2*metrics.pad+metrics.title +(lines?metrics.gap+lines*metrics.field +(lines-1)*metrics.gap:0)+ 1}}
6
6
  function cardStyle(view,geometry){const style=view.host.style,{metrics}=geometry;style.setProperty("--cx-card-cols",String(geometry.columns));style.setProperty("--cx-card-span",String(geometry.span));style.setProperty("--cx-card-pad",metrics.pad+"px");style.setProperty("--cx-card-field",metrics.field+"px");style.setProperty("--cx-card-gap",metrics.gap+"px");style.setProperty("--cx-card-title",metrics.title+"px")}
7
- function layoutAnchor(view){const rows=view.rowProjection||view,top=view.logicalTop(),count=rows.rowCount();if(!count)return null;const index=rows.rowAt(top),height=(view.autoRows?null:view.rowH)||1;return{index,share:Math.max(0,Math.min(1,(top-rows.rowTop(index))/ height)) };
8
- }
9
- function layoutRows(view,anchor){const rows=view.rowProjection||view;for(const row of[...view.rowCache.values(),...view.placeholders.values()])row.hpx=view.rowH;if(view.autoRows){view.rowOffsets=null;view.rowHeights?.clear();view.measureNeeded=true;view.render()}
10
- else{const bounds=view.rowBounds(),count=view.rowProjection?rows.rowCount():Math.max(0,bounds.last-bounds.first+1);view.total=count*view.rowH;view.syncScrollRange(anchor?rows.rowTop(anchor.index)+ anchor.share*view.rowH:0)}
11
- if(anchor&&view.autoRows)view.setLogicalTop(rows.rowTop(anchor.index));view.render()}
12
7
  function layoutApplyGrid(view,mode){const anchor=layoutAnchor(view);if(mode==="cards"){if(view.cardAutoRows===undefined){view.cardAutoRows=view.autoRows;view.autoRows=false}}
13
8
  else if(view.cardAutoRows!==undefined){view.autoRows=view.cardAutoRows;view.cardAutoRows=undefined;view.rowOffsets=null}
14
9
  view.fitFont=null;view.fitKey=null;view.layout=(view.layout||0)+ 1;view.version++;view.layoutApplying=true;try{view.buildHeader();view.syncColumnControls()}finally{view.layoutApplying=false}
15
10
  if(mode==="cards"){const geometry=cardGeometry(view);cardStyle(view,geometry);view.rowH=geometry.height}
16
11
  else view.rowH=densityRowHeight(view,view.density);layoutRows(view,anchor);view.syncPinnedShadows?.()}
17
- function layoutApplyTree(view){const before=view.rowH,after=densityRowHeight(view,view.density);if(before!==after){const anchor=view.captureScrollAnchor();view.rowH=after;const status=row=>{if(row&&row.hpx===before)row.hpx=after};status(view.root._status);for(const row of view.keyMap.values()){if(!row.h?.detail&&row.hpx===before)row.hpx=after;status(row._status)}
18
- for(const row of view.rows)if(row.status)status(row);view.retop();if(anchor)view.restoreScrollAnchor(anchor)}
19
- view.fitKey=null;view.version++;if(view.fitReady)view.applyWidths();view.render()}
20
12
  function layoutApply(view,mode,density){const active=document.activeElement,held=view.canvas.contains(active)?active:null;const cell=held?.closest(".cx-cell"),row=view.focused,column=cell&&view.cols[view.rowCells(cell.parentNode).indexOf(cell)]?.id;view.layoutMode=mode;view.density=density;view.host.setAttribute("data-cx-density",density);if(mode==="fit")view.host.removeAttribute("data-cx-layout");else view.host.setAttribute("data-cx-layout",mode);view.host.style.setProperty("--cx-row-h",densityRowHeight(view,density)+ "px");if(view.kind==="grid")layoutApplyGrid(view,mode);else layoutApplyTree(view);if(held&&row&&view.rendered.get(row)){const at=column?view.cols.findIndex(item=>item.id===column):-1;if(at>=0)view.focusCell(row,at,null);else view.rendered.get(row).focus({preventScroll:true})}}
21
13
  const LAYOUT_ICON='<rect x="4" y="4" width="16" height="7" rx="1.5"/><rect x="4" y="13" width="16" height="7" rx="1.5"/>';let layoutSeq=0;function layoutGroup(view,legend,name,choices,current,choose){const group=h("div","cx-layout-group"),title=h("div","cx-layout-title");title.id=name+"-title";group.setAttribute("role","radiogroup");group.setAttribute("aria-labelledby",title.id);setText(title,legend);group.appendChild(title);for(const[value,text]of choices){const label=h("label","cx-layout-choice"),input=h("input");input.type="radio";input.name=name;input.value=value;input.checked=value===current;input.addEventListener("change",()=>{if(input.checked)choose(value)});label.append(input,document.createTextNode(text));group.appendChild(label)}
22
14
  return group}
@@ -24,7 +16,7 @@ function layoutModeText(view,mode){return view.labels[mode==="fit"?"layoutFit":m
24
16
  function layoutDensityText(view,density){return view.labels[density==="compact"?"layoutCompact":density==="comfortable"?"layoutComfortable":"layoutNormal"]}
25
17
  function layoutMenu(view){if(view.tools.layout===false||typeof view.controlPanel!=="function")return;const{details,panel}=view.controlPanel(view.labels.layoutMenu,"cx-grid-layout"),id=view.id+"-layout-" + ++layoutSeq;const icon=details.firstChild.querySelector("svg");if(icon)icon.replaceWith(svgIcon(LAYOUT_ICON));const choose=change=>Promise.resolve().then(()=>VIEW_MODES.setLayout(view,change)).catch(error=>view.emit("error",{error}));const render=()=>{const options=view.layoutOptions;if(panel.firstChild){for(const input of panel.querySelectorAll("input"))input.checked=input.value===view.layoutMode||input.value===view.density;return}
26
18
  panel.replaceChildren(...[options.modes.length>1&&layoutGroup(view,view.labels.layoutMenu,id+"-mode",options.modes.map(mode=>[mode,layoutModeText(view,mode)]),view.layoutMode,mode=>choose({mode})),layoutGroup(view,view.labels.layoutDensity,id+"-density",LAYOUT_DENSITIES.map(density=>[density,layoutDensityText(view,density)]),view.density,density=>choose({density}))].filter(Boolean))};render();view.layoutMenu={details,render};const anchor=view.toolbar.querySelector(".cx-grid-views")||view.spacer;if(anchor&&anchor.parentNode===view.toolbar)view.toolbar.insertBefore(details,anchor)}
27
- VIEW_MODES.layoutsStart=view=>{if(!view.layoutMenu)layoutMenu(view);if(!view.sortMenu)sortMenu(view);if(view.layoutStarted)return;view.layoutStarted=true;view.host.classList.add("cx-layouts");view.lifetime.signal.addEventListener("abort",()=>{view.host.classList.remove("cx-layouts");for(const name of["cols","span","pad","field","gap","title"])view.host.style.removeProperty("--cx-card-"+name)},{once:true});view.host.setAttribute("data-cx-density",view.density);if(view.layoutMode!=="fit"||view.kind==="grid"&&view.density!==view.declaredDensity)layoutApply(view,view.layoutMode,view.density)};VIEW_MODES.setLayout=(view,change)=>{if(!change||typeof change!=="object"||Array.isArray(change)||Object.keys(change).some(key=>!["mode","density"].includes(key))||
19
+ VIEW_MODES.layoutsStart=view=>{if(!view.layoutMenu)layoutMenu(view);if(!view.sortMenu)sortMenu(view);if(view.layoutStarted)return;view.layoutStarted=true;view.host.classList.add("cx-layouts");view.lifetime.signal.addEventListener("abort",()=>{view.host.classList.remove("cx-layouts");for(const name of["cols","span","pad","field","gap","title"])view.host.style.removeProperty("--cx-card-"+name)},{once:true});view.host.setAttribute("data-cx-density",view.density);if(view.layoutMode!=="fit"||view.kind==="grid"&&view.density!==view.declaredDensity)layoutApply(view,view.layoutMode,view.density)};VIEW_MODES.refreshCardDensity=view=>{const anchor=layoutAnchor(view),geometry=cardGeometry(view);cardStyle(view,geometry);view.rowH=geometry.height;view.version++;layoutRows(view,anchor)};VIEW_MODES.setLayout=(view,change)=>{if(!change||typeof change!=="object"||Array.isArray(change)||Object.keys(change).some(key=>!["mode","density"].includes(key))||
28
20
  change.mode!==undefined&&!view.layoutOptions.modes.includes(change.mode)||change.density!==undefined&&!LAYOUT_DENSITIES.includes(change.density))
29
21
  throw new Error("CanopyX: setLayout takes a mode the view allows and a density.");if(!view.layoutStarted)VIEW_MODES.layoutsStart(view);const mode=change.mode??view.layoutMode,density=change.density??view.density;if(mode!==view.layoutMode||density!==view.density){layoutApply(view,mode,density);view.layoutMenu?.render();view.sortMenu?.sync();if(view.live){setText(view.live,"");setText(view.live,fill(view.labels.layoutChanged,{mode:layoutModeText(view,mode),density:layoutDensityText(view,density)}))}
30
22
  view.stateChanged();view.emit("layout",{mode,density})}
@@ -1,16 +1,16 @@
1
1
  /* Linked views: external filter chips and highlighted rows. The info tone keeps both apart from the reader's own chips and selection. */
2
- .cx-has-linked,.cx-link-bar,.cx-link-chip{--cx-linked-bg:color-mix(in srgb,var(--cx-tone-info) 14%,var(--cx-surface));}
2
+ .cx-has-linked,.cx-link-bar,.cx-link-chip{--cx-linked-bg:color-mix(in srgb,var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7)) 14%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));}
3
3
  .cx-has-linked .cx-row[data-cx-linked="true"]{background:var(--cx-linked-bg);}
4
- .cx-has-linked .cx-row[data-cx-linked="true"][aria-selected="true"]{background:color-mix(in srgb,var(--cx-tone-info) 14%,var(--cx-selected-bg));}
4
+ .cx-has-linked .cx-row[data-cx-linked="true"][aria-selected="true"]{background:color-mix(in srgb,var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7)) 14%,var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435)));}
5
5
  .cx-has-linked .cx-row[data-cx-linked="true"] [data-cx-pin]{background:var(--cx-linked-bg);}
6
- .cx-has-linked .cx-row[data-cx-linked="true"] > :first-child{box-shadow:inset var(--cx-size-3px) 0 0 var(--cx-tone-info);}
6
+ .cx-has-linked .cx-row[data-cx-linked="true"] > :first-child{box-shadow:inset var(--cx-size-3px) 0 0 var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7));}
7
7
  .cx-link-bar{flex:none;display:flex;flex-wrap:wrap;gap:var(--cx-size-6px);padding:0 0 var(--cx-size-8px);min-width:0;}
8
- .cx-link-chip{max-width:100%;height:var(--cx-size-24px);min-height:var(--cx-size-24px);padding:0 var(--cx-size-9px);border:0;border-radius:var(--cx-size-12px);background:var(--cx-linked-bg);color:var(--cx-text);font:inherit;font-size:var(--cx-size-13px);white-space:nowrap;overflow:hidden;cursor:pointer;}
8
+ .cx-link-chip{max-width:100%;height:var(--cx-size-24px);min-height:var(--cx-size-24px);padding:0 var(--cx-size-9px);border:0;border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--cx-linked-bg);color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font:inherit;font-size:var(--cx-size-13px);white-space:nowrap;overflow:hidden;cursor:pointer;}
9
9
  .cx-data-grid .cx-link-chip.cx-grid-chip{background:var(--cx-linked-bg);}
10
- .cx-link-chip:hover{background:color-mix(in srgb,var(--cx-tone-info) 22%,var(--cx-surface));}
11
- .cx-link-chip:focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-1px);}
10
+ .cx-link-chip:hover{background:color-mix(in srgb,var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7)) 22%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));}
11
+ .cx-link-chip:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
12
12
  @media (forced-colors:active){
13
- .cx-has-linked .cx-row[data-cx-linked="true"]{outline:var(--cx-size-2px) dashed Highlight;outline-offset:var(--cx-size-neg-2px);}
13
+ .cx-has-linked .cx-row[data-cx-linked="true"]{outline:var(--cx-size-2px) dashed Highlight;outline-offset:calc(-1 * var(--hfx-focus-width,2px));}
14
14
  .cx-link-chip{border:var(--cx-size-1px) solid ButtonText;}
15
15
  }
16
16
  @media print{
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"fa0c9e888463553b",install(context){if(installed.has(context.LINK_IMPL))return;const{LINK_IMPL,h,setText,filterChipContent,fill,numberFormat,cellValue,setAttr,cellMatches}=context;const{TreeGrid,DataGrid}=LINK_IMPL;const LINK_SOURCE=/^[A-Za-z0-9][\w.:-]{0,127}$/, LINK_MAX_KEYS = 10000, LINK_MAX_VALUES = 1000;
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"e7268bbe59e2dfa8",install(context){if(installed.has(context.LINK_IMPL))return;const{LINK_IMPL,h,setText,filterChipContent,fill,numberFormat,cellValue,setAttr,cellMatches}=context;const{TreeGrid,DataGrid}=LINK_IMPL;const LINK_SOURCE=/^[A-Za-z0-9][\w.:-]{0,127}$/, LINK_MAX_KEYS = 10000, LINK_MAX_VALUES = 1000;
2
2
  const linkText=(value,name,max)=>{if(value===undefined)return undefined;if(typeof value!=="string"||!/\S/.test(value) || value.length > max) throw new Error("CanopyX: link " + name + " must be visible text of at most " + max + " characters.");
3
3
  return value};const linkIsoDate=value=>typeof value==="string"&&/^\d{4}-\d\d-\d\dT.*(?:Z|[+-]\d\d:\d\d)$/.test(value) && Number.isFinite(Date.parse(value));
4
4
  function linkColumn(grid,field){const column=grid.view.columns.find(item=>item.id===field);if(!column)throw new Error("CanopyX: a link names the undeclared column '"+field+"'.");return column}
@@ -1,20 +1,20 @@
1
1
  /* Live data: the order prompt sits in the toolbar (over the rows without one);changed cells flash (a still outline with reduced motion). */
2
2
  .cx-data-grid.cx-live-grid{position:relative;}
3
- .cx-data-grid .cx-live-bar{display:inline-flex;align-items:center;gap:var(--cx-size-6px);flex:none;max-width:100%;height:var(--cx-control-h);padding:0 var(--cx-size-2px) 0 var(--cx-size-10px);border-radius:var(--cx-radius);background:var(--cx-accent-soft);color:var(--cx-text);font-size:var(--cx-size-13d5px);white-space:nowrap;}
3
+ .cx-data-grid .cx-live-bar{display:inline-flex;align-items:center;gap:var(--cx-size-6px);flex:none;max-width:100%;height:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));padding:0 var(--cx-size-2px) 0 var(--cx-size-10px);border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font-size:var(--cx-size-13d5px);white-space:nowrap;}
4
4
  .cx-data-grid .cx-live-bar[hidden]{display:none;}
5
- .cx-data-grid .cx-live-bar.cx-live-float{position:absolute;left:50%;z-index:4;transform:translateX(-50%);max-width:calc(100% - var(--cx-size-24px));border:var(--cx-size-1px) solid var(--cx-line-strong);background:var(--cx-surface);box-shadow:var(--cx-panel-shadow);}
6
- .cx-data-grid .cx-live-bar .cx-ico{flex:none;width:var(--cx-size-16px);height:var(--cx-size-16px);color:var(--cx-accent);}
5
+ .cx-data-grid .cx-live-bar.cx-live-float{position:absolute;left:50%;z-index:4;transform:translateX(-50%);max-width:calc(100% - var(--cx-size-24px));border:var(--cx-size-1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));}
6
+ .cx-data-grid .cx-live-bar .cx-ico{flex:none;width:var(--cx-size-16px);height:var(--cx-size-16px);color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
7
7
  .cx-data-grid .cx-live-bar-text{overflow:hidden;text-overflow:ellipsis;}
8
- .cx-data-grid .cx-live-bar .cx-button{height:var(--cx-size-28px);min-height:var(--cx-size-28px);padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid color-mix(in srgb,var(--cx-accent) 45%,var(--cx-surface));border-radius:var(--cx-radius-sm);background:var(--cx-surface);color:var(--cx-text);font:inherit;font-size:var(--cx-size-13px);font-weight:600;cursor:pointer;}
9
- .cx-data-grid .cx-live-bar .cx-button:hover{background:color-mix(in srgb,var(--cx-accent) 10%,var(--cx-surface));}
10
- .cx-data-grid .cx-live-bar .cx-button:focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-1px);}
8
+ .cx-data-grid .cx-live-bar .cx-button{height:var(--cx-size-28px);min-height:var(--cx-size-28px);padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid color-mix(in srgb,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)) 45%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font:inherit;font-size:var(--cx-size-13px);font-weight:600;cursor:pointer;}
9
+ .cx-data-grid .cx-live-bar .cx-button:hover{background:color-mix(in srgb,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)) 10%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));}
10
+ .cx-data-grid .cx-live-bar .cx-button:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
11
11
  .cx-data-grid.cx-phone .cx-live-bar{height:var(--cx-size-44px);padding:0 0 0 var(--cx-size-8px);background:transparent;}
12
12
  .cx-data-grid.cx-phone .cx-live-bar:not(.cx-live-float) .cx-live-bar-text{position:absolute;width:var(--cx-size-1px);height:var(--cx-size-1px);overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
13
- .cx-data-grid.cx-phone .cx-live-bar .cx-button{height:var(--cx-size-44px);min-height:var(--cx-size-44px);min-width:var(--cx-size-44px);background:var(--cx-accent-soft);}
14
- @keyframes cx-live-flash{from{box-shadow:inset 0 0 0 var(--cx-size-999px) color-mix(in srgb,var(--cx-accent) 28%,transparent);}to{box-shadow:inset 0 0 0 var(--cx-size-999px) transparent;}}
13
+ .cx-data-grid.cx-phone .cx-live-bar .cx-button{height:var(--cx-size-44px);min-height:var(--cx-size-44px);min-width:var(--cx-size-44px);background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));}
14
+ @keyframes cx-live-flash{from{box-shadow:inset 0 0 0 var(--cx-size-999px) color-mix(in srgb,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)) 28%,transparent);}to{box-shadow:inset 0 0 0 var(--cx-size-999px) transparent;}}
15
15
  .cx-data-grid .cx-cell.cx-live-flash{animation:cx-live-flash var(--cx-live-flash-ms,1200ms) ease-out both;}
16
16
  @media (prefers-reduced-motion:reduce){
17
- .cx-data-grid .cx-cell.cx-live-flash{box-shadow:inset 0 0 0 var(--cx-size-2px) color-mix(in srgb,var(--cx-accent) 60%,transparent);}
17
+ .cx-data-grid .cx-cell.cx-live-flash{box-shadow:inset 0 0 0 var(--cx-size-2px) color-mix(in srgb,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)) 60%,transparent);}
18
18
  }
19
19
  @media (forced-colors:active){
20
20
  .cx-data-grid .cx-live-bar{border:var(--cx-size-1px) solid CanvasText;background:Canvas;color:CanvasText;}