@evotecit/canopyx 0.3.11 → 0.3.15

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 (102) 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-export.js +8 -4
  18. package/CanopyX.Html/Assets/canopyx-facets.css +33 -33
  19. package/CanopyX.Html/Assets/canopyx-facets.js +10 -11
  20. package/CanopyX.Html/Assets/canopyx-filter-editor.css +57 -57
  21. package/CanopyX.Html/Assets/canopyx-filter-editor.js +15 -11
  22. package/CanopyX.Html/Assets/canopyx-flow-checks.css +11 -11
  23. package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
  24. package/CanopyX.Html/Assets/canopyx-flow-command.css +7 -7
  25. package/CanopyX.Html/Assets/canopyx-flow-command.js +1 -1
  26. package/CanopyX.Html/Assets/canopyx-flow-dialog.css +7 -7
  27. package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
  28. package/CanopyX.Html/Assets/canopyx-flow-drafts.css +7 -7
  29. package/CanopyX.Html/Assets/canopyx-flow-drafts.js +1 -1
  30. package/CanopyX.Html/Assets/canopyx-flow-entry.css +17 -76
  31. package/CanopyX.Html/Assets/canopyx-flow-entry.js +9 -3
  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 +9 -3
  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 +1 -1
  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 +134 -77
  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 +134 -77
  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 +58 -24
  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 +4 -12
  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 +2 -2
  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 +58 -24
  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 +11 -0
  79. package/CanopyX.Html/Assets/canopyx-record-panel.css +49 -49
  80. package/CanopyX.Html/Assets/canopyx-record-panel.js +13 -11
  81. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +142 -84
  82. package/CanopyX.Html/Assets/canopyx-reporting.css +214 -276
  83. package/CanopyX.Html/Assets/canopyx-reporting.js +142 -84
  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 -46
  87. package/CanopyX.Html/Assets/canopyx-tree-tools.js +5 -4
  88. package/CanopyX.Html/Assets/canopyx.css +81 -142
  89. package/CanopyX.Html/Assets/canopyx.js +58 -24
  90. package/JavaScript/calendar.d.ts +15 -0
  91. package/JavaScript/grid.d.ts +29 -4
  92. package/JavaScript/hosts.d.ts +11 -0
  93. package/JavaScript/locales/de.mjs +5 -0
  94. package/JavaScript/locales/es.mjs +5 -0
  95. package/JavaScript/locales/fr.mjs +5 -0
  96. package/JavaScript/locales/it.mjs +5 -0
  97. package/JavaScript/locales/pl.mjs +5 -0
  98. package/JavaScript/plugins.d.ts +4 -0
  99. package/JavaScript/protocol.d.ts +14 -1
  100. package/JavaScript/records.d.ts +2 -0
  101. package/README.md +6 -2
  102. package/package.json +7 -1
@@ -26,14 +26,15 @@ function checkPage(doc,node){checkDocument(doc,"page");if(!Array.isArray(doc.ite
26
26
  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}
27
27
  function isCellObject(cell){return cell!==null&&typeof cell==="object"}
28
28
  function cellValue(cell){return isCellObject(cell)?(cell.value===undefined?null:cell.value):(cell===undefined?null:cell)}
29
- 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")) {
29
+ 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):"")+ ")"}
30
+ 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")) {
30
31
  return NO_TONE}
31
32
  const host=!/^(neutral|info|success|warning|danger|muted)$/.test(name);
32
33
  tone={cls:" cx-tone-"+name +(host?" cx-toned":""),host:host?name:null};if(tones.size<256)tones.set(name,tone)}
33
34
  return tone}
34
35
  function applyTone(element,base,tone){element.className=base+tone.cls;toneColors(element,tone)}
35
36
  function toneColors(element,tone){if((element._tone||null)===tone.host){return}
36
- 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")}}
37
+ 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")}}
37
38
  function pad2(value){return value<10?"0"+value:String(value)}
38
39
  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)}
39
40
  return texts}
@@ -46,9 +47,10 @@ if(typeof value==="boolean"){return value?fmt.labels.yes:fmt.labels.no}
46
47
  if(typeof value==="number"&&kind==="number"){return numberText(value,fmt.lang,format)}
47
48
  if(typeof value==="string"&&kind==="datetime"){return formatDate(value,fmt)}
48
49
  return String(value)}
49
- function cellText(cell,column,fmt){if(isCellObject(cell)&&typeof cell.text==="string"){return cell.text}
50
+ function cellText(cell,column,fmt){const raw=cellValue(cell);if(typeof raw==="string"&&Object.hasOwn(column.valueLabels||{},raw))return column.valueLabels[raw];if(isCellObject(cell)&&typeof cell.text==="string"){return cell.text}
50
51
  return formatValue(cellValue(cell),column.kind,fmt,column.format)}
51
- const collator=new Intl.Collator(undefined,{numeric:true,sensitivity:"base"});const safeGridNumber=value=>Number.isFinite(value)&&Math.abs(value)<=Number.MAX_SAFE_INTEGER;function sortKey(cell,column){let value=isCellObject(cell)&&(typeof cell.sort==="string"||safeGridNumber(cell.sort))?cell.sort:cellValue(cell);if((value===null||value==="")&&isCellObject(cell)&&typeof cell.text==="string"&&cell.text!==""){value=cell.text}
52
+ const collator=new Intl.Collator(undefined,{numeric:true,sensitivity:"base"});const safeGridNumber=value=>Number.isFinite(value)&&Math.abs(value)<=Number.MAX_SAFE_INTEGER;function sortKey(cell,column){if(column.valueOrder?.length){const raw=cellValue(cell);if(raw==null)return{rank:2,value:0};const at=typeof raw==="string"?column.valueOrder.indexOf(raw):-1;return{rank:1,category:at<0?column.valueOrder.length:at,type:typeof raw,value:raw}}
53
+ let value=isCellObject(cell)&&(typeof cell.sort==="string"||safeGridNumber(cell.sort))?cell.sort:cellValue(cell);if((value===null||value==="")&&isCellObject(cell)&&typeof cell.text==="string"&&cell.text!==""){value=cell.text}
52
54
  if(value===null||value===""){return{rank:2,value:0}}
53
55
  if(typeof value==="boolean"){return{rank:0,value:value?1:0}}
54
56
  if(typeof value==="number"){return{rank:0,value}}
@@ -56,7 +58,20 @@ if(column.kind==="datetime"){const time=Date.parse(value);if(!isNaN(time)){retur
56
58
  return{rank:1,value:String(value)}}
57
59
  function compareKeys(a,b,direction){if(a.rank!==b.rank){return a.rank-b.rank}
58
60
  if(a.rank===2){return 0}
59
- const order=a.rank===0?(a.value<b.value?-1:a.value>b.value?1:0):collator.compare(a.value,b.value);return order*direction}
61
+ const order=a.category!==undefined?a.category-b.category||
62
+ (a.type<b.type?-1:a.type>b.type?1:a.value<b.value?-1:a.value>b.value?1:0):
63
+ a.rank===0?(a.value<b.value?-1:a.value>b.value?1:0):collator.compare(a.value,b.value);return order*direction}
64
+ function columnNumericTone(column,raw){return typeof raw==="number"&&Number.isFinite(raw)?column.numericTones?.find(rule=>
65
+ rule.operator==="atMost"?raw<=rule.value:rule.operator==="atLeast"?raw>=rule.value:
66
+ rule.operator==="below"?raw<rule.value:raw>rule.value):undefined}
67
+ function columnValueTone(column,cell){const raw=cellValue(cell);return columnNumericTone(column,raw)?.tone||(typeof raw==="string"&&Object.hasOwn(column.valueTones||{},raw)?column.valueTones[raw]:undefined)}
68
+ function validateColumnValues(column){const fail=()=>{throw new Error("CanopyX: invalid column value labels, order, tones or line limit.")};const tone=value=>typeof value==="string"&&/^[a-z][a-z0-9-]{0,31}$/.test(value) && !value.endsWith("-bg");
69
+ if(column.maxLines!==undefined&&(!Number.isInteger(column.maxLines)||column.maxLines<1||column.maxLines>12))fail();for(const name of["valueLabels","valueTones"])if(column[name]!==undefined){const map=column[name];if(column.kind!=="text"||!map||typeof map!=="object"||Array.isArray(map)||Object.keys(map).length>512||
70
+ Object.entries(map).some(([key,value])=>key.length>4096||(name==="valueTones"?!tone(value):typeof value!=="string"||value.length>4096)))fail()}
71
+ if(column.valueOrder!==undefined&&(column.kind!=="text"||!Array.isArray(column.valueOrder)||column.valueOrder.length>512||
72
+ new Set(column.valueOrder).size!==column.valueOrder.length||column.valueOrder.some(value=>typeof value!=="string"||value.length>4096)))fail();if(column.numericTones!==undefined&&(column.kind!=="number"||!Array.isArray(column.numericTones)||column.numericTones.length>32||
73
+ column.numericTones.some(rule=>!rule||!["atMost","atLeast","below","above"].includes(rule.operator)||!Number.isFinite(rule.value)||
74
+ !tone(rule.tone)||typeof rule.label!=="string"||!rule.label.trim()||rule.label.length>4096)))fail()}
60
75
  function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, name) => (values && Object.hasOwn(values, name) ? String(values[name]) : match));
61
76
  }
62
77
  const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
@@ -76,6 +91,12 @@ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.
76
91
  catch(_){trustPolicy=null}}
77
92
  return trustPolicy?trustPolicy["create"+kind](value):value}
78
93
  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.")}
94
+ 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}}}
95
+ 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}
96
+ 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)}
97
+ 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)}
98
+ return copied}
99
+ 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}
79
100
  DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridMore:"More",gridPrint:"Print",gridDetails:"Record details",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close"}));DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{recordBack:"Back",recordBackTo:"Back to {record}",recordTrail:"Record trail",recordShowing:"Showing {record}",recordTabs:"Record views",recordSections:"Jump to a section",recordOtherFields:"Other fields",recordShowEmpty:"Show empty fields ({count})",recordHideEmpty:"Hide empty fields",recordActions:"Record actions",recordCopyValues:"Copy values",recordCopyJson:"Copy as JSON",recordCopyLink:"Copy link",recordCopied:"Copied to the clipboard",recordPrint:"Print record",recordExportCsv:"Export CSV",recordExportJson:"Export JSON",recordOpenAll:"Open all in grid",recordLoadMore:"Load more",recordCount:"{shown} of {total}",recordItems:"{count} items",recordMore:"+{count}",recordShowAll:"Show all {count}",recordRetry:"Retry",recordLoadFailed:"Could not load the record details: {error}",recordUnavailable:"Record {id} is not available here.",recordField:"Field",recordValue:"Value",recordSection:"Section",recordBefore:"Before",recordAfter:"After",recordAdded:"Added",recordRemoved:"Removed",recordChanged:"{count} changed fields"}));function boundedPattern(source,exact=true,whole=false){const bad=()=>{throw new Error("CanopyX: pattern requires literals, character classes and at most one variable repetition anchored at the start; groups, alternatives and backreferences are unsupported.")};if(typeof source!=="string"||source.length>256)bad();let width=0,variable=0;for(let i=0;i<source.length;){const unit=source[i++];if(unit==="^"&&i===1||unit==="$"&&i===source.length)continue;if(unit==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbBnrtfv\\.^$*+?{}\[\]()|/]$/.test(escape)) bad();
80
101
  }else if(unit==="["){let closed=false;while(i<source.length){const c=source[i++];if(c==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbnrtfv\\.^$*+?{}\[\]()|/-]$/.test(escape)) bad(); }
81
102
  else if(c==="]"){closed=true;break}}
@@ -119,7 +140,8 @@ if(column.kind==="datetime"){const date=typeof value==="string"&&/^\d{4}-\d\d-\d
119
140
  if(!Number.isFinite(date))
120
141
  throw new Error("CanopyX: date grid cells need ISO dates with an explicit time zone.");return date}
121
142
  if(typeof value!=="string"&&typeof value!=="boolean")throw new Error("CanopyX: text grid cells need strings or booleans.");return value}
122
- function cellMatches(cell,predicate,column){const scalar=gridScalar(cell,column),op=predicate.operator;if(op==="isNull")return scalar===null;if(op==="isNotNull")return scalar!==null;if(scalar===null)return false;const normalize=value=>column.kind==="text"&&typeof value==="string"?foldText(value):value;const value=normalize(scalar),values=predicate.values.map(operand=>normalize(gridScalar(operand,column))),operand=values[0];switch(op){case "eq":return value===operand;case "ne":return value!==operand;case "in":return values.includes(value);case "contains":return String(value).includes(String(operand));case "startsWith":return String(value).startsWith(String(operand));case "gt":return value>operand;case "ge":return value>=operand;case "lt":return value<operand;case "le":return value<=operand}
143
+ function gridExactTokens(column){return column.kind==="text"&&(column.valueOrder?.length||Object.keys(column.valueLabels||{}).length)}
144
+ function cellMatches(cell,predicate,column){const scalar=gridScalar(cell,column),op=predicate.operator;if(op==="isNull")return scalar===null;if(op==="isNotNull")return scalar!==null;if(scalar===null)return false;const normalize=value=>column.kind==="text"&&!gridExactTokens(column)&&typeof value==="string"?foldText(value):value;const value=normalize(scalar),values=predicate.values.map(operand=>normalize(gridScalar(operand,column))),operand=values[0];switch(op){case "eq":return value===operand;case "ne":return value!==operand;case "in":return values.includes(value);case "contains":return String(value).includes(String(operand));case "startsWith":return String(value).startsWith(String(operand));case "gt":return value>operand;case "ge":return value>=operand;case "lt":return value<operand;case "le":return value<=operand}
123
145
  return false}
124
146
  function validateGridRows(rows,columns,ids=new Set()){if(!Array.isArray(rows))throw new Error("CanopyX: grid rows must be an array.");const declared=new Map(columns.map(column=>[column.id,column]));for(const row of rows){requireIdentifier(row&&row.id,"grid row ID");if(ids.has(row.id))throw new Error("CanopyX: duplicate grid row ID "+row.id);ids.add(row.id);if(!row.cells||typeof row.cells!=="object"||Array.isArray(row.cells))
125
147
  throw new Error("CanopyX: invalid flat row fields.");gridDecoration(row.tone,row.className);for(const id of Object.keys(row.cells)){if(!declared.has(id))throw new Error("CanopyX: undeclared grid column "+id);const cell=row.cells[id];if(isCellObject(cell)){if(Array.isArray(cell)||
@@ -191,9 +213,9 @@ throw new Error("CanopyX: unknown source kind '"+kind+"'.")}
191
213
  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)}
192
214
  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))}}
193
215
  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.")}
194
- 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"))
216
+ 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"))
195
217
  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.")}
196
- 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.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||[]}
218
+ 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||[]}
197
219
  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()}
198
220
  async search(query,limit){if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");const navigation=navigationScope(this,this.dataLifetime.signal);try{const result=await navigation.wait(this.source.search(query,limit,this.sourceRequest(this.dataLifetime.signal)));if(navigation.cancelled())throw new DOMException("Search snapshot was retired.","AbortError");if(this.queryAware)snapshotRevision(result,this.datasetRevision);return validateSearchResult(result)}finally{navigation.dispose()}}
199
221
  buildIcons(icons){const templates=new Map();Object.keys(icons).forEach((key)=>{const holder=h("span","cx-icon");holder.setAttribute("aria-hidden","true");hostHtml(holder,icons[key],this.opts.sanitizeHtml,"icon");// trusted host SVG, declared once per view
@@ -258,10 +280,9 @@ value.sort===undefined||typeof value!=="object")throw new Error("CanopyX: query
258
280
  const named=new Set(value.filters);if(named.size!==value.filters.length||value.filters.some(id=>!(grid.view.filters||[]).some(f=>f.id===id)))
259
281
  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})}
260
282
  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}
261
- 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")}
262
- 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")}
283
+ 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")}
263
284
  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++}
264
- 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);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";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");setText(title,column.title);cell.appendChild(title)}
285
+ 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)}
265
286
  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}}
266
287
  return Math.max(0,lo)},indexOf(w){const i=w?w._ri:undefined;return i!==undefined&&this.rows[i]===w?i:-1},render(){let measured=false;for(let pass=0;!this.destroyed;pass++){this.renderPass();if(!this.measureDetails())break;measured=true;if(pass===3){this.scheduleRender();break}}
267
288
  return measured}});function columnWidth(column,width){return Math.min(column.maxW,Math.max(column.minW,width))}
@@ -311,13 +332,13 @@ this.paintSlot(slot,node,this.cols[i],this.columnIndex[i],w)}},paintRowState(row
311
332
  const expander=this.expandable(w)?"cx-exp":"cx-exp cx-leaf";if(slot.expCls!==expander){slot.exp.className=expander;slot.expCls=expander}
312
333
  const key=w.h.icon&&this.iconTemplates.has(w.h.icon)?w.h.icon:null;if(slot.iconKey!==key){if(slot.iconEl){slot.iconEl.remove()}
313
334
  slot.iconEl=key?this.iconTemplates.get(key).cloneNode(true):null;if(slot.iconEl){slot.cell.insertBefore(slot.iconEl,slot.content)}
314
- slot.iconKey=key}},cellTip(event){const cell=event.target.closest?.(".cx-cell"),row=cell?.parentNode._kind==="node"&&cell.parentNode._w;const column=row&&!row.status&&this.cols[[...cell.parentNode.children].indexOf(cell)],tip=column?.tooltip;const source=tip==="auto"?column:this.columns.find(item=>item.id===tip);if(!source||cell.title&&!cell._cxTip)return;cell._cxTip=true;cell.title=tip!=="auto"||[cell,...cell.querySelectorAll("*")].some(item=>item.scrollWidth>item.clientWidth)?
335
+ slot.iconKey=key}},cellTip(event){const cell=event.target.closest?.(".cx-cell"),row=cell?.parentNode._kind==="node"&&cell.parentNode._w;const column=row&&!row.status&&this.cols[[...cell.parentNode.children].indexOf(cell)],tip=column?.tooltip;const source=tip==="auto"?column:this.columns.find(item=>item.id===tip);if(!source||cell.title&&!cell._cxTip)return;cell._cxTip=true;cell.title=tip!=="auto"||[cell,...cell.querySelectorAll("*")].some(item=>item.scrollWidth>item.clientWidth||item.scrollHeight>item.clientHeight)?
315
336
  cellText(this.cellOf(row.h,source,this.columns.indexOf(source)),source,this.fmt):""},paintSlot(slot,node,column,index,w){const value=this.cellOf(node,column,index);if(slot.cell._cxTip){slot.cell._cxTip=false;slot.cell.removeAttribute("title");slot.title=null}
316
337
  const hosted=column.render?this.paintHostSlot(slot,node,column,index,w):null;if(hosted==="host"){return}
317
338
  const decorated=hosted==="decorated";const text=cellText(value,column,this.fmt);if(slot.text.data!==text){slot.text.data=text}
318
- const object=isCellObject(value);const tone=object?toneOf(value.tone):NO_TONE;const cls=slot.base+tone.cls;if(slot.cls!==cls){if(decorated){if(tone.cls)slot.cell.className +=tone.cls}else{slot.cell.className=cls}
339
+ const object=isCellObject(value);const rule=columnNumericTone(column,cellValue(value));const tone=toneOf(columnValueTone(column,value)||(object?value.tone:null));const cls=slot.base+tone.cls;if(slot.cls!==cls){if(decorated){if(tone.cls)slot.cell.className +=tone.cls}else{slot.cell.className=cls}
319
340
  slot.cls=cls}
320
- toneColors(slot.cell,tone);const title=object&&value.title?value.title:decorated?null:otherZone(value,column,this.fmt);if(slot.title!==title){if(title){slot.cell.title=title}else{slot.cell.removeAttribute("title")}
341
+ toneColors(slot.cell,tone);const title=object&&value.title?value.title:decorated?null:rule?.label||otherZone(value,column,this.fmt);setAttr(slot.cell,"aria-description",rule?.label||null);if(slot.title!==title){if(title){slot.cell.title=title}else{slot.cell.removeAttribute("title")}
321
342
  slot.title=title}
322
343
  this.paintBadges(slot,(index===0&&node.badges)||null,object&&value.badges?value.badges:null)},paintBadges(slot,first,second){const count=(first?first.length:0)+(second?second.length:0);for(let k=0;k<count;k++){const badge=first&&k<first.length?first[k]:second[k -(first?first.length:0)];let span=slot.badges[k];if(!span){span=slot.content.appendChild(h("span"));span._text=span.appendChild(document.createTextNode(""));slot.badges.push(span)}
323
344
  const tone=toneOf(badge.tone||"neutral");if(span._cls!==tone.cls){applyTone(span,"cx-badge",tone);span._cls=tone.cls}
@@ -506,7 +527,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
506
527
  active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
507
528
  close()}else{return}
508
529
  e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
509
- const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["bbcdb89bb78ede8b","canopyx-tree-tools.8f90c97d2d2dda86.js","canopyx-tree-tools.ef7a3fb9c9115a82.css"],"export":["8b99c0b7b0ec37c5","canopyx-export.6989ea36f5d6da7b.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["fa0c9e888463553b","canopyx-link.4ec39bc39fa6cf50.js","canopyx-link.8435c892613926ac.css"],"highlight":["f39423961654c1e2","canopyx-highlight.a6f93893d36ab343.js","canopyx-highlight.5b6d2e0d979f9f9b.css"],"layouts":["fa8c686f21626884","canopyx-layouts.e7250c82a6abf52e.js","canopyx-layouts.0b75738924533ee8.css"],"record-panel":["bcc06276c7933af6","canopyx-record-panel.a374fb4254f9115c.js","canopyx-record-panel.f3691d54cefaab04.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
530
+ 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":["94adeb844689e329","canopyx-record-panel.d0d71d38743e3476.js","canopyx-record-panel.66edd824ab6111c1.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
510
531
  function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
511
532
  part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
512
533
  function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
@@ -516,7 +537,7 @@ const load=(element,attribute,file,kind)=>new Promise((resolve,reject)=>{const u
516
537
  .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")
517
538
  .finally(()=>script.remove()).catch(error=>{part.scriptReady=null;throw error}));await Promise.all([style,code])}}
518
539
  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})}
519
- 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}));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)}
540
+ 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)}
520
541
  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")
521
542
  throw new Error("CanopyX: invalid state column.");seen.add(c.id);return{id:c.id,width:c.width,hidden:c.hidden}}
522
543
  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})})}
@@ -530,9 +551,9 @@ catch(error){/* Nodes removed since the snapshot are skipped. */ }
530
551
  }},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"&&
531
552
  (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))||
532
553
  ["requires","views","toolbarItems","menuItems","exportFormats","recordActions"].some(key=>item[key]!==undefined&&!Array.isArray(item[key]))||
533
- ["cellRenderers","columnTypes","editors","events","aggregates","detailRenderers","drawerSections"].some(key=>item[key]!==undefined&&Object(item[key])!==item[key])||
554
+ ["cellRenderers","columnTypes","editors","events","aggregates","detailRenderers","drawerSections","filterOperators","sortComparators"].some(key=>item[key]!==undefined&&Object(item[key])!==item[key])||
534
555
  !(item.requires||[]).every(partName)||!(item.views||[]).every(kind=>kind==="tree"||kind==="grid")||
535
- ![...Object.values(item.cellRenderers||{}),...Object.values(item.events||{}),...Object.values(item.detailRenderers||{}),...Object.values(item.drawerSections||{})].every(fn)||
556
+ ![...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)||
536
557
  !(item.toolbarItems||[]).every(entry())||!(item.recordActions||[]).every(entry())||!(item.menuItems||[]).every(entry(true)))
537
558
  throw new Error("CanopyX: invalid plugin '"+item.name+"'.");item.exportFormats?.forEach(exportFormat);return item}
538
559
  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())}}}
@@ -570,14 +591,27 @@ finally{navigation.dispose()}
570
591
  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.
571
592
  }
572
593
  this.linkChanged=this.dataLifetime.signal;return this.ready.then(()=>undefined,()=>undefined)}
573
- 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));
594
+ return this.openDeepLink()};function sharedDensity(host){const value=host.closest("[data-hfx-density]")?.getAttribute("data-hfx-density");return value==="compact"||value==="comfortable"?value:null}
595
+ 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"]})}
596
+ view.lifetime.signal.addEventListener("abort",()=>observer.disconnect(),{once:true})}
597
+ 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)) };
598
+ }
599
+ 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()}
600
+ 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)}
601
+ 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)))}
602
+ view.render()}
603
+ 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)}
604
+ for(const row of view.rows)if(row.status)status(row);view.retop();if(anchor)view.restoreScrollAnchor(anchor)}
605
+ view.fitKey=null;view.version++;if(view.fitReady)view.applyWidths();view.render()}
606
+ 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?.()}
607
+ 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));
574
608
  }).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})}}
575
609
  linkMethods(TreeGrid);function linkGridPart(View){(Object.hasOwn(View.prototype,"parts")?View.prototype.parts:View.prototype.parts={}).link=LINK_PART}
576
610
  function linkReady(grid,ready){return Promise.all([ready,grid.linkStart()]).then(([result])=>result)}
577
611
  function linkApi(grid){const api={};for(const name of LINK_METHODS.concat("getExternalFilters","getHighlight"))api[name]=(...args)=>grid[name](...args);return api}
578
- 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}));function loadRecordPanel(){return loadPart(RECORD_PART)}
612
+ 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)}
579
613
  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}))}
580
- 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");
614
+ 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");
581
615
  if(!options||typeof options!=="object"||Array.isArray(options)||Object.keys(options).some(key=>!HIGHLIGHT_KEYS.includes(key))||
582
616
  HIGHLIGHT_KEYS.slice(0,5).some(key=>options[key]!==undefined&&typeof options[key]!=="boolean")||
583
617
  options.minLength!==undefined&&(!Number.isInteger(options.minLength)||options.minLength<1||options.minLength>32)||
@@ -593,12 +627,12 @@ function readModeState(view,state){const result={};if(state.layout!==undefined){
593
627
  throw new Error("CanopyX: invalid saved layout.");if(options)result.layout={mode:options.modes.includes(layout.mode)?layout.mode:options.mode,density:layout.density}}
594
628
  if(state.highlight!==undefined){if(typeof state.highlight!=="boolean")throw new Error("CanopyX: invalid saved highlight choice.");if(view.highlightOptions)result.highlight=state.highlight}
595
629
  return result}
596
- function densityRowHeight(view,density){const steps=DENSITY_STEP[view.kind];return Math.max(20,Math.min(64,view.baseRowH+steps[density]- steps[view.declaredDensity]))}
597
- 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}
630
+ 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]))}
631
+ 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}
598
632
  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))
599
633
  this.setLayout(state.layout).catch(error=>this.emit("error",{error}));if(state.highlight!==undefined&&state.highlight!==!!this.highlightOn)
600
634
  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))
601
- .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})}
635
+ .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})}
602
636
  function checkBranch(){return{value:null,mask:0,children:new Map()}}
603
637
  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)}
604
638
  if(branch.value!==null)throw new Error("CanopyX: a checking path cannot have duplicate intents.");branch.value=item.checked}
@@ -2,8 +2,8 @@
2
2
  .cx-data-grid .cx-grid-pager [hidden]{display:none !important;}
3
3
  .cx-data-grid .cx-grid-pager .cx-pages{display:inline-flex;align-items:center;gap:var(--cx-size-4px);}
4
4
  .cx-data-grid .cx-grid-pager .cx-pages .cx-button{width:auto;min-width:var(--cx-size-30px);padding:0 var(--cx-size-8px);font-variant-numeric:tabular-nums;}
5
- .cx-data-grid .cx-grid-pager .cx-pages .cx-button[aria-current="page"]{border-color:var(--cx-accent);background:var(--cx-accent-soft);color:var(--cx-accent-text);font-weight:600;}
6
- .cx-data-grid .cx-grid-pager .cx-gap{min-width:var(--cx-size-16px);text-align:center;color:var(--cx-muted);}
5
+ .cx-data-grid .cx-grid-pager .cx-pages .cx-button[aria-current="page"]{border-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));font-weight:600;}
6
+ .cx-data-grid .cx-grid-pager .cx-gap{min-width:var(--cx-size-16px);text-align:center;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
7
7
  .cx-phone .cx-grid-pager .cx-pages .cx-button{min-width:var(--cx-size-44px);}
8
8
  @media (forced-colors:active){
9
9
  .cx-data-grid .cx-grid-pager .cx-pages .cx-button[aria-current="page"]{border-color:Highlight;outline:var(--cx-size-2px) solid Highlight;}
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"8f804f70b96409f2",install(context){if(installed.has(context.GRID_PAGER_IMPL))return;const{DataGrid,GRID_PAGER_IMPL,h,setText,fill,gridButton,gridOption,numberFormat,gridCountLabel}=context;const BUILD_PAGER=DataGrid.prototype.buildPager,SYNC_PAGER=DataGrid.prototype.syncPager;const PAGER_INFO=["range","sentence","none"];function pagerSettings(view){const pager=view.pager,fail=name=>{throw new Error("CanopyX: invalid pager "+name+".")};if(!pager||typeof pager!=="object"||Array.isArray(pager))fail("settings");const flag=(name,fallback)=>{if(pager[name]!==undefined&&typeof pager[name]!=="boolean")fail(name);return pager[name]===undefined?fallback:pager[name]};const numbers=pager.numbers===undefined?0:pager.numbers;if(!Number.isInteger(numbers)||numbers!==0&&(numbers<5||numbers>15))fail("numbers");if(pager.info!==undefined&&!PAGER_INFO.includes(pager.info))fail("info");let lengths=null;if(pager.lengths!==undefined){if(!Array.isArray(pager.lengths)||!pager.lengths.length||pager.lengths.length>16)fail("lengths");const seen=new Set();lengths=pager.lengths.map(entry=>{const item=entry!==null&&typeof entry==="object"?entry:{value:entry};if(item.value!=="all"&&!(Number.isInteger(item.value)&&item.value>=1&&item.value<=10000)||seen.has(item.value)||
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"3dcab112113081dd",install(context){if(installed.has(context.GRID_PAGER_IMPL))return;const{DataGrid,GRID_PAGER_IMPL,h,setText,fill,gridButton,gridOption,numberFormat,gridCountLabel}=context;const BUILD_PAGER=DataGrid.prototype.buildPager,SYNC_PAGER=DataGrid.prototype.syncPager;const PAGER_INFO=["range","sentence","none"];function pagerSettings(view){const pager=view.pager,fail=name=>{throw new Error("CanopyX: invalid pager "+name+".")};if(!pager||typeof pager!=="object"||Array.isArray(pager))fail("settings");const flag=(name,fallback)=>{if(pager[name]!==undefined&&typeof pager[name]!=="boolean")fail(name);return pager[name]===undefined?fallback:pager[name]};const numbers=pager.numbers===undefined?0:pager.numbers;if(!Number.isInteger(numbers)||numbers!==0&&(numbers<5||numbers>15))fail("numbers");if(pager.info!==undefined&&!PAGER_INFO.includes(pager.info))fail("info");let lengths=null;if(pager.lengths!==undefined){if(!Array.isArray(pager.lengths)||!pager.lengths.length||pager.lengths.length>16)fail("lengths");const seen=new Set();lengths=pager.lengths.map(entry=>{const item=entry!==null&&typeof entry==="object"?entry:{value:entry};if(item.value!=="all"&&!(Number.isInteger(item.value)&&item.value>=1&&item.value<=10000)||seen.has(item.value)||
2
2
  item.label!==undefined&&(typeof item.label!=="string"||!item.label.trim()||item.label.length>64))fail("lengths");seen.add(item.value);return{value:item.value,label:item.label}}).filter(item=>item.value!=="all"||view.source.kind==="inline")}
3
3
  return{lengths,numbers,info:pager.info||"range",lengthMenu:flag("lengthMenu",true),pageInput:flag("pageInput",!numbers),firstLast:flag("firstLast",true)}}
4
4
  function pagerWindow(current,count,max){const range=(start,end)=>Array.from({length:Math.max(0,end-start)},(_,index)=>start+index);if(count<=max)return range(0,count);if(current<max-3)return[...range(0,max-2),null,count-1];if(current>count-max+2)return[0,null,...range(count-max+2,count)];const inner=max-4,start=current-Math.floor((inner-1)/ 2);
@@ -0,0 +1,11 @@
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"4337e3756b443220",install(context){if(installed.has(context.GRID_PRESENTER_IMPL))return;const{GRID_PRESENTER_IMPL,h,setText,fill,cellValue,cellText,isCellObject,columnNumericTone,columnValueTone,gridPresenterTone,gridPresenterLink,numberFormat,toneColors,toneOf,applyTone,gridIcon,badgeElement,GRID_HISTORY_KINDS,GRID_HISTORY_IMPL,RECORD_IMPL}=context;function gridRenderPresenter(grid,column,options,record,complete){return(row,element)=>{const cell=row.cells[column.id],raw=cellValue(cell),text=cellText(cell,column,grid.fmt),object=isCellObject(cell);const rule=columnNumericTone(column,raw),declaredTone=columnValueTone(column,cell),tone=declaredTone||gridPresenterTone(options,raw,object?cell.tone:null);element.classList.add("cx-presented-cell");if(rule||object&&cell.title)element.title=rule?.label||cell.title;if(declaredTone)applyTone(element,element.className,toneOf(declaredTone));if(rule)element.setAttribute("aria-description",rule.label);const add=(value,cls="cx-presenter-text",tag="span")=>{const item=h(tag,cls),textItem=/^(cx-presenter-text|p-mono|p-link|cx-wrapped-text|p-muted)\b/.test(cls);setText(item,value);
2
+ if(declaredTone&&textItem)item.style.color="inherit";if(column.wrap&&textItem){item.classList.add("cx-wrapped-text");item.style.maxWidth="100%";item.style.flex="none";item.title=rule?.label||String(value);if(complete){item.style.webkitLineClamp="unset";item.style.maxHeight="none"}
3
+ else{const lines=record?column.maxLines??2:grid.layoutMode==="cards"?Math.min(column.maxLines??2,2):grid.autoRows?column.maxLines??2:1;item.style.webkitLineClamp=String(lines);item.style.maxHeight=lines*1.4+"em"}}
4
+ element.appendChild(item);return item};const more=(value,label=grid.labels.gridShowMore)=>{const button=add(label,"cx-link cx-presenter-expand","button");button.type="button";button.setAttribute("aria-haspopup","dialog");button.setAttribute("aria-label",fill(grid.labels.gridExpandCell,{column:column.title}));button.addEventListener("click",()=>grid.showReportingText(column,value,button,row.id,options.mono));return button};if(GRID_HISTORY_KINDS.includes(options.kind)){if(GRID_HISTORY_IMPL.render)GRID_HISTORY_IMPL.render(grid,column,options,cell,element,text);else grid.loadHistory()}else if(options.kind==="structured"){if(RECORD_IMPL.summary)RECORD_IMPL.summary(grid,column,options,row,element,text);else{add(text);grid.loadRecordPanel()}}else if(raw==null&&object&&cell.text==="")add("");else if(raw==null&&(!object||cell.text===undefined)||text==="")add("—","p-missing");else if(options.kind==="link"){const href=gridPresenterLink(cellValue(options.hrefColumn?row.cells[options.hrefColumn]:cell));const link=add(text,"p-link",href?"a":"span");if(href){link.href=href;if(options.newWindow){link.target="_blank";link.rel="noopener noreferrer"}}}else if(options.kind==="icon"){add(options.glyph,"cx-presenter-icon").setAttribute("aria-hidden","true");add(text)}
5
+ else if(options.kind==="boolean"&&typeof raw==="boolean"){const value=add(raw?"":"—",raw?"p-bool-yes"+(options.inverted?" cx-bool-bad":""):"p-bool-no");value.setAttribute("role","img");value.setAttribute("aria-label",raw?grid.labels.yes:grid.labels.no);if(raw)value.appendChild(gridIcon("check"))}else if(options.kind==="state"||options.kind==="enum"){if(options.quietTones?.includes(tone))add(text,(options.quietStyle==="plain"?"cx-presenter-text":"p-muted")+(options.kind==="enum"?" p-inset":""));else if(options.kind==="state"){const state=add("","p-state"+(tone==="success"?" quiet":""));const dot=h("span","p-dot "+(tone==="success"?"quiet":tone));toneColors(dot,toneOf(tone));state.append(dot,document.createTextNode(text))}else{const pill=add(text,"p-pill "+tone);applyTone(pill,pill.className,toneOf(tone))}}else if(options.kind==="change"){const delta=cellValue(row.cells[options.deltaColumn]);if(typeof delta==="number")add((delta===0?"":delta>0?"↑ ":"↓ ")+numberFormat(grid.lang).format(Math.abs(delta)),"p-delta "+(delta===0?"flat":(delta>0)===!!options.higherIsGood?"good":"bad"));add(text)}else if(options.kind==="progress"&&typeof raw==="number"){const box=add("","p-progress"),track=h("span","track"),bar=h("span","fill "+tone),maximum=options.maximum||100;track.setAttribute("role","progressbar");track.setAttribute("aria-label",column.title);track.setAttribute("aria-valuemin","0");track.setAttribute("aria-valuemax",String(maximum));track.setAttribute("aria-valuenow",String(Math.min(maximum,Math.max(0,raw))));track.setAttribute("aria-valuetext",text);bar.style.width=Math.min(100,Math.max(0,raw/maximum*100))+"%";toneColors(bar,toneOf(tone));track.appendChild(bar);box.append(track,document.createTextNode(text));
6
+ }else if(options.kind==="identifier"){add(text,options.mono?"p-mono":"cx-presenter-text");const secondary=options.secondaryColumn?cellText(row.cells[options.secondaryColumn],grid.columns.find(item=>item.id===options.secondaryColumn),grid.fmt):object&&cell.secondary;if(secondary)add(secondary,"p-sub")}else if(options.kind==="tags"||options.kind==="list"){const values=text.split(options.separator).map(item=>item.trim()).filter(Boolean),limit=options.kind==="tags"?3:options.limit||3;const preview=add("","cx-tag-list");element.classList.add("cx-list-cell");for(const value of values.slice(0,limit)){const tag=h("span","p-tag");setText(tag,value);preview.appendChild(tag)}
7
+ if(values.length>limit||options.kind==="list")more(text,values.length>limit?"+"+(values.length-limit):grid.labels.gridShowMore)}else if(options.kind==="longText"){if(column.wrap){add(text,"cx-wrapped-text"+(options.mono?" p-mono":""))}else{const budget=Math.max(256,Math.ceil((column.renderWidth||column.width)/7*5));
8
+ const preview=add(text.length>budget?text.slice(0,budget).replace(/[\uD800-\uDBFF]$/,"")+" …":text,"cx-wrapped-text"+(options.mono?" p-mono":""));
9
+ if(!grid.autoRows)element.classList.add("cx-fixed-text");if(!column.wrap||text.length>Math.max(40,(column.renderWidth||column.width)/7*4)||text.split("\n").length>4){element.classList.add("cx-clamped");more(text);}
10
+ }}else add(text);if(object)for(const badge of cell.badges||[])element.appendChild(badgeElement(badge));return true}}
11
+ GRID_PRESENTER_IMPL.create=gridRenderPresenter;installed.add(context.GRID_PRESENTER_IMPL)}};(global.CanopyXParts||=[]).push(["presenters",part])})(typeof window!=="undefined"?window:globalThis);
@@ -1,93 +1,93 @@
1
1
  /* ---------- record panel: the rich record drawer of flat grids and trees ---------- */
2
2
  body .cx-host.cx-drawer.cx-record-drawer{max-width:var(--cx-size-640px);}
3
- .cx-record-btn{display:inline-flex;align-items:center;gap:var(--cx-size-6px);min-height:var(--cx-size-28px);padding:0 var(--cx-size-8px);border:var(--cx-size-1px) solid transparent;border-radius:var(--cx-radius-sm);background:transparent;color:inherit;font:inherit;cursor:pointer;text-align:start;}
4
- .cx-record-btn:hover{background:var(--cx-hover-bg);}
5
- .cx-drawer :is(.cx-record-btn,.cx-record-tab):focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-1px);}
3
+ .cx-record-btn{display:inline-flex;align-items:center;gap:var(--cx-size-6px);min-height:var(--cx-size-28px);padding:0 var(--cx-size-8px);border:var(--cx-size-1px) solid transparent;border-radius:var(--hfx-radius-sm,4px);background:transparent;color:inherit;font:inherit;cursor:pointer;text-align:start;}
4
+ .cx-record-btn:hover{background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));}
5
+ .cx-drawer :is(.cx-record-btn,.cx-record-tab):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);}
6
6
  .cx-record-btn .cx-ico{width:var(--cx-size-16px);height:var(--cx-size-16px);flex:none;stroke:currentColor;fill:none;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round;}
7
- .cx-drawer .cx-record-link{min-height:0;padding:0;border:0;color:var(--cx-accent-text);text-decoration:underline;text-underline-offset:var(--cx-size-2px);overflow-wrap:anywhere;}
7
+ .cx-drawer .cx-record-link{min-height:0;padding:0;border:0;color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));text-decoration:underline;text-underline-offset:var(--cx-size-2px);overflow-wrap:anywhere;}
8
8
  .cx-drawer .cx-record-link:hover{background:transparent;text-decoration-thickness:var(--cx-size-2px);}
9
- .cx-record-trail{display:flex;align-items:center;gap:var(--cx-size-8px);min-width:0;margin:0 0 var(--cx-size-4px);font-size:var(--cx-size-13px);color:var(--cx-muted);}
10
- .cx-drawer .cx-record-back{min-height:0;padding:0 var(--cx-size-4px) 0 0;color:var(--cx-accent-text);font-weight:600;}
9
+ .cx-record-trail{display:flex;align-items:center;gap:var(--cx-size-8px);min-width:0;margin:0 0 var(--cx-size-4px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
10
+ .cx-drawer .cx-record-back{min-height:0;padding:0 var(--cx-size-4px) 0 0;color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));font-weight:600;}
11
11
  .cx-record-crumbs{display:flex;align-items:center;gap:var(--cx-size-4px);min-width:0;margin:0;padding:0;list-style:none;overflow:hidden;}
12
12
  .cx-record-crumbs li{display:flex;align-items:center;gap:var(--cx-size-4px);min-width:0;}
13
13
  .cx-record-crumbs li::before{content:"›";}
14
- .cx-drawer .cx-record-crumb{display:block;max-width:var(--cx-size-160px);min-height:0;padding:0 var(--cx-size-2px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--cx-muted);}
15
- .cx-record-summary{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-8px) var(--cx-size-20px);padding:var(--cx-size-10px) var(--cx-size-16px);border-bottom:var(--cx-size-1px) solid var(--cx-line);background:var(--cx-head-bg);}
14
+ .cx-drawer .cx-record-crumb{display:block;max-width:var(--cx-size-160px);min-height:0;padding:0 var(--cx-size-2px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
15
+ .cx-record-summary{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-8px) var(--cx-size-20px);padding:var(--cx-size-10px) var(--cx-size-16px);border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
16
16
  .cx-record-status{display:flex;align-items:center;gap:var(--cx-size-6px);}
17
17
  .cx-record-facts{display:flex;flex-wrap:wrap;gap:var(--cx-size-6px) var(--cx-size-20px);margin:0;}
18
18
  .cx-record-fact{min-width:0;}
19
- .cx-record-fact dt{font-size:var(--cx-size-11d5px);letter-spacing:var(--cx-size-d04em);text-transform:uppercase;color:var(--cx-muted);}
19
+ .cx-record-fact dt{font-size:var(--cx-size-11d5px);letter-spacing:var(--cx-size-d04em);text-transform:uppercase;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
20
20
  .cx-record-fact dd{margin:0;font-weight:600;overflow-wrap:anywhere;}
21
21
  .cx-drawer .cx-drawer-h > .cx-record-menu{position:relative;flex:none;}
22
- .cx-drawer .cx-record-menu-btn{justify-content:center;width:var(--cx-control-h);height:var(--cx-control-h);padding:0;}
23
- .cx-record-menu-list{position:absolute;right:0;top:calc(100% + var(--cx-size-4px));z-index:5;display:flex;flex-direction:column;min-width:var(--cx-size-180px);padding:var(--cx-size-4px);background:var(--cx-surface);border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);box-shadow:var(--cx-panel-shadow);}
22
+ .cx-drawer .cx-record-menu-btn{justify-content:center;width:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));height:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));padding:0;}
23
+ .cx-record-menu-list{position:absolute;right:0;top:calc(100% + var(--cx-size-4px));z-index:5;display:flex;flex-direction:column;min-width:var(--cx-size-180px);padding:var(--cx-size-4px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));}
24
24
  .cx-record-menu-item{justify-content:flex-start;min-height:var(--cx-size-32px);white-space:nowrap;}
25
- .cx-record-tools{position:sticky;top:0;z-index:3;background:var(--cx-surface);border-bottom:var(--cx-size-1px) solid var(--cx-line);}
25
+ .cx-record-tools{position:sticky;top:0;z-index:3;background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
26
26
  .cx-record-tabs{display:flex;gap:var(--cx-size-2px);padding:0 var(--cx-size-10px);overflow-x:auto;scrollbar-width:thin;}
27
- .cx-record-tab{flex:none;padding:var(--cx-size-10px) var(--cx-size-10px) var(--cx-size-8px);border:0;border-bottom:var(--cx-size-2px) solid transparent;background:transparent;color:var(--cx-muted);font:inherit;font-weight:600;white-space:nowrap;cursor:pointer;}
28
- .cx-record-tab:hover{color:var(--cx-text);}
29
- .cx-record-tab[aria-selected="true"]{color:var(--cx-text);border-bottom-color:var(--cx-accent);}
27
+ .cx-record-tab{flex:none;padding:var(--cx-size-10px) var(--cx-size-10px) var(--cx-size-8px);border:0;border-bottom:var(--cx-size-2px) solid transparent;background:transparent;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font:inherit;font-weight:600;white-space:nowrap;cursor:pointer;}
28
+ .cx-record-tab:hover{color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));}
29
+ .cx-record-tab[aria-selected="true"]{color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));border-bottom-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
30
30
  .cx-record-subtools{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-4px) var(--cx-size-12px);padding:var(--cx-size-6px) var(--cx-size-12px);}
31
- .cx-record-tabs + .cx-record-subtools{border-top:var(--cx-size-1px) solid var(--cx-line);}
31
+ .cx-record-tabs + .cx-record-subtools{border-top:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
32
32
  .cx-record-jump{display:flex;flex-wrap:wrap;gap:var(--cx-size-4px);flex:1;min-width:0;}
33
- .cx-drawer .cx-record-jump-link{min-height:var(--cx-size-24px);padding:0 var(--cx-size-10px);border-color:var(--cx-line);border-radius:var(--cx-size-999px);font-size:var(--cx-size-13px);color:var(--cx-accent-text);}
34
- .cx-drawer .cx-record-empty{margin-inline-start:auto;min-height:var(--cx-size-24px);font-size:var(--cx-size-13px);color:var(--cx-muted);}
35
- .cx-record-section{border-bottom:var(--cx-size-1px) solid var(--cx-line);}
33
+ .cx-drawer .cx-record-jump-link{min-height:var(--cx-size-24px);padding:0 var(--cx-size-10px);border-color:var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));font-size:var(--cx-size-13px);color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));}
34
+ .cx-drawer .cx-record-empty{margin-inline-start:auto;min-height:var(--cx-size-24px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
35
+ .cx-record-section{border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
36
36
  .cx-record-section:last-child{border-bottom:0;}
37
- .cx-record-section .cx-record-section{border-bottom:0;margin:0 var(--cx-size-16px) var(--cx-size-4px);border-inline-start:var(--cx-size-2px) solid var(--cx-line);}
37
+ .cx-record-section .cx-record-section{border-bottom:0;margin:0 var(--cx-size-16px) var(--cx-size-4px);border-inline-start:var(--cx-size-2px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
38
38
  .cx-record-section-h{margin:0;font:inherit;}
39
- .cx-drawer .cx-record-toggle{width:100%;padding:var(--cx-size-10px) var(--cx-size-16px) var(--cx-size-4px);border-radius:0;font-size:var(--cx-size-11d5px);font-weight:700;letter-spacing:var(--cx-size-d06em);text-transform:uppercase;color:var(--cx-muted);}
39
+ .cx-drawer .cx-record-toggle{width:100%;padding:var(--cx-size-10px) var(--cx-size-16px) var(--cx-size-4px);border-radius:var(--hfx-radius-none,0);font-size:var(--cx-size-11d5px);font-weight:700;letter-spacing:var(--cx-size-d06em);text-transform:uppercase;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
40
40
  .cx-record-toggle .cx-ico{width:var(--cx-size-14px);height:var(--cx-size-14px);transform:rotate(90deg);transition:transform .12s;}
41
41
  .cx-record-toggle[aria-expanded="false"] .cx-ico{transform:none;}
42
- .cx-drawer .cx-record-section .cx-record-section .cx-record-toggle{padding:var(--cx-size-6px) var(--cx-size-10px) var(--cx-size-2px);font-size:var(--cx-size-13px);letter-spacing:0;text-transform:none;color:var(--cx-text);}
42
+ .cx-drawer .cx-record-section .cx-record-section .cx-record-toggle{padding:var(--cx-size-6px) var(--cx-size-10px) var(--cx-size-2px);font-size:var(--cx-size-13px);letter-spacing:0;text-transform:none;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));}
43
43
  .cx-record-section .cx-record-section .cx-dl{padding:var(--cx-size-4px) var(--cx-size-10px) var(--cx-size-6px);}
44
44
  .cx-record-section-b{padding-bottom:var(--cx-size-6px);}
45
45
  .cx-record-section-b > .cx-dl{padding-top:var(--cx-size-6px);padding-bottom:var(--cx-size-6px);}
46
- .cx-record-object{grid-template-columns:minmax(var(--cx-size-92px),max-content) 1fr;gap:var(--cx-size-2px) var(--cx-size-12px);padding:var(--cx-size-2px) 0 var(--cx-size-2px) var(--cx-size-10px);border-inline-start:var(--cx-size-2px) solid var(--cx-line);}
46
+ .cx-record-object{grid-template-columns:minmax(var(--cx-size-92px),max-content) 1fr;gap:var(--cx-size-2px) var(--cx-size-12px);padding:var(--cx-size-2px) 0 var(--cx-size-2px) var(--cx-size-10px);border-inline-start:var(--cx-size-2px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
47
47
  .cx-drawer .cx-record-object dd{margin-bottom:0;}
48
48
  .cx-record-section-b,.cx-record-object-value{container-type:inline-size;min-width:0;}
49
49
  @container (max-width:400px){
50
50
  .cx-record-object,.cx-record-section-b > .cx-dl{grid-template-columns:minmax(0,1fr);gap:var(--cx-size-2px) 0;}
51
51
  }
52
52
  .cx-record-block{padding:var(--cx-size-6px) var(--cx-size-16px) var(--cx-size-10px);}
53
- .cx-record-block-h{margin-bottom:var(--cx-size-6px);font-size:var(--cx-size-13px);color:var(--cx-muted);}
53
+ .cx-record-block-h{margin-bottom:var(--cx-size-6px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
54
54
  .cx-record-custom{padding:var(--cx-size-6px) var(--cx-size-16px);}
55
55
  .cx-record-custom:empty{display:none;}
56
56
  .cx-record-chips{display:flex;flex-wrap:wrap;gap:var(--cx-size-4px);}
57
- .cx-drawer .cx-record-chip{display:inline-flex;align-items:center;max-width:100%;min-height:var(--cx-size-22px);padding:0 var(--cx-size-8px);border:var(--cx-size-1px) solid var(--cx-line-strong);border-radius:var(--cx-radius-sm);font-size:var(--cx-size-13px);overflow-wrap:anywhere;text-decoration:none;}
58
- .cx-drawer .cx-record-chip:is(.cx-tone-info,.cx-tone-success,.cx-tone-warning,.cx-tone-danger,.cx-toned){background:color-mix(in srgb,currentColor 9%,var(--cx-surface));border-color:color-mix(in srgb,currentColor 38%,var(--cx-surface));}
59
- .cx-drawer .cx-record-chip.cx-record-link{color:var(--cx-accent-text);}
60
- .cx-drawer .cx-diff-removed{text-decoration:line-through;color:var(--cx-muted);}
61
- .cx-drawer .cx-diff-added{font-weight:600;border-color:var(--cx-accent);}
62
- .cx-record-more-count{margin-inline-start:var(--cx-size-4px);color:var(--cx-muted);font-size:var(--cx-size-12d5px);}
63
- .cx-drawer :is(.cx-record-more,.cx-record-load-more,.cx-record-retry){margin-top:var(--cx-size-6px);border-color:var(--cx-line);color:var(--cx-accent-text);}
57
+ .cx-drawer .cx-record-chip{display:inline-flex;align-items:center;max-width:100%;min-height:var(--cx-size-22px);padding:0 var(--cx-size-8px);border:var(--cx-size-1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));border-radius:var(--hfx-radius-status,999px);font-size:var(--cx-size-13px);overflow-wrap:anywhere;text-decoration:none;}
58
+ .cx-drawer .cx-record-chip:is(.cx-tone-info,.cx-tone-success,.cx-tone-warning,.cx-tone-danger,.cx-toned){background:color-mix(in srgb,currentColor 9%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));border-color:color-mix(in srgb,currentColor 38%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));}
59
+ .cx-drawer .cx-record-chip.cx-record-link{color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));}
60
+ .cx-drawer .cx-diff-removed{text-decoration:line-through;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
61
+ .cx-drawer .cx-diff-added{font-weight:600;border-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
62
+ .cx-record-more-count{margin-inline-start:var(--cx-size-4px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--cx-size-12d5px);}
63
+ .cx-drawer :is(.cx-record-more,.cx-record-load-more,.cx-record-retry){margin-top:var(--cx-size-6px);border-color:var(--hfx-color-border,light-dark(#e2e4e7,#272a30));color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));}
64
64
  :is(.cx-record-diff,.cx-record-table){width:100%;border-collapse:collapse;font-size:var(--cx-size-13px);}
65
- :is(.cx-record-diff,.cx-record-table) :is(th,td){padding:var(--cx-size-4px) var(--cx-size-8px);border-bottom:var(--cx-size-1px) solid var(--cx-line);text-align:start;vertical-align:top;overflow-wrap:anywhere;}
66
- :is(.cx-record-diff,.cx-record-table) thead th{font-size:var(--cx-size-12px);font-weight:600;color:var(--cx-muted);}
65
+ :is(.cx-record-diff,.cx-record-table) :is(th,td){padding:var(--cx-size-4px) var(--cx-size-8px);border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));text-align:start;vertical-align:top;overflow-wrap:anywhere;}
66
+ :is(.cx-record-diff,.cx-record-table) thead th{font-size:var(--cx-size-12px);font-weight:600;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
67
67
  .cx-record-diff tbody th{width:30%;font-weight:600;}
68
- .cx-record-diff .cx-diff-before{color:var(--cx-muted);}
68
+ .cx-record-diff .cx-diff-before{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
69
69
  .cx-record-diff-compact{margin-top:var(--cx-size-6px);}
70
70
  .cx-record-diff-compact thead{display:none;}
71
- .cx-record-collection-h{display:flex;align-items:center;gap:var(--cx-size-8px);margin-bottom:var(--cx-size-6px);font-size:var(--cx-size-13px);color:var(--cx-muted);}
72
- .cx-drawer .cx-record-open-all{margin-inline-start:auto;color:var(--cx-accent-text);font-weight:600;}
73
- .cx-record-nested{height:var(--cx-size-360px);border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);background:var(--cx-surface);}
71
+ .cx-record-collection-h{display:flex;align-items:center;gap:var(--cx-size-8px);margin-bottom:var(--cx-size-6px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
72
+ .cx-drawer .cx-record-open-all{margin-inline-start:auto;color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));font-weight:600;}
73
+ .cx-record-nested{height:var(--cx-size-360px);border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));}
74
74
  .cx-record-nested.cx-host{padding:0;}
75
- .cx-record-card{margin-bottom:var(--cx-size-8px);padding:var(--cx-size-8px) var(--cx-size-12px);border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);}
75
+ .cx-record-card{margin-bottom:var(--cx-size-8px);padding:var(--cx-size-8px) var(--cx-size-12px);border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));}
76
76
  .cx-record-card-title{font-weight:600;}
77
77
  .cx-drawer .cx-record-card .cx-dl{grid-template-columns:1fr;gap:0;padding:var(--cx-size-4px) 0 0;}
78
- .cx-record-card dt{font-size:var(--cx-size-12px);color:var(--cx-muted);}
78
+ .cx-record-card dt{font-size:var(--cx-size-12px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
79
79
  .cx-drawer .cx-record-card dd{margin-bottom:var(--cx-size-4px);}
80
80
  .cx-timeline{position:relative;margin:0;padding:0;list-style:none;}
81
- .cx-timeline-day{padding:var(--cx-size-8px) 0 var(--cx-size-2px);font-size:var(--cx-size-11d5px);font-weight:700;letter-spacing:var(--cx-size-d04em);color:var(--cx-muted);}
81
+ .cx-timeline-day{padding:var(--cx-size-8px) 0 var(--cx-size-2px);font-size:var(--cx-size-11d5px);font-weight:700;letter-spacing:var(--cx-size-d04em);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
82
82
  .cx-timeline-item{position:relative;display:grid;grid-template-columns:var(--cx-size-16px) 1fr;gap:var(--cx-size-8px);padding:var(--cx-size-4px) 0 var(--cx-size-8px);}
83
- .cx-timeline-item::before{content:"";position:absolute;left:calc(var(--cx-size-8px) - var(--cx-size-1px));top:var(--cx-size-20px);bottom:0;width:var(--cx-size-2px);background:var(--cx-line);}
83
+ .cx-timeline-item::before{content:"";position:absolute;left:calc(var(--cx-size-8px) - var(--cx-size-1px));top:var(--cx-size-20px);bottom:0;width:var(--cx-size-2px);background:var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
84
84
  .cx-timeline-item:last-child::before{display:none;}
85
- .cx-timeline-dot{width:var(--cx-size-10px);height:var(--cx-size-10px);margin:var(--cx-size-5px) auto 0;border-radius:50%;color:var(--cx-muted);background:currentColor;}
85
+ .cx-timeline-dot{width:var(--cx-size-10px);height:var(--cx-size-10px);margin:var(--cx-size-5px) auto 0;border-radius:50%;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));background:currentColor;}
86
86
  .cx-timeline-dot:is(.cx-tone-info,.cx-tone-success,.cx-tone-warning,.cx-tone-danger,.cx-toned){color:var(--cx-t,inherit);}
87
- .cx-timeline-meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-6px);font-size:var(--cx-size-12d5px);color:var(--cx-muted);}
87
+ .cx-timeline-meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-6px);font-size:var(--cx-size-12d5px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
88
88
  .cx-timeline-summary{margin-top:var(--cx-size-2px);overflow-wrap:anywhere;}
89
- .cx-record-note{margin:var(--cx-size-8px) var(--cx-size-16px);color:var(--cx-muted);font-style:italic;}
90
- .cx-record-error{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-8px);color:var(--cx-tone-danger);font-style:normal;}
89
+ .cx-record-note{margin:var(--cx-size-8px) var(--cx-size-16px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-style:italic;}
90
+ .cx-record-error{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-8px);color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));font-style:normal;}
91
91
  .cx-drawer.cx-phone :is(.cx-record-btn,.cx-record-tab){min-height:var(--cx-size-44px);}
92
92
  .cx-drawer.cx-phone .cx-record-menu-btn{width:var(--cx-size-44px);height:var(--cx-size-44px);}
93
93
  .cx-drawer.cx-phone .cx-record-crumbs{display:none;}
@@ -97,15 +97,15 @@ body .cx-host.cx-drawer.cx-record-drawer{max-width:var(--cx-size-640px);}
97
97
  .cx-record-print{display:none;}
98
98
  @media print{
99
99
  html.cx-record-printing body > :not(.cx-record-print){display:none !important;}
100
- html.cx-record-printing .cx-record-print{display:block;padding:0;font:var(--cx-size-12px)/1.4 var(--cx-font);color:var(--cx-text);background:var(--cx-surface);}
100
+ html.cx-record-printing .cx-record-print{display:block;padding:0;font:var(--cx-size-12px)/1.4 var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));}
101
101
  .cx-record-print h1{margin:0 0 var(--cx-size-4px);font-size:var(--cx-size-20px);}
102
102
  .cx-record-print h2{margin:var(--cx-size-16px) 0 var(--cx-size-4px);font-size:var(--cx-size-16px);}
103
103
  .cx-record-print .cx-record-section{break-inside:avoid;border:0;}
104
- .cx-record-print .cx-record-section-h{margin:var(--cx-size-10px) 0 var(--cx-size-2px);font-size:var(--cx-size-11d5px);font-weight:700;text-transform:uppercase;color:var(--cx-muted);}
104
+ .cx-record-print .cx-record-section-h{margin:var(--cx-size-10px) 0 var(--cx-size-2px);font-size:var(--cx-size-11d5px);font-weight:700;text-transform:uppercase;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
105
105
  .cx-record-print .cx-dl{display:grid;grid-template-columns:var(--cx-size-180px) 1fr;gap:var(--cx-size-2px) var(--cx-size-12px);margin:0;padding:0;}
106
106
  .cx-record-print dd{margin:0;}
107
- .cx-record-print .p-sub{margin-inline-start:var(--cx-size-6px);color:var(--cx-muted);}
108
- .cx-record-print .cx-record-summary{border:var(--cx-size-1px) solid var(--cx-line);background:var(--cx-surface);}
107
+ .cx-record-print .p-sub{margin-inline-start:var(--cx-size-6px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
108
+ .cx-record-print .cx-record-summary{border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));}
109
109
  }
110
110
  @media (prefers-reduced-motion:reduce){.cx-record-toggle .cx-ico{transition:none;}}
111
111
  @media (forced-colors:active){.cx-record-tab[aria-selected="true"]{border-bottom-color:Highlight;}.cx-timeline-dot{forced-color-adjust:none;background:CanvasText;}}