@evotecit/canopyx 0.1.2 → 0.2.0

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 (85) hide show
  1. package/CanopyX.Html/Assets/canopyx-calendar-edit.js +113 -0
  2. package/CanopyX.Html/Assets/canopyx-calendar-ics.js +87 -0
  3. package/CanopyX.Html/Assets/canopyx-calendar-recurrence.js +36 -0
  4. package/CanopyX.Html/Assets/canopyx-calendar.css +279 -0
  5. package/CanopyX.Html/Assets/canopyx-calendar.js +307 -0
  6. package/CanopyX.Html/Assets/canopyx-cell-range.css +38 -0
  7. package/CanopyX.Html/Assets/canopyx-cell-range.js +141 -0
  8. package/CanopyX.Html/Assets/canopyx-column-groups.css +18 -0
  9. package/CanopyX.Html/Assets/canopyx-column-groups.js +51 -0
  10. package/CanopyX.Html/Assets/canopyx-data.js +14 -0
  11. package/CanopyX.Html/Assets/canopyx-detail-rows.css +18 -0
  12. package/CanopyX.Html/Assets/canopyx-detail-rows.js +51 -0
  13. package/CanopyX.Html/Assets/canopyx-editing.css +44 -0
  14. package/CanopyX.Html/Assets/canopyx-editing.js +134 -0
  15. package/CanopyX.Html/Assets/canopyx-enhance.js +126 -0
  16. package/CanopyX.Html/Assets/canopyx-export.js +18 -0
  17. package/CanopyX.Html/Assets/canopyx-facets.css +86 -0
  18. package/CanopyX.Html/Assets/canopyx-facets.js +65 -0
  19. package/CanopyX.Html/Assets/canopyx-filter-editor.css +15 -18
  20. package/CanopyX.Html/Assets/canopyx-filter-editor.js +23 -17
  21. package/CanopyX.Html/Assets/canopyx-format-editor.css +77 -0
  22. package/CanopyX.Html/Assets/canopyx-format-editor.js +30 -0
  23. package/CanopyX.Html/Assets/canopyx-formatting.css +40 -0
  24. package/CanopyX.Html/Assets/canopyx-formatting.js +101 -0
  25. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +352 -246
  26. package/CanopyX.Html/Assets/canopyx-grid.css +139 -117
  27. package/CanopyX.Html/Assets/canopyx-grid.js +352 -246
  28. package/CanopyX.Html/Assets/canopyx-grouping.css +39 -0
  29. package/CanopyX.Html/Assets/canopyx-grouping.js +85 -0
  30. package/CanopyX.Html/Assets/canopyx-highlight.css +34 -0
  31. package/CanopyX.Html/Assets/canopyx-highlight.js +80 -0
  32. package/CanopyX.Html/Assets/canopyx-history.js +13 -0
  33. package/CanopyX.Html/Assets/canopyx-interactive.css +18 -6
  34. package/CanopyX.Html/Assets/canopyx-interactive.js +179 -100
  35. package/CanopyX.Html/Assets/canopyx-labels-de.js +304 -0
  36. package/CanopyX.Html/Assets/canopyx-labels-es.js +304 -0
  37. package/CanopyX.Html/Assets/canopyx-labels-fr.js +529 -0
  38. package/CanopyX.Html/Assets/canopyx-labels-it.js +529 -0
  39. package/CanopyX.Html/Assets/canopyx-labels-pl.js +304 -0
  40. package/CanopyX.Html/Assets/canopyx-layouts.css +48 -0
  41. package/CanopyX.Html/Assets/canopyx-layouts.js +39 -0
  42. package/CanopyX.Html/Assets/canopyx-link.css +19 -0
  43. package/CanopyX.Html/Assets/canopyx-link.js +38 -0
  44. package/CanopyX.Html/Assets/canopyx-links.js +14 -0
  45. package/CanopyX.Html/Assets/canopyx-live.css +24 -0
  46. package/CanopyX.Html/Assets/canopyx-live.js +88 -0
  47. package/CanopyX.Html/Assets/canopyx-module.mjs +180 -100
  48. package/CanopyX.Html/Assets/canopyx-pager.css +10 -0
  49. package/CanopyX.Html/Assets/canopyx-pager.js +14 -0
  50. package/CanopyX.Html/Assets/canopyx-record-panel.css +111 -0
  51. package/CanopyX.Html/Assets/canopyx-record-panel.js +178 -0
  52. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +406 -342
  53. package/CanopyX.Html/Assets/canopyx-reporting.css +140 -135
  54. package/CanopyX.Html/Assets/canopyx-reporting.js +406 -342
  55. package/CanopyX.Html/Assets/canopyx-search.js +32 -0
  56. package/CanopyX.Html/Assets/canopyx-timeline.css +80 -0
  57. package/CanopyX.Html/Assets/canopyx-timeline.js +88 -0
  58. package/CanopyX.Html/Assets/canopyx-tree-tools.css +103 -0
  59. package/CanopyX.Html/Assets/canopyx-tree-tools.js +92 -0
  60. package/CanopyX.Html/Assets/canopyx.css +17 -5
  61. package/CanopyX.Html/Assets/canopyx.js +175 -96
  62. package/JavaScript/calendar.d.ts +362 -0
  63. package/JavaScript/cell-ranges.d.ts +76 -0
  64. package/JavaScript/column-groups.d.ts +32 -0
  65. package/JavaScript/editing.d.ts +257 -0
  66. package/JavaScript/enhance.d.ts +202 -0
  67. package/JavaScript/facets.d.ts +58 -0
  68. package/JavaScript/formatting.d.ts +88 -0
  69. package/JavaScript/grid.d.ts +409 -56
  70. package/JavaScript/hosts.d.ts +177 -2
  71. package/JavaScript/index.d.ts +53 -4
  72. package/JavaScript/live.d.ts +115 -0
  73. package/JavaScript/locales/de.mjs +304 -0
  74. package/JavaScript/locales/es.mjs +304 -0
  75. package/JavaScript/locales/fr.d.ts +6 -0
  76. package/JavaScript/locales/fr.mjs +527 -0
  77. package/JavaScript/locales/it.d.ts +6 -0
  78. package/JavaScript/locales/it.mjs +527 -0
  79. package/JavaScript/locales/pl.mjs +304 -0
  80. package/JavaScript/plugins.d.ts +113 -0
  81. package/JavaScript/protocol.d.ts +139 -6
  82. package/JavaScript/records.d.ts +136 -0
  83. package/README.md +61 -9
  84. package/README.nuget.md +1 -1
  85. package/package.json +99 -3
@@ -0,0 +1,10 @@
1
+ /* Pager controls part: numbered page buttons and switched-off pager controls (docs/paging.md). */
2
+ .cx-data-grid .cx-grid-pager [hidden]{display:none !important;}
3
+ .cx-data-grid .cx-grid-pager .cx-pages{display:inline-flex;align-items:center;gap:var(--cx-size-4px);}
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);}
7
+ .cx-phone .cx-grid-pager .cx-pages .cx-button{min-width:var(--cx-size-44px);}
8
+ @media (forced-colors:active){
9
+ .cx-data-grid .cx-grid-pager .cx-pages .cx-button[aria-current="page"]{border-color:Highlight;outline:var(--cx-size-2px) solid Highlight;}
10
+ }
@@ -0,0 +1,14 @@
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)||
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
+ return{lengths,numbers,info:pager.info||"range",lengthMenu:flag("lengthMenu",true),pageInput:flag("pageInput",!numbers),firstLast:flag("firstLast",true)}}
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);
5
+ return[0,null,...range(start,start+inner),null,count-1]}
6
+ function pagerPages(current,count,max){return pagerWindow(current,count,max).map((page,index,pages)=>page===null&&pages[index+1]- pages[index-1]===2?pages[index-1]+ 1:page)}
7
+ Object.assign(DataGrid.prototype,{buildPager(){if(!this.paged||!this.view.pager)return BUILD_PAGER.call(this);const settings=pagerSettings(this.view),previous=this.pager;this.pagerSettings=settings;BUILD_PAGER.call(this);if(previous&&previous!==this.pager)previous.replaceWith(this.pager);this.pager.hidden=this.opts.toolbar===false;this.pager.classList.add("cx-pager-custom");this.pageLengthChoice.closest(".cx-rpp").hidden=!settings.lengthMenu;if(this.pageNumber)this.pageNumber.closest(".pg").hidden=!settings.pageInput;if(!settings.firstLast)[this.pageButtons[0],this.pageButtons[3]].forEach(button=>{if(button)button.hidden=true});this.pageRange.hidden=settings.info==="none";if(settings.numbers&&!this.cursor){this.pageList=h("span","cx-pages");this.pageButtons[1].after(this.pageList)}
8
+ this.syncPager()},syncPager(){const before=document.activeElement;SYNC_PAGER.call(this);const settings=this.pagerSettings;if(!this.pager||!settings)return;const paging=this.getPaging(),busy=!this.acceptedQuery||!!this.pendingQuery,numbers=numberFormat(this.lang);if(!busy&&this.pager.contains(before)&&before.disabled&&(document.activeElement===before||!this.pager.contains(document.activeElement))){if(this.pageList)this.pageListFocus=true;else[...this.pager.querySelectorAll("button,select,input")].find(control=>!control.disabled&&!control.closest("[hidden]"))?.focus({preventScroll:true})}
9
+ if(settings.lengths){const choice=this.pageLengthChoice,current=this.pageAll?"all":this.pageLength,items=settings.lengths.slice();if(!items.some(item=>item.value===current)){const at=items.findIndex(item=>item.value==="all"||item.value>current);items.splice(at<0?items.length:at,0,{value:current})}
10
+ choice.replaceChildren(...items.map(item=>gridOption(item.value,item.label||(item.value==="all"?this.labels.gridAll:numbers.format(item.value)))));choice.value=String(current)}
11
+ if(settings.info==="sentence"&&paging.matched!==null){gridCountLabel(this.pageRange,paging.matched<paging.total?this.labels.gridPageInfoFiltered:this.labels.gridPageInfo,{first:numbers.format(paging.first),last:numbers.format(paging.last),count:numbers.format(paging.matched),total:numbers.format(paging.total)},/(\{first\}.*?\{last\})/);
12
+ }
13
+ if(this.pageList)this.syncPageList(paging,busy,numbers)},syncPageList(paging,busy,numbers){const list=this.pageList,active=document.activeElement;const refocus=list.contains(active)||this.pageListFocus&&(!active||active===document.body||this.pager.contains(active));const width=this.host.clientWidth,max=width&&width<=640?Math.min(5,this.pagerSettings.numbers):this.pagerSettings.numbers;list.replaceChildren(...pagerPages(paging.pageIndex,paging.pageCount,max).map(index=>{if(index===null){const gap=h("span","cx-gap");gap.setAttribute("aria-hidden","true");setText(gap,"…");return gap}
14
+ const page=numbers.format(index+1),button=gridButton(page,()=>{this.pageListFocus=true;try{this.goToPage(index).catch(()=>{})}catch(error){this.emit("error",{error})}});button.classList.add("cx-page");button.setAttribute("aria-label",fill(this.labels.gridPageButton,{page}));if(index===paging.pageIndex)button.setAttribute("aria-current","page");button.disabled=busy;return button}));if(refocus&&!busy)list.querySelector("[aria-current]")?.focus({preventScroll:true});this.pageListFocus=refocus&&busy}});GRID_PAGER_IMPL.installed=true;installed.add(context.GRID_PAGER_IMPL)}};(global.CanopyXParts||=[]).push(["pager",part])})(typeof window!=="undefined"?window:globalThis);
@@ -0,0 +1,111 @@
1
+ /* ---------- record panel: the rich record drawer of flat grids and trees ---------- */
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);}
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;}
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;}
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
+ .cx-record-crumbs li{display:flex;align-items:center;gap:var(--cx-size-4px);min-width:0;}
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);}
16
+ .cx-record-status{display:flex;align-items:center;gap:var(--cx-size-6px);}
17
+ .cx-record-facts{display:flex;flex-wrap:wrap;gap:var(--cx-size-6px) var(--cx-size-20px);margin:0;}
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);}
20
+ .cx-record-fact dd{margin:0;font-weight:600;overflow-wrap:anywhere;}
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);}
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);}
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);}
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);}
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);}
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);}
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);}
40
+ .cx-record-toggle .cx-ico{width:var(--cx-size-14px);height:var(--cx-size-14px);transform:rotate(90deg);transition:transform .12s;}
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);}
43
+ .cx-record-section .cx-record-section .cx-dl{padding:var(--cx-size-4px) var(--cx-size-10px) var(--cx-size-6px);}
44
+ .cx-record-section-b{padding-bottom:var(--cx-size-6px);}
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);}
47
+ .cx-drawer .cx-record-object dd{margin-bottom:0;}
48
+ .cx-record-section-b,.cx-record-object-value{container-type:inline-size;min-width:0;}
49
+ @container (max-width:400px){
50
+ .cx-record-object,.cx-record-section-b > .cx-dl{grid-template-columns:minmax(0,1fr);gap:var(--cx-size-2px) 0;}
51
+ }
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);}
54
+ .cx-record-custom{padding:var(--cx-size-6px) var(--cx-size-16px);}
55
+ .cx-record-custom:empty{display:none;}
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);}
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);}
67
+ .cx-record-diff tbody th{width:30%;font-weight:600;}
68
+ .cx-record-diff .cx-diff-before{color:var(--cx-muted);}
69
+ .cx-record-diff-compact{margin-top:var(--cx-size-6px);}
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);}
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);}
76
+ .cx-record-card-title{font-weight:600;}
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);}
79
+ .cx-drawer .cx-record-card dd{margin-bottom:var(--cx-size-4px);}
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);}
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);}
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;}
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);}
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;}
91
+ .cx-drawer.cx-phone :is(.cx-record-btn,.cx-record-tab){min-height:var(--cx-size-44px);}
92
+ .cx-drawer.cx-phone .cx-record-menu-btn{width:var(--cx-size-44px);height:var(--cx-size-44px);}
93
+ .cx-drawer.cx-phone .cx-record-crumbs{display:none;}
94
+ .cx-drawer.cx-phone :is(.cx-record-link,.cx-record-crumb){min-height:var(--cx-size-24px);}
95
+ .cx-drawer.cx-phone .cx-record-nested{height:var(--cx-size-280px);}
96
+ .cx-drawer.cx-phone .cx-record-section .cx-record-section{margin-inline:var(--cx-size-10px);}
97
+ .cx-record-print{display:none;}
98
+ @media print{
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);}
101
+ .cx-record-print h1{margin:0 0 var(--cx-size-4px);font-size:var(--cx-size-20px);}
102
+ .cx-record-print h2{margin:var(--cx-size-16px) 0 var(--cx-size-4px);font-size:var(--cx-size-16px);}
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);}
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
+ .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);}
109
+ }
110
+ @media (prefers-reduced-motion:reduce){.cx-record-toggle .cx-ico{transition:none;}}
111
+ @media (forced-colors:active){.cx-record-tab[aria-selected="true"]{border-bottom-color:Highlight;}.cx-timeline-dot{forced-color-adjust:none;background:CanvasText;}}
@@ -0,0 +1,178 @@
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"bcc06276c7933af6",install(context){if(installed.has(context.RECORD_IMPL))return;const{RECORD_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,validateGridRows,badgeElement,loadSidecar,requireIdentifier,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField}=context;const RECORD_KINDS=["items","fields","records","events","changes"],RECORD_LINK_KEY=/^[A-Za-z][\w.-]{0,31}$/, RECORD_MAX_STRUCTURE_DEPTH = 8;
2
+ const recordKind=cell=>{const kinds=isCellObject(cell)&&!Array.isArray(cell)?RECORD_KINDS.filter(name=>cell[name]!==undefined):[];if(kinds.length>1)recordFail("a cell carries at most one structured value.");return kinds[0]||null};const recordFail=message=>{throw new Error("CanopyX: "+message)};const recordText=(value,max=256)=>typeof value==="string"&&!!value.trim()&&value.length<=max;const recordGridHelpers=()=>RECORD_IMPL.grid||{};function recordCheckValue(cell,depth=0){if(cell==null)return;if(depth>RECORD_MAX_STRUCTURE_DEPTH)recordFail("structured values nest at most "+RECORD_MAX_STRUCTURE_DEPTH+" levels.");const kind=recordKind(cell);if(kind==="items")for(const item of cell.items||[])recordCheckValue(item,depth+1);if(kind==="fields")for(const field of cell.fields||[])recordCheckValue(field.value,depth+1);if(kind==="changes")for(const change of cell.changes||[]){recordCheckValue(change.before,depth+1);recordCheckValue(change.after,depth+1)}
3
+ if(kind==="events")for(const event of cell.events||[])for(const change of event.changes||[]){recordCheckValue(change.before,depth+1);recordCheckValue(change.after,depth+1)}
4
+ if(kind==="records")recordCheckRows(cell.records.rows||cell.records.roots,depth+1)}
5
+ function recordCheckRows(rows,depth){const pending=[...rows||[]],seen=new Set();while(pending.length){const row=pending.pop();if(!row||seen.has(row))continue;seen.add(row);for(const cells of[row.cells,row.fields])if(cells)Object.values(cells).forEach(cell=>recordCheckValue(cell,depth));const detail=row.detail;if(detail){if(depth>RECORD_MAX_STRUCTURE_DEPTH)recordFail("structured values nest at most "+RECORD_MAX_STRUCTURE_DEPTH+" levels.");if(detail.type==="properties")for(const item of detail.items||[])recordCheckValue(item.value,depth);if(detail.type==="table")for(const cells of detail.rows||[])for(const cell of cells)recordCheckValue(cell,depth);if(detail.type==="grid"||detail.type==="tree")recordCheckRows(detail.rows||detail.roots,depth+1)}
6
+ for(const child of row.children||[])pending.push(child)}}
7
+ function recordSpec(view){if(view._recordSpec)return view._recordSpec;const spec=view.view.record||{},columns=new Set(view.columns.map(column=>column.id)),fields=new Set(),sections=new Set();if(typeof spec!=="object"||Array.isArray(spec))recordFail("a record panel is an object.");for(const field of spec.fields||[]){requireIdentifier(field?.id,"record field ID");if(field.id==="__proto__")recordFail("a record field cannot be named __proto__.");if(columns.has(field.id)||fields.has(field.id)||!recordText(field.title)||field.kind!==undefined&&!["text","number","datetime"].includes(field.kind)||
8
+ field.section!==undefined&&!recordText(field.section))recordFail("record field "+field.id+" needs a unique id, a title and a text, number or datetime kind.");if(field.presenter!==undefined&&recordGridHelpers().validatePresenter)recordGridHelpers().validatePresenter(field.presenter,{kind:"text",...field},view.columns);fields.add(field.id)}
9
+ const known=id=>columns.has(id)||fields.has(id),top=new Set();const walk=(list,depth)=>{if(!Array.isArray(list)||depth>2)recordFail("record sections are an array, nested at most three levels.");for(const section of list){requireIdentifier(section?.id,"record section ID");if(sections.has(section.id)||!recordText(section.label)||section.fields!==undefined&&(!Array.isArray(section.fields)||!section.fields.every(known))||
10
+ section.renderer!==undefined&&!/^[a-z][a-z0-9-]{0,31}$/.test(section.renderer) || section.collapsed !== undefined && typeof section.collapsed !== "boolean")
11
+ recordFail("record section "+section.id+" needs a unique id, a label and declared fields.");sections.add(section.id);if(!depth)top.add(section.id);walk(section.sections||[],depth+1)}};walk(spec.sections||[],0);const tabs=new Set();for(const tab of spec.tabs||[]){requireIdentifier(tab?.id,"record tab ID");if(tabs.has(tab.id)||!recordText(tab.label)||!Array.isArray(tab.sections)||!tab.sections.every(id=>top.has(id)))recordFail("record tab "+tab.id+" needs a unique id, a label and declared top-level sections.");tabs.add(tab.id)}
12
+ const header=spec.header,link=spec.deepLink,source=spec.source;if(header!==undefined&&(!header||header.facts!==undefined&&(!Array.isArray(header.facts)||header.facts.length>6||!header.facts.every(known))||
13
+ header.status!==undefined&&!known(header.status)))recordFail("a record header names up to six declared facts and a declared status.");if(link!==undefined&&link!==true&&(!link||typeof link!=="object"||link.key!==undefined&&!RECORD_LINK_KEY.test(link.key)))recordFail("a record deep link is true or { key }.");if(source!==undefined&&(!source||!["inline","host","sidecar"].includes(source.kind)||source.kind==="sidecar"&&
14
+ (typeof source.base!=="string"||!Number.isInteger(source.shards)||source.shards<1||source.shards>65536)))recordFail("a record source is inline, host, or a sidecar with a base and 1 to 65,536 shards.");if(source?.kind==="sidecar"&&(!source.base||/[?#]/.test(source.base)))
15
+ recordFail("a record sidecar base must be a non-empty folder path without a query or fragment.");for(const name of["hideEmpty","jumpList"])if(spec[name]!==undefined&&typeof spec[name]!=="boolean")recordFail("record "+name+" is a boolean.");if(spec.actions!==undefined&&(!spec.actions||Object.entries(spec.actions).some(([name,value])=>!["copy","print","export","link"].includes(name)||typeof value!=="boolean")))
16
+ recordFail("record actions switch copy, print, export and link on or off.");return view._recordSpec=spec}
17
+ const recordPrimary=view=>view.kind==="tree"?view.columns[0]:view.visibleColumns()[0];function recordFields(view){const spec=recordSpec(view),primary=recordPrimary(view),fields=[];view.columns.forEach((column,index)=>{if(column.drawer===false||view.kind==="tree"&&!index)return;fields.push({id:column.id,title:column.title,kind:column.kind,presenter:column.presenter,wrap:column.wrap,section:column.section,column,primary:column===primary})});for(const field of spec.fields||[])fields.push({...field,kind:field.kind||"text",column:null,primary:false});return fields}
18
+ function recordCell(view,record,payload,field){const own=(values,id)=>values&&Object.hasOwn(values,id)?values[id]:undefined;if(!field.column)return own(payload?.fields,field.id)!==undefined?own(payload.fields,field.id):own(record.fields,field.id);if(own(payload?.cells,field.id)!==undefined)return own(payload.cells,field.id);return view.kind==="tree"?view.cellOf(record,field.column,view.columns.indexOf(field.column)):own(record.cells,field.id)}
19
+ function recordEmpty(cell,field,fmt){const kind=recordKind(cell);if(kind==="records")return!cell.records.rows?.length&&!cell.records.roots?.length;if(kind)return!Array.isArray(cell[kind])||!cell[kind].length;if(isCellObject(cell)&&(cell.series?.length||cell.badges?.length))return false;return cellText(cell,field,fmt)===""}
20
+ function recordLayout(view,fields){const spec=recordSpec(view),byId=new Map(fields.map(field=>[field.id,field])),placed=new Set(),labels=view.labels;const section=(item,depth)=>({id:item.id,label:item.label,depth,collapsed:!!item.collapsed,renderer:item.renderer||null,fields:(item.fields||[]).map(id=>byId.get(id)).filter(field=>field&&!placed.has(field.id)&&placed.add(field.id)),sections:(item.sections||[]).map(child=>section(child,depth+1))});const sections=(spec.sections||[]).map(item=>section(item,0)),header=new Set([...(spec.header?.facts||[]),spec.header?.status].filter(Boolean));const rest=fields.filter(field=>!placed.has(field.id)&&!(field.primary&&view.view.record)&&!header.has(field.id));if(!spec.sections){const named=new Map();for(const field of rest){const name=field.section||labels.gridDetailsSection;if(!named.has(name))named.set(name,{id:"s"+named.size,label:name,depth:0,fields:[],sections:[]});named.get(name).fields.push(field)}
21
+ sections.push(...named.values())}else if(rest.length)sections.push({id:"other",label:labels.recordOtherFields,depth:0,fields:rest,sections:[]});const known=new Map(sections.map(item=>[item.id,item]));const tabs=(spec.tabs||[]).map(tab=>({id:tab.id,label:tab.label,sections:tab.sections.map(id=>known.get(id)).filter(Boolean)}));if(tabs.length){const used=new Set(tabs.flatMap(tab=>tab.sections));tabs[tabs.length-1].sections.push(...sections.filter(item=>!used.has(item)))}
22
+ return{tabs:tabs.length?tabs:[{id:"all",label:"",sections}],header:spec.header||null,byId,hideEmpty:!!view.view.record&&spec.hideEmpty!==false,jump:spec.jumpList}}
23
+ const RECORD_PACKS=new Map();function recordShard(id,shards){let hash=2166136261;for(let i=0;i<id.length;i++)hash=Math.imul(hash^id.charCodeAt(i),16777619);return(hash>>>0)%shards}
24
+ function recordLoader(view){const source=recordSpec(view).source;if(typeof view.opts.loadRecord==="function")return view.opts.loadRecord;if(view.kind==="grid"&&typeof view.source?.record==="function")return(request,options)=>view.source.record(request,options);return source?.kind==="sidecar"?"sidecar":null}
25
+ function recordRevision(view){if(view.kind==="grid"){if(!view.opts.source&&view.view.source.kind==="inline")return null;return view.snapshot?.revision??null}
26
+ return view.datasetRevision??null}
27
+ const recordCacheKey=(view,id,revision=recordRevision(view))=>JSON.stringify([revision,id]);const recordEntry=(view,id)=>view._recordPayloads?.get(recordCacheKey(view,id));RECORD_IMPL.invalidate=(view,id)=>{view._recordPayloads?.delete(recordCacheKey(view,id))};function recordPayload(view,id,doc,revision){if(doc==null)return null;if(typeof doc!=="object"||Array.isArray(doc)||doc.protocol!==undefined&&doc.protocol!==PROTOCOL||doc.type!==undefined&&doc.type!=="gridRecord"||
28
+ doc.view!==undefined&&doc.view!==view.view.id||doc.id!==undefined&&doc.id!==id||
29
+ revision!=null&&doc.revision!==undefined&&doc.revision!==revision)recordFail("a record source answers with the gridRecord of the requested record and revision.");for(const name of["cells","fields"])if(doc[name]!==undefined&&(!doc[name]||typeof doc[name]!=="object"||Array.isArray(doc[name])||Object.hasOwn(doc[name],"__proto__")))
30
+ recordFail("record "+name+" are an object of ids.");if(doc.row!==undefined&&(!doc.row||doc.row.id!==id||!doc.row.cells||typeof doc.row.cells!=="object"))recordFail("a record's row is the requested record.");for(const cells of[doc.cells,doc.fields])if(cells)Object.values(cells).forEach(cell=>recordCheckValue(cell));if(doc.row){if(view.kind==="grid")validateGridRows([doc.row],view.columns);recordCheckRows([doc.row],0)}
31
+ return JSON.parse(JSON.stringify({cells:doc.cells||null,fields:doc.fields||null,row:doc.row||null}))}
32
+ function recordFetch(view,id,extra,signal){const loader=recordLoader(view),spec=recordSpec(view).source,revision=recordRevision(view);if(!loader)return Promise.resolve(null);if(loader==="sidecar"){const shard=recordShard(id,spec.shards),key=JSON.stringify([view.view.id,spec.base,shard]);let pack=RECORD_PACKS.get(key);if(!pack){pack=loadSidecar(spec.base,view.view.id,"r"+shard).then(doc=>{if(!doc||doc.protocol!==PROTOCOL||doc.type!=="gridRecordPack"||doc.view!==view.view.id||!Array.isArray(doc.records)||doc.records.some(item=>!item||typeof item.id!=="string"))
33
+ recordFail("record pack r"+shard+" is not a gridRecordPack of this view.");return new Map(doc.records.map(item=>[item.id,item]))});RECORD_PACKS.set(key,pack);if(RECORD_PACKS.size>16)RECORD_PACKS.delete(RECORD_PACKS.keys().next().value)}
34
+ return pack.then(records=>recordPayload(view,id,records.get(id)||null,revision)).catch(error=>{if(error.name!=="AbortError"&&RECORD_PACKS.get(key)===pack)RECORD_PACKS.delete(key);throw error})}
35
+ const request={protocol:PROTOCOL,type:"gridRecordQuery",view:view.view.id,id,...(revision!=null?{revision}:{}),...extra};const run=signal=>Promise.resolve(loader(request,{signal}));return(view.runGridHook?view.runGridHook(run,signal||view.dataLifetime?.signal):run(signal||view.lifetime.signal)).then(doc=>recordPayload(view,id,doc,revision))}
36
+ function recordEnsure(view,id){const cache=view._recordPayloads||=new Map(),key=recordCacheKey(view,id);let entry=cache.get(key);if(entry)return entry;if(!recordLoader(view))return null;entry={state:"loading"};cache.set(key,entry);if(cache.size>64)cache.delete(cache.keys().next().value);entry.promise=recordFetch(view,id,{}).then(payload=>{entry.state="ready";entry.payload=payload;return payload},error=>{entry.state="error";entry.error=error;if(error.name!=="AbortError")view.emit("error",{error});throw error});entry.promise.catch(()=>{});return entry}
37
+ const RECORD_ICONS={back:'<path d="m14 7-5 5 5 5"/>',print:'<path d="M7 9V4h10v5M7 17H5v-6h14v6h-2M8 14h8v6H8z"/>',link:'<path d="M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1"/>',more:'<circle cx="5" cy="12" r="1.2"/><circle cx="12" cy="12" r="1.2"/><circle cx="19" cy="12" r="1.2"/>',open:'<path d="M14 5h5v5M19 5l-8 8M17 14v5H5V7h5"/>',chevron:'<path d="m9 6 6 6-6 6"/>'};function recordIcon(name){return svgIcon(RECORD_ICONS[name])}
38
+ function recordButton(text,run,className,icon){const button=h("button","cx-record-btn" +(className?" "+className:""));button.type="button";if(icon)button.appendChild(recordIcon(icon));if(text)button.appendChild(document.createTextNode(text));button.addEventListener("click",event=>{event.stopPropagation();run(event)});return button}
39
+ const recordCount=(ctx,count)=>formatValue(count,"number",ctx.fmt);const recordRefValid=ref=>!!ref&&typeof ref==="object"&&typeof ref.id==="string"&&!!ref.id&&(ref.view===undefined||typeof ref.view==="string"&&!!ref.view);function recordPlain(ctx,field,cell,element){const text=cellText(cell,field,ctx.fmt),object=isCellObject(cell),span=h("span");applyTone(span,"cx-drawer-text" +(text?"":" p-missing"),toneOf(object?cell.tone:null));setText(span,text||"—");if(object&&cell.title)span.title=cell.title;element.appendChild(span);if(object)for(const badge of cell.badges||[])element.appendChild(badgeElement(badge))}
40
+ function recordLink(ctx,cell,field,element,className){const text=cellText(cell,field,ctx.fmt)||cell.ref.id;if(ctx.print||!recordRefValid(cell.ref)){recordPlain(ctx,field,cell,element);return null}
41
+ const link=recordButton(text,()=>ctx.navigate(cell.ref,link),"cx-record-link" +(className?" "+className:""));applyTone(link,link.className,toneOf(cell.tone||null));link.setAttribute("data-cx-origin",field.id+":"+ctx.origins++);if(cell.title)link.title=cell.title;element.appendChild(link);return link}
42
+ function recordScalar(ctx,field,cell,element){const view=ctx.view,grid=recordGridHelpers();if(isCellObject(cell)&&cell.ref){recordLink(ctx,cell,field,element);return}
43
+ if(field.column&&view.paintDrawerValue){if(view.kind==="tree")view.paintDrawerValue(field.column,ctx.node,element,view.columns.indexOf(field.column),ctx);else view.paintDrawerValue(field.column,ctx.row,element,{signal:ctx.signal,width:ctx.width});return}
44
+ if(field.presenter&&grid.gridCellRenderer&&view.kind==="grid"){grid.gridCellRenderer(view,{...field,renderWidth:ctx.width},field.presenter)(ctx.row,element);return}
45
+ recordPlain(ctx,field,cell,element)}
46
+ function recordChip(ctx,field,item){const object=isCellObject(item),text=cellText(item,field,ctx.fmt);if(object&&item.ref&&recordRefValid(item.ref)&&!ctx.print){const holder=h("span");return recordLink(ctx,item,field,holder,"cx-record-chip")}
47
+ const chip=h("span");applyTone(chip,"cx-record-chip",toneOf(object?item.tone:null));setText(chip,text||"—");if(object&&item.title)chip.title=item.title;return chip}
48
+ function recordItems(ctx,field,items,element){const list=h("span","cx-record-chips"),limit=ctx.print?items.length:24;for(const item of items.slice(0,limit))list.appendChild(recordChip(ctx,field,item));if(items.length>limit){const more=recordButton(fill(ctx.labels.recordShowAll,{count:recordCount(ctx,items.length)}),()=>{more.remove();for(const item of items.slice(limit))list.appendChild(recordChip(ctx,field,item));list.querySelector(".cx-record-chip:nth-child(" +(limit+1)+ ")")?.focus?.()},"cx-record-more");list.appendChild(more)}
49
+ element.appendChild(list)}
50
+ function recordObject(ctx,field,entries,element,depth){element.classList.add("cx-record-object-value");const list=h("dl","cx-dl cx-record-object");for(const entry of entries){if(!entry||!recordText(entry.name,4096))recordFail("an object field has a name and a value.");const term=h("dt"),value=h("dd");setText(term,entry.name);recordValue(ctx,{id:field.id,title:entry.name,kind:entry.kind||"text",nested:true},entry.value,value,depth+1);list.append(term,value)}
51
+ element.appendChild(list)}
52
+ function recordValue(ctx,field,cell,element,depth=0){const kind=recordKind(cell);try{if(kind&&!Array.isArray(cell[kind])&&kind!=="records")recordFail("a structured "+kind+" value is an array.");if(depth>RECORD_MAX_STRUCTURE_DEPTH)recordFail("structured values nest at most "+RECORD_MAX_STRUCTURE_DEPTH+" levels.");else if(kind==="items")recordItems(ctx,field,cell.items,element);else if(kind==="fields")recordObject(ctx,field,cell.fields,element,depth);else if(kind==="records")recordCollection(ctx,field,cell.records,element);else if(kind==="events")recordTimeline(ctx,field,cell.events,element);else if(kind==="changes")recordChanges(ctx,field,cell.changes,element);else if(depth)isCellObject(cell)&&cell.ref?recordLink(ctx,cell,field,element):recordPlain(ctx,field,cell,element);else recordScalar(ctx,field,cell,element)}catch(error){element.replaceChildren();recordPlain(ctx,field,isCellObject(cell)?cell.text??null:cell,element);ctx.view.emit("error",{error})}
53
+ return kind==="records"||kind==="events"||kind==="changes"}
54
+ const recordRowTitle=(list,row,fmt)=>row&&(list.columns?.[0]&&cellText(row.cells?.[list.columns[0].id],list.columns[0],fmt)||row.label||row.id)||"";RECORD_IMPL.summary=(grid,column,options,row,element,text)=>{const cell=row.cells[column.id],kind=recordKind(cell),labels=grid.labels,fmt=grid.fmt;const add=(value,className)=>{const item=h("span",className||"cx-presenter-text");setText(item,value);element.appendChild(item);return item};const list=kind==="records"?cell.records?.rows||cell.records?.roots||[]:kind?cell[kind]:null;if(!kind||!Array.isArray(list)){add(text||"—",text?"":"p-missing");return}
55
+ const count=kind==="records"&&Number.isInteger(cell.records.total)?cell.records.total:list.length;if(!count){add(text||"—",text?"":"p-missing");return}
56
+ if(typeof cell.text==="string"&&!options.display){add(cell.text);return}
57
+ const display=options.display||(kind==="items"?"chips":kind==="fields"?"first":"count");const more=rest=>{if(rest>0)add(fill(labels.recordMore,{count:formatValue(rest,"number",fmt)}),"cx-record-more-count")};if(display==="count"){add(fill(options.countText||labels.recordItems,{count:formatValue(count,"number",fmt)}));return}
58
+ if(display==="chips"&&kind==="items"){const limit=options.limit||3,box=h("span","cx-tag-list");element.classList.add("cx-list-cell");for(const item of list.slice(0,limit)){const tag=h("span");applyTone(tag,"p-tag",toneOf(isCellObject(item)?item.tone:null));setText(tag,cellText(item,column,fmt));box.appendChild(tag)}
59
+ element.appendChild(box);more(count-Math.min(limit,list.length));return}
60
+ const first=list[0];add((kind==="items"?cellText(first,column,fmt):kind==="fields"?cellText(first?.value,{kind:"text"},fmt):
61
+ kind==="records"?recordRowTitle(cell.records,first,fmt):kind==="events"?first?.summary:first?.name)||"—");more(count-1)};let recordNestedSeq=0;function recordEmit(view,name,detail){let go=view.host.dispatchEvent(new CustomEvent("canopyx:"+name,{detail,cancelable:true,bubbles:true}));const callback=view.opts["on"+name[0].toUpperCase()+ name.slice(1)];if(typeof callback==="function"){try{go=callback(detail)!==false&&go}catch(error){console.error(error)}}
62
+ return go}
63
+ const recordRowRef=(list,row)=>list.target?.view?{view:list.target.view,id:row.id}:
64
+ list.columns.map(column=>row.cells?.[column.id]).find(cell=>isCellObject(cell)&&recordRefValid(cell.ref))?.ref||null;const recordCollectionComplete=list=>!!list.roots||!Number.isInteger(list.total)||list.rows.length>=list.total;const recordTargetFilters=target=>Array.isArray(target.filters)&&target.filters.length?target.filters:null;const recordTargetValues=target=>Array.isArray(target.values)&&target.values.length?target.values:null;const recordCanOpenAll=list=>!!recordTargetFilters(list.target)||!!(list.target.column&&recordTargetValues(list.target))||
65
+ recordCollectionComplete(list)&&(!list.target.column||!!recordCollectionIds(list,1000)?.length);function recordCollectionIds(list,maximum=Infinity){if(!list.roots)return list.rows.length>maximum?null:list.rows.map(row=>row.id);const ids=[],pending=[list.roots[Symbol.iterator]()];while(pending.length){const next=pending[pending.length-1].next();if(next.done){pending.pop();continue}
66
+ if(ids.length>=maximum)return null;const node=next.value;ids.push(node.id);if(node.children?.length)pending.push(node.children[Symbol.iterator]())}
67
+ return ids}
68
+ function recordCollection(ctx,field,list,element){if(!list||typeof list!=="object"||!Array.isArray(list.columns)||!list.columns.length||list.columns.some(column=>!column||!column.id||!recordText(column.title))||
69
+ (list.roots!==undefined?!Array.isArray(list.roots):list.rows!==undefined&&!Array.isArray(list.rows)))recordFail("a collection has columns and rows (or tree roots).");list.rows||=[];const rows=list.rows,total=Number.isInteger(list.total)?Math.max(list.total,rows.length):(list.roots||rows).length,labels=ctx.labels;const block=h("div","cx-record-collection"),head=h("div","cx-record-collection-h"),count=h("span","cx-record-count");setText(count,list.roots||total===rows.length?fill(labels.recordItems,{count:recordCount(ctx,total)}):
70
+ fill(labels.recordCount,{shown:recordCount(ctx,rows.length),total:recordCount(ctx,total)}));if(total>5||total>rows.length||ctx.print)head.appendChild(count);if(!ctx.print&&list.target?.view){const openAll=recordButton(labels.recordOpenAll,()=>recordOpenAll(ctx,field,list).catch(error=>ctx.view.emit("error",{error})),"cx-record-open-all","open");openAll.disabled=!recordCanOpenAll(list);head.appendChild(openAll)}
71
+ const body=h("div","cx-record-collection-b");if(head.firstChild)block.appendChild(head);block.appendChild(body);if(ctx.print)recordTable(ctx,list,body);else if(ctx.phone&&!list.roots)recordCards(ctx,field,list,body);else recordNested(ctx,field,list,body);if(!ctx.print&&!list.roots&&rows.length<total&&recordLoader(ctx.view)){const more=recordButton(labels.recordLoadMore,()=>recordMore(ctx,field,list,more),"cx-record-load-more");block.appendChild(more)}
72
+ element.appendChild(block)}
73
+ function recordNested(ctx,field,list,body){const grid=recordGridHelpers(),host=h("div","cx-host cx-record-nested"),rows=list.rows,tree=!!list.roots||!grid.createDataGrid;host.setAttribute("data-cx-theme",ctx.view.host.getAttribute("data-cx-theme")||"auto");const columns=list.columns.map(column=>({kind:"text",sortable:true,...column})),id="cx-record-" + ++recordNestedSeq;const byKey=new Map(rows.map((row,at)=>["r"+String(at).padStart(6,"0"),row]));const open=item=>{const row=byKey.get(item.id)||item,ref=recordRowRef(list,row);if(ref)ctx.navigate(ref,host)};let api;if(tree){const roots=list.roots||rows.map(row=>({id:row.id,label:recordRowTitle(list,row,ctx.fmt),cells:row.cells}));host.classList.add("cx-record-nested-tree");api=createTreeGrid(host,{view:{protocol:PROTOCOL,type:"view",id,label:field.title,columns,source:{kind:"inline"},roots,rowHeight:30},labels:ctx.view.opts.labels,toolbar:false,onDetails:({node})=>open(node)})}else{const length=Math.min(Math.max(list.pageLength||10,1),100),paged=rows.length>length;api=grid.createDataGrid(host,{view:{protocol:PROTOCOL,type:"grid",id,label:field.title,rowHeight:30,pageSize:Math.min(10000,Math.max(rows.length,1)),selection:"none",search:rows.length>8,columns,source:{kind:"inline"},rows:[...byKey].map(([key,row])=>({...row,id:key})),toolbar:{filters:false,columns:false,views:false,export:false,more:false,count:false,columnMenus:false},...(paged?{presentation:"paged",pageLength:length}:{}),rowAction:rows.some(row=>recordRowRef(list,row))?"details":"none"},labels:ctx.view.opts.labels,...(rows.length>8?{}:{toolbar:false}),onDetails:({row})=>open(row)})}
74
+ host.style.setProperty("--cx-record-rows",String(Math.min(tree?(list.roots||rows).length:Math.min(rows.length,list.pageLength||10),12)));body.appendChild(host);recordOnDispose(ctx.signal,()=>api.destroy());api.ready?.catch(error=>{if(!ctx.signal.aborted)ctx.view.emit("error",{error})})}
75
+ function recordCards(ctx,field,list,body){const holder=h("div","cx-record-cards"),rows=list.rows,columns=list.columns,step=10;const card=row=>{const item=h("div","cx-record-card"),title=h("div","cx-record-card-title"),ref=recordRowRef(list,row),text=recordRowTitle(list,row,ctx.fmt);item.setAttribute("role","group");item.setAttribute("aria-label",text);if(ref)recordLink(ctx,{value:text,ref},{id:field.id,kind:"text"},title);else setText(title,text);const fields=h("dl","cx-dl");for(const column of columns.slice(1)){const cell=row.cells?.[column.id],spec={id:column.id,title:column.title,kind:column.kind||"text"};if(recordEmpty(cell,spec,ctx.fmt))continue;const term=h("dt"),value=h("dd");setText(term,column.title);recordValue(ctx,spec,cell,value,1);fields.append(term,value)}
76
+ item.append(title,fields);return item};for(const row of rows.slice(0,step))holder.appendChild(card(row));body.appendChild(holder);if(rows.length>step){const more=recordButton(fill(ctx.labels.recordShowAll,{count:recordCount(ctx,rows.length)}),()=>{more.remove();for(const row of rows.slice(step))holder.appendChild(card(row));holder.children[step]?.querySelector("button")?.focus()},"cx-record-more");body.appendChild(more)}}
77
+ function recordTable(ctx,list,body){const table=h("table","cx-record-table"),head=h("tr"),thead=h("thead"),tbody=h("tbody");for(const column of list.columns){const cell=h("th");setText(cell,column.title);head.appendChild(cell)}
78
+ const add=(row,level)=>{const line=h("tr");list.columns.forEach((column,index)=>{const cell=h("td"),value=row.cells?.[column.id]??(index?null:row.label);if(!index&&level)cell.style.paddingInlineStart=(level*16+6)+ "px";recordValue(ctx,{id:column.id,title:column.title,kind:column.kind||"text"},value,cell,1);line.appendChild(cell)});tbody.appendChild(line);for(const child of row.children||[])add(child,level+1)};for(const row of list.roots||list.rows)add(row,0);thead.appendChild(head);table.append(thead,tbody);body.appendChild(table)}
79
+ async function recordMore(ctx,field,list,button){button.disabled=true;setText(button,ctx.labels.loading);try{const payload=await recordFetch(ctx.view,ctx.record.id,{field:field.id,offset:list.rows.length,limit:list.pageSize||50},ctx.signal);if(ctx.signal.aborted)return;const page=(payload?.fields?.[field.id]??payload?.cells?.[field.id])?.records;if(!page||!Array.isArray(page.rows))recordFail("a field page answers with the field's records.");const known=new Set(list.rows.map(row=>row.id));validateGridRows(page.rows,list.columns.map(column=>({kind:"text",...column})),known);const total=page.total??list.total;if(total!=null&&(!Number.isInteger(total)||total<known.size))recordFail("a collection page's total cannot be below its accepted rows.");if(!page.rows.length&&(!Number.isInteger(total)||total>known.size))recordFail("a collection page cannot end before its declared total.");list.rows.push(...page.rows);if(page.total!=null)list.total=page.total;ctx.repaint()}catch(error){if(!button.isConnected)return;button.disabled=false;setText(button,ctx.labels.recordLoadMore);recordAnnounce(ctx.dialog,fill(ctx.labels.recordLoadFailed,{error:error.message}));ctx.view.emit("error",{error})}}
80
+ async function recordOpenAll(ctx,field,list){if(!recordCanOpenAll(list))return;const target=list.target,ids=recordCollectionIds(list),explicitFilters=recordTargetFilters(target);const filters=explicitFilters||(target.column?[{column:target.column,operator:"in",values:recordTargetValues(target)||ids}]:null);const detail=Object.freeze({view:target.view,filters,ids,field:field.id,record:ctx.record.id,total:Number.isInteger(list.total)?list.total:(list.roots||list.rows).length});if(!recordEmit(ctx.view,"openAll",detail))return;const api=recordApi(target.view);if(!api||!filters||api.view.type!=="grid"){recordAnnounce(ctx.dialog,fill(ctx.labels.recordUnavailable,{id:target.view}));return}
81
+ const values=!explicitFilters&&target.column&&filters[0].values,linked=RECORD_IMPL.grid?.DataGrid?.prototype.setExternalFilter;let external;if(values&&typeof linked==="function"&&!linked.linkStub&&typeof api.setExternalFilter==="function"){let sourceLabel=(ctx.dialog.querySelector(".cx-drawer-h h4")?.textContent||ctx.record.id)+ " · " +(field.title||field.id);if(sourceLabel.length>128)sourceLabel=sourceLabel.slice(0,127)+ "…";external=await Promise.resolve().then(()=>api.setExternalFilter("record-"+field.id,{field:target.column,values,sourceLabel,label:fill(ctx.labels.recordItems,{count:recordCount(ctx,values.length)})}))
82
+ .then(()=>true,()=>false)}else external=false;if(!external){const query=api.getQuery()||{};await api.setQuery({sort:query.sort||[],search:"",filters})}
83
+ ctx.dialog.close();api.element.scrollIntoView({block:"start"});api.focus()}
84
+ function recordTimeline(ctx,field,events,element){const list=h("ol","cx-timeline"),limit=ctx.print?events.length:20;let day=null;const add=event=>{if(!event||typeof event!=="object"||!recordText(event.summary,4096)||event.time!==undefined&&typeof event.time!=="string")
85
+ recordFail("a timeline event has a summary and an ISO time.");const label=event.time?formatValue(event.time,"datetime",ctx.fmt):"",date=label.slice(0,10);if(date&&date!==day){day=date;const heading=h("li","cx-timeline-day");setText(heading,day);list.appendChild(heading)}
86
+ const item=h("li","cx-timeline-item"),dot=h("span"),main=h("div","cx-timeline-main"),meta=h("div","cx-timeline-meta"),summary=h("div","cx-timeline-summary");applyTone(dot,"cx-timeline-dot",toneOf(event.tone||"neutral"));dot.setAttribute("aria-hidden","true");if(label){const time=h("time");time.dateTime=event.time;time.title=label;setText(time,label.length>11?label.slice(11):label);meta.appendChild(time)}
87
+ if(event.kind){const kind=h("span");applyTone(kind,"cx-record-chip",toneOf(event.tone||null));setText(kind,event.kind);meta.appendChild(kind)}
88
+ if(event.actor){const actor=h("span","cx-timeline-actor");setText(actor,event.actor);meta.appendChild(actor)}
89
+ if(event.ref&&recordRefValid(event.ref))recordLink(ctx,{value:event.summary,ref:event.ref},field,summary);else setText(summary,event.summary);main.append(meta,summary);if(Array.isArray(event.changes)&&event.changes.length)recordChanges(ctx,field,event.changes,main,true);item.append(dot,main);list.appendChild(item)};events.slice(0,limit).forEach(add);element.appendChild(list);if(events.length>limit){const more=recordButton(fill(ctx.labels.recordShowAll,{count:recordCount(ctx,events.length)}),()=>{more.remove();events.slice(limit).forEach(add);list.querySelectorAll(".cx-timeline-item")[limit]?.querySelector("button")?.focus()},"cx-record-more");element.appendChild(more)}}
90
+ function recordTokens(ctx,field,items,other,cell,mark,word){const keys=new Set(other.map(item=>cellText(item,field,ctx.fmt))),box=h("span","cx-record-chips");for(const item of items){const chip=recordChip(ctx,field,item),changed=!keys.has(cellText(item,field,ctx.fmt));if(changed){chip.classList.add(mark);const note=h("span","cx-sr-only");setText(note,word+": ");chip.prepend(note)}
91
+ box.appendChild(chip)}
92
+ cell.appendChild(box)}
93
+ function recordChanges(ctx,field,changes,element,compact){const table=h("table","cx-record-diff" +(compact?" cx-record-diff-compact":"")),caption=h("caption","cx-sr-only"),head=h("tr"),body=h("tbody"),labels=ctx.labels;setText(caption,fill(labels.recordChanged,{count:recordCount(ctx,changes.length)}));for(const text of[labels.recordField,labels.recordBefore,labels.recordAfter]){const cell=h("th");cell.scope="col";setText(cell,text);head.appendChild(cell)}
94
+ for(const change of changes){if(!change||!recordText(change.name,4096))recordFail("a change names its field.");const line=h("tr"),name=h("th"),before=h("td","cx-diff-before"),after=h("td","cx-diff-after"),spec={id:field.id,title:change.name,kind:change.kind||"text",nested:true};name.scope="row";setText(name,change.name);if(recordKind(change.before)==="items"&&recordKind(change.after)==="items"){recordTokens(ctx,spec,change.before.items,change.after.items,before,"cx-diff-removed",labels.recordRemoved);recordTokens(ctx,spec,change.after.items,change.before.items,after,"cx-diff-added",labels.recordAdded)}else{recordValue(ctx,spec,change.before??null,before,1);recordValue(ctx,spec,change.after??null,after,1)}
95
+ line.append(name,before,after);body.appendChild(line)}
96
+ const thead=h("thead");thead.appendChild(head);table.append(caption,thead,body);element.appendChild(table)}
97
+ let RECORD_SHOW_EMPTY=false;const recordId=(dialog,kind,id)=>dialog.id+"-"+kind+"-"+String(id).replace(/[^\w-]/g, "_");
98
+ const recordOnDispose=(signal,cleanup)=>{const dispose=()=>{try{cleanup()}catch(error){console.error(error)}};if(signal.aborted)dispose();else signal.addEventListener("abort",dispose,{once:true})};function recordContext(view,record,dialog,context,payload){const ctx={view,record,payload,dialog,labels:view.labels,fmt:view.fmt,signal:context.signal,index:context.index,origins:0,pending:[],phone:view.host.clientWidth<=640,print:!!context.print,width:context.print?520:view.host.clientWidth<=640?300:380,row:{id:record.id,cells:recordMerge(record.cells,payload?.cells,record.fields,payload?.fields)},node:view.kind==="tree"?{...record,cells:recordMerge(record.cells,payload?.cells)}:null};ctx.navigate=(ref,origin)=>recordNavigate(ctx,ref,origin);ctx.repaint=()=>{if(!context.signal.aborted&&dialog._cxRecord===record&&dialog.isConnected)recordRepaint(view,dialog,record,context.index)};return ctx}
99
+ function recordMerge(...sources){const cells=Object.create(null);for(const source of sources)if(source)for(const key of Object.keys(source))if(key!=="__proto__")cells[key]=source[key];return cells}
100
+ function recordRepaint(view,dialog,record,index){const body=dialog.querySelector(".cx-drawer-body"),scroll=body?.scrollTop||0,active=document.activeElement,inside=body?.contains(active);const section=inside&&active.closest("[data-cx-section]")?.getAttribute("data-cx-section"),field=inside&&active.closest("[data-cx-field]")?.getAttribute("data-cx-field");const kind=inside&&[...active.classList].find(name=>name.startsWith("cx-record-")),id=inside&&active.id;dialog._cxPaint(record,index);if(body)body.scrollTop=scroll;if(!inside||body.contains(document.activeElement))return;const scope=field?body.querySelector('[data-cx-field="'+CSS.escape(field)+ '"]'):section?body.querySelector('[data-cx-section="'+CSS.escape(section)+ '"]'):body;const title=dialog.querySelector(".cx-drawer-h h4"),target=id&&body.querySelector("#"+CSS.escape(id))||kind&&scope?.querySelector("."+kind)||title;if(target===title)view.focusRing(title);else target?.focus({preventScroll:true})}
101
+ const recordVisible=(ctx,field,cell,showEmpty)=>showEmpty||!recordEmpty(cell,field,ctx.fmt)||ctx.view.recordKeepField?.(field.id,ctx.record)===true;function recordHasContent(ctx,section,showEmpty){return!!section.renderer||section.fields.some(field=>recordVisible(ctx,field,recordCell(ctx.view,ctx.record,ctx.payload,field),showEmpty))||
102
+ section.sections.some(child=>recordHasContent(ctx,child,showEmpty))}
103
+ function recordEmptyCount(ctx,sections){return sections.reduce((count,section)=>count+section.fields.filter(field=>recordEmpty(recordCell(ctx.view,ctx.record,ctx.payload,field),field,ctx.fmt)).length +
104
+ recordEmptyCount(ctx,section.sections),0)}
105
+ function recordFieldsInto(ctx,fields,content,showEmpty){let list=null;for(const field of fields){const cell=recordCell(ctx.view,ctx.record,ctx.payload,field);if(!recordVisible(ctx,field,cell,showEmpty))continue;const kind=recordKind(cell);if(kind==="records"||kind==="events"||kind==="changes"){const block=h("div","cx-record-block"),heading=h("div","cx-record-block-h"),value=h("div","cx-record-block-b");setText(heading,field.title);block.setAttribute("data-cx-field",field.id);value.setAttribute("data-cx-field",field.id);block.append(heading,value);content.appendChild(block);list=null;recordValue(ctx,field,cell,value);continue}
106
+ if(!list){list=h("dl","cx-dl cx-record-fields");content.appendChild(list)}
107
+ const term=h("dt"),value=h("dd");setText(term,field.title);term.setAttribute("data-cx-field",field.id);value.setAttribute("data-cx-field",field.id);list.append(term,value);recordValue(ctx,field,cell,value)}}
108
+ function recordSection(ctx,section,state,showEmpty){if(!recordHasContent(ctx,section,showEmpty))return null;const element=h("section","cx-record-section cx-record-depth-"+section.depth),heading=h("h3","cx-record-section-h"),content=h("div","cx-record-section-b");element.id=recordId(ctx.dialog,"s",section.id);element.setAttribute("data-cx-section",section.id);content.id=element.id+"-b";heading.setAttribute("aria-level",String(3+section.depth));const collapsed=!ctx.print&&(state.collapsed.has(section.id)?state.collapsed.get(section.id):section.collapsed);if(ctx.print)setText(heading,section.label);else{const toggle=recordButton(section.label,()=>{const open=toggle.getAttribute("aria-expanded")!=="true";state.collapsed.set(section.id,!open);toggle.setAttribute("aria-expanded",String(open));content.hidden=!open;if(open)recordMount(ctx,content)},"cx-record-toggle","chevron");toggle.setAttribute("aria-expanded",String(!collapsed));toggle.setAttribute("aria-controls",content.id);heading.appendChild(toggle)}
109
+ element.append(heading,content);content.hidden=collapsed;if(section.renderer)recordCustom(ctx,section,content);recordFieldsInto(ctx,section.fields,content,showEmpty);for(const child of section.sections){const nested=recordSection(ctx,child,state,showEmpty);if(nested)content.appendChild(nested)}
110
+ return element}
111
+ function recordCustom(ctx,section,content){const view=ctx.view,renderer=view.plugins?.map(item=>item.drawerSections?.[section.renderer]).find(item=>typeof item==="function")||view.opts.recordSections?.[section.renderer];if(typeof renderer!=="function")return;const holder=h("div","cx-record-custom");content.appendChild(holder);const values=Object.fromEntries(recordFields(view).map(field=>[field.id,recordCell(view,ctx.record,ctx.payload,field)]));const context=Object.freeze({section:section.id,view:view.view.id,api:view.host.canopyx,labels:ctx.labels,signal:ctx.signal,payload:ctx.payload,values,print:ctx.print,width:ctx.width,onDispose:cleanup=>recordOnDispose(ctx.signal,cleanup)});let pending;try{pending=Promise.resolve(renderer(JSON.parse(JSON.stringify(ctx.record)),holder,context))}
112
+ catch(error){pending=Promise.reject(error)}
113
+ ctx.pending.push(pending);pending.catch(error=>{if(!ctx.signal.aborted)view.emit("error",{error})})}
114
+ function recordMount(ctx,content){for(const host of content.querySelectorAll(".cx-record-nested"))host.canopyx?.refresh()}
115
+ function recordTabs(ctx,layout,state,tabs,select){const list=h("div","cx-record-tabs");list.setAttribute("role","tablist");list.setAttribute("aria-label",ctx.labels.recordTabs);const buttons=tabs.map(tab=>{const button=h("button","cx-record-tab");button.type="button";setText(button,tab.label);button.id=recordId(ctx.dialog,"t",tab.id);button.setAttribute("role","tab");const selected=tab.id===state.tab;if(selected)button.setAttribute("aria-controls",recordId(ctx.dialog,"p",tab.id));button.setAttribute("aria-selected",String(selected));button.tabIndex=selected?0:-1;button.addEventListener("click",()=>select(tab.id,true));return button});list.addEventListener("keydown",event=>{const at=buttons.indexOf(document.activeElement);if(at<0)return;const next={ArrowRight:at+1,ArrowLeft:at-1,Home:0,End:buttons.length-1}[event.key];if(next===undefined)return;event.preventDefault();const target=buttons[(next+buttons.length)%buttons.length];select(tabs[buttons.indexOf(target)].id,false);ctx.dialog.querySelector("#"+CSS.escape(target.id))?.focus()});list.append(...buttons);return list}
116
+ RECORD_IMPL.paint=(view,record,body,dialog,context)=>{const state=dialog._cxPanel||={stack:[],tab:null,collapsed:new Map()};dialog.id||=view.id+"-record";if(state.recordId!==record.id){state.collapsed=new Map();state.recordId=record.id}
117
+ state.index=context.index;let layout;try{layout=recordLayout(view,recordFields(view))}
118
+ catch(error){view.emit("error",{error});return view.paintDrawerBody.call(Object.create(view,{recordNeeded:{value:()=>false}}),record,body,dialog,context)}
119
+ const entry=recordEnsure(view,record.id),payload=entry?.state==="ready"?entry.payload:null,ctx=recordContext(view,record,dialog,context,payload);if(view.loadHistory&&!view._recordHistory&&(view.view.record?.fields||[]).some(field=>["statusStrip","sparklineBars","sparklineLine"].includes(field.presenter?.kind)))
120
+ view._recordHistory=Promise.resolve(view.loadHistory()).then(()=>{if(dialog.isConnected&&dialog._cxRecord)recordRepaint(view,dialog,dialog._cxRecord,dialog._cxPanel?.index)},()=>{});const showEmpty=RECORD_SHOW_EMPTY||!layout.hideEmpty;const tabs=layout.tabs.filter(tab=>tab.sections.some(section=>recordHasContent(ctx,section,showEmpty)));if(!tabs.length)tabs.push(layout.tabs[0]);if(!tabs.some(tab=>tab.id===state.tab))state.tab=tabs[0].id;recordSummary(ctx,layout,dialog);body.replaceChildren();const tools=h("div","cx-record-tools"),panel=h("div","cx-record-panel"),sub=h("div","cx-record-subtools");let tabLifetime,tabContext;const paintTab=()=>{tabLifetime?.abort();tabLifetime=new AbortController();tabContext=recordContext(view,record,dialog,{...context,signal:AbortSignal.any([context.signal,tabLifetime.signal])},payload);const tab=tabs.find(item=>item.id===state.tab),sections=tab.sections.map(section=>recordSection(tabContext,section,state,showEmpty)).filter(Boolean);panel.replaceChildren(...sections);sub.replaceChildren();if(tabs.length>1){panel.setAttribute("role","tabpanel");panel.id=recordId(dialog,"p",tab.id);panel.setAttribute("aria-labelledby",recordId(dialog,"t",tab.id));panel.tabIndex=0}
121
+ if(layout.jump!==false&&sections.length>=(layout.jump?2:4)){const jump=h("nav","cx-record-jump");jump.setAttribute("aria-label",ctx.labels.recordSections);for(const element of sections){const target=element.querySelector(".cx-record-toggle");jump.appendChild(recordButton(target.textContent,()=>{element.scrollIntoView({block:"start"});target.focus({preventScroll:true})},"cx-record-jump-link"))}
122
+ sub.appendChild(jump)}
123
+ const hidden=layout.hideEmpty?recordEmptyCount(ctx,layout.tabs.flatMap(item=>item.sections)):0;if(hidden||RECORD_SHOW_EMPTY&&layout.hideEmpty){const toggle=recordButton(RECORD_SHOW_EMPTY?ctx.labels.recordHideEmpty:fill(ctx.labels.recordShowEmpty,{count:recordCount(ctx,hidden)}),()=>{RECORD_SHOW_EMPTY=!RECORD_SHOW_EMPTY;recordRepaint(view,dialog,record,context.index);dialog.querySelector(".cx-record-empty")?.focus()},"cx-record-empty");toggle.setAttribute("aria-pressed",String(RECORD_SHOW_EMPTY));sub.appendChild(toggle)}
124
+ sub.hidden=!sub.firstChild};const select=(id,focus)=>{state.tab=id;for(const button of tools.querySelectorAll("[role=tab]")){const on=button.id===recordId(dialog,"t",id);button.setAttribute("aria-selected",String(on));button.tabIndex=on?0:-1;if(on)button.setAttribute("aria-controls",recordId(dialog,"p",id));else button.removeAttribute("aria-controls")}
125
+ paintTab();recordMount(tabContext,panel);dialog.dispatchEvent(new CustomEvent("cx-drawer-paint",{detail:{id:record.id,index:context.index??null}}));if(focus)tools.querySelector("[aria-selected=true]")?.focus()};if(tabs.length>1)tools.appendChild(recordTabs(ctx,layout,state,tabs,select));tools.appendChild(sub);paintTab();body.append(tools,panel);tools.hidden=tabs.length<2&&sub.hidden;if(entry?.state==="loading"){const note=h("p","cx-record-note");setText(note,ctx.labels.loading);panel.prepend(note);entry.promise.then(()=>ctx.repaint(),()=>ctx.repaint())}else if(entry?.state==="error"){const note=h("p","cx-record-note cx-record-error");setText(note,fill(ctx.labels.recordLoadFailed,{error:entry.error.message}));note.setAttribute("role","alert");note.appendChild(recordButton(ctx.labels.recordRetry,()=>{view._recordPayloads.delete(recordCacheKey(view,record.id));ctx.repaint()},"cx-record-retry"));panel.prepend(note)}
126
+ recordLinkWrite(view,record,dialog)};function recordSummary(ctx,layout,dialog){const box=dialog.querySelector(".cx-record-summary");if(!box)return;box.replaceChildren();const header=layout.header,value=id=>{const field=layout.byId.get(id);return field&&[field,recordCell(ctx.view,ctx.record,ctx.payload,field)]};if(header?.status){const[field,cell]=value(header.status)||[];if(field&&!recordEmpty(cell,field,ctx.fmt)){const status=h("div","cx-record-status");status.setAttribute("data-cx-fact",field.id);recordValue(ctx,field,cell,status);box.appendChild(status)}}
127
+ const facts=h("dl","cx-record-facts");for(const id of header?.facts||[]){const[field,cell]=value(id)||[];if(!field||recordEmpty(cell,field,ctx.fmt))continue;const item=h("div","cx-record-fact"),term=h("dt"),detail=h("dd");item.setAttribute("data-cx-fact",field.id);setText(term,field.title);recordValue(ctx,field,cell,detail);item.append(term,detail);facts.appendChild(item)}
128
+ if(facts.firstChild)box.appendChild(facts);box.hidden=!box.firstChild}
129
+ function recordApi(id){for(const host of document.querySelectorAll("[data-canopyx-mounted]"))if(host.canopyx?.view?.id===id)return host.canopyx;return null}
130
+ function recordAnnounce(dialog,text){const live=dialog?.querySelector(".cx-record-live");if(!live)return;setText(live,"");setTimeout(()=>setText(live,text),50)}
131
+ const recordTitle=dialog=>dialog.querySelector(".cx-drawer-h h4")?.textContent||"";function recordNavigate(ctx,ref,origin){const view=ctx.view,dialog=ctx.dialog,state=dialog._cxPanel||{stack:[]};const entry={view:view.view.id,id:ctx.record.id,title:recordTitle(dialog),tab:state.tab,origin:origin?.getAttribute?.("data-cx-origin")||null};const api=ref.view&&ref.view!==view.view.id?recordApi(ref.view):view.host.canopyx;if(!api?.openRecord){recordAnnounce(dialog,fill(ctx.labels.recordUnavailable,{id:ref.id}));return Promise.resolve()}
132
+ return api.openRecord(ref.id,{stack:[...state.stack,entry].slice(-20),returnFocus:dialog._returnFocus,path:ref.path})
133
+ .then(()=>recordRetire(dialog),error=>{recordAnnounce(dialog,fill(ctx.labels.recordUnavailable,{id:ref.id}));view.emit("error",{error})})}
134
+ function recordBack(view,dialog,steps=1){const stack=dialog._cxPanel?.stack||[],entry=stack[stack.length-steps],api=entry&&recordApi(entry.view);if(!api)return;api.openRecord(entry.id,{stack:stack.slice(0,stack.length-steps),tab:entry.tab,origin:entry.origin,back:true,returnFocus:dialog._returnFocus})
135
+ .then(()=>recordRetire(dialog),error=>{recordAnnounce(dialog,fill(view.labels.recordUnavailable,{id:entry.id}));view.emit("error",{error})})}
136
+ function recordRetire(dialog){if(dialog.isConnected&&dialog.open&&document.querySelectorAll("dialog.cx-drawer[open]").length>1){dialog._replaced=true;dialog.close();dialog.remove()}}
137
+ RECORD_IMPL.open=async(view,id,options={})=>{requireIdentifier(id,"record ID");if(view.destroyed)recordFail("the view was destroyed.");await view.ready;const dialog=view.kind==="tree"?await recordOpenNode(view,id,options):await recordOpenRow(view,id,options);if(!dialog)return;const origin=options.origin&&dialog.querySelector('[data-cx-origin="'+CSS.escape(options.origin)+ '"]');if(origin)origin.focus({preventScroll:false});if(options.stack)recordAnnounce(dialog,fill(options.back?view.labels.recordBackTo:view.labels.recordShowing,{record:recordTitle(dialog)}))};async function recordOpenRow(view,id,options){await view.requirePart("filter-editor");let index=null,row=null;const loaded=[...view.rowCache.values()].find(item=>!item.status&&item.key===id);if(loaded){row=loaded.h;index=loaded._ri;if(!view.pendingQuery)await view.focusResult(index,false).catch(()=>{})}
138
+ else if(view.acceptedQuery&&!view.pendingQuery&&typeof view.source.position==="function"){const position=await view.runGridHook(signal=>view.source.position(view.acceptedQuery,id,{signal}));if(Number.isInteger(position)&&position>=0&&position<view.rowCount()){await view.focusResult(position,false);const item=view.rowCache.get(position);if(item&&!item.status&&item.key===id){row=item.h;index=position}}}
139
+ if(!row&&typeof view.source.row==="function")row=view.source.row(id);if(!row&&recordLoader(view)){const key=recordCacheKey(view,id);const payload=await recordFetch(view,id,{row:true});if(payload?.row){row=payload.row;(view._recordPayloads||=new Map()).set(key,{state:"ready",payload,promise:Promise.resolve(payload)})}}
140
+ if(!row)recordFail("record "+id+" is not available.");const returnFocus=options.returnFocus||document.activeElement;if(typeof view.opts.onDetails==="function"){const record=recordGridHelpers().gridFreeze(JSON.parse(JSON.stringify(row)));await view.runGridHook(signal=>view.opts.onDetails({row:record,query:view.acceptedQuery,signal,returnFocus}));return null}
141
+ return view.openGridDrawer(row,index,returnFocus,options)}
142
+ async function recordOpenNode(view,id,options){await view.requirePart("tree-tools");let w=view.keyMap.get(id);if(!w&&Array.isArray(options.path)&&options.path.length){await view.expandPath(options.path,{focus:false});w=view.keyMap.get(id)}
143
+ if(!w)recordFail("record "+id+" is not available.");return view.showDetails(id,{...options,node:w.h})}
144
+ const recordLinkKey=view=>view.view.record?.deepLink?.key||"record";const recordLinkParams=()=>(global.location.hash||"").replace(/^#/, "").split("&").filter(Boolean);
145
+ const recordLinkPath=ids=>ids.map(encodeURIComponent).join("/");function recordLinkRead(view){const prefix=recordLinkKey(view)+ "=";for(const param of recordLinkParams()){const value=param.startsWith(prefix)?param.slice(prefix.length):"",at=value.indexOf(":");if(at<1)continue;try{if(decodeURIComponent(value.slice(0,at))!==view.view.id)continue;const rest=value.slice(at+1),ids=(view.kind==="tree"?rest.split("/"):[rest]).map(decodeURIComponent);if(ids.every(id=>id))return ids}catch(error){}}
146
+ return null}
147
+ function recordLinkFor(view,record){const ids=[];if(view.kind==="tree")for(let w=view.keyMap.get(record.id);w&&w!==view.root&&w.key!=null;w=w.parent)ids.unshift(w.key);return recordLinkKey(view)+ "="+encodeURIComponent(view.view.id)+ ":"+recordLinkPath(ids.length?ids:[record.id])}
148
+ const recordLinkPrefix=view=>recordLinkKey(view)+ "="+encodeURIComponent(view.view.id)+ ":";function recordAddress(view,record){const prefix=recordLinkPrefix(view),params=recordLinkParams().filter(param=>!param.startsWith(prefix));params.push(recordLinkFor(view,record));return global.location.href.replace(/#.*$/, "") + "#" + params.join("&");
149
+ }
150
+ function recordLinkWrite(view,record,dialog){if(!view.view.record?.deepLink)return;const link=record&&recordLinkFor(view,record);view._recordLinkOwner=record?{dialog,link}:null;const prefix=recordLinkPrefix(view),params=recordLinkParams().filter(param=>!param.startsWith(prefix));if(record)params.push(link);const hash=params.length?"#"+params.join("&"):"";if((global.location.hash||"")===hash)return;try{global.history.replaceState(global.history.state,"",hash||global.location.pathname+global.location.search)}
151
+ catch(error){}
152
+ view._recordLinkOpen=record?recordLinkPath(recordLinkRead(view)||[]):null}
153
+ RECORD_IMPL.start=view=>{if(view._recordStarted||!view.view.record?.deepLink)return;view._recordStarted=true;const read=()=>{const ids=recordLinkRead(view),key=ids?recordLinkPath(ids):null,owner=view._recordLinkOwner?.dialog;if(!ids){view._recordLinkOpen=null;view._recordLinkOwner=null;return}
154
+ if(key===view._recordLinkOpen&&(!owner||owner.open||owner._replaced))return;view._recordLinkOwner=null;view._recordLinkOpen=key;RECORD_IMPL.open(view,ids[ids.length-1],{path:ids}).catch(error=>view.emit("error",{error}))};global.addEventListener("hashchange",read,{signal:view.lifetime.signal});view.lifetime.signal.addEventListener("abort",()=>{view._recordLinkOwner=null;view._recordLinkOpen=null},{once:true});Promise.resolve(view.ready).then(read,()=>{})};RECORD_IMPL.decorate=(view,dialog,{head,identity,options})=>{if(!view.view.record)return;try{recordSpec(view)}catch(error){return}
155
+ dialog.id||=view.id+"-record";dialog.classList.add("cx-record-drawer");const state=dialog._cxPanel={stack:Array.isArray(options.stack)?options.stack:[],tab:options.tab||null,collapsed:new Map()},labels=view.labels;const live=h("div","cx-record-live cx-sr-only");live.setAttribute("aria-live","polite");dialog.appendChild(live);if(state.stack.length){const trail=h("nav","cx-record-trail"),crumbs=h("ol","cx-record-crumbs"),last=state.stack[state.stack.length-1];trail.setAttribute("aria-label",labels.recordTrail);const back=recordButton(labels.recordBack,()=>recordBack(view,dialog),"cx-record-back","back");back.setAttribute("aria-label",fill(labels.recordBackTo,{record:last.title||last.id}));state.stack.slice(-3).forEach((entry,at,list)=>{const item=h("li");item.appendChild(recordButton(entry.title||entry.id,()=>recordBack(view,dialog,list.length-at),"cx-record-crumb"));crumbs.appendChild(item)});trail.append(back,crumbs);identity.prepend(trail)}
156
+ const summary=h("div","cx-record-summary");summary.hidden=true;head.after(summary);recordActionsMenu(view,dialog,identity);dialog.addEventListener("keydown",event=>{if(event.altKey&&event.key==="ArrowLeft"&&state.stack.length){event.preventDefault();recordBack(view,dialog)}});dialog.addEventListener("close",()=>{if(view.destroyed)return;const owner=view._recordLinkOwner;if(owner?.dialog!==dialog)return;if(dialog._replaced){view._recordLinkOwner=null;return}
157
+ const ids=recordLinkRead(view);if(ids&&owner.link===recordLinkPrefix(view)+ recordLinkPath(ids))recordLinkWrite(view,null);view._recordLinkOwner=null;view._recordLinkOpen=null},{once:true})};function recordActionsMenu(view,dialog,identity){const spec=recordSpec(view),switches=spec.actions||{},labels=view.labels,items=[];const add=(label,task)=>items.push({label,task});if(switches.link!==false&&spec.deepLink)add(labels.recordCopyLink,()=>recordCopy(view,dialog,recordAddress(view,dialog._cxRecord)));if(switches.copy!==false){add(labels.recordCopyValues,()=>recordCopy(view,dialog,recordExport(view,dialog,"text")));add(labels.recordCopyJson,()=>recordCopy(view,dialog,recordExport(view,dialog,"json")))}
158
+ if(switches.export!==false){add(labels.recordExportCsv,()=>recordDownload(view,dialog,"csv"));add(labels.recordExportJson,()=>recordDownload(view,dialog,"json"))}
159
+ if(switches.print!==false)add(labels.recordPrint,()=>recordPrint(view,dialog));for(const action of[...(Array.isArray(view.opts.recordActions)?view.opts.recordActions:[]),...view.plugins.flatMap(item=>item.recordActions||[])]){if(!action||typeof action.label!=="string"||typeof action.run!=="function")continue;add(action.label,()=>{const record=dialog._cxRecord,entry=recordEntry(view,record.id);return action.run(Object.freeze({record:JSON.parse(JSON.stringify(record)),view:view.view.id,api:view.host.canopyx,payload:entry?.payload||null,signal:view.lifetime.signal}))})}
160
+ if(!items.length)return;const menu=h("div","cx-record-menu"),toggle=recordButton("",()=>show(list.hidden),"cx-record-menu-btn","more"),list=h("div","cx-record-menu-list");list.id=dialog.id+"-actions";list.setAttribute("role","menu");list.setAttribute("aria-label",labels.recordActions);list.hidden=true;toggle.setAttribute("aria-label",labels.recordActions);toggle.title=labels.recordActions;toggle.setAttribute("aria-haspopup","menu");toggle.setAttribute("aria-expanded","false");toggle.setAttribute("aria-controls",list.id);const show=open=>{list.hidden=!open;toggle.setAttribute("aria-expanded",String(open));if(open)buttons[0].focus()};const buttons=items.map(item=>{const button=recordButton(item.label,()=>{show(false);toggle.focus();Promise.resolve().then(item.task).catch(error=>{recordAnnounce(dialog,error.message);view.emit("error",{error})})},"cx-record-menu-item");button.setAttribute("role","menuitem");button.tabIndex=-1;return button});list.append(...buttons);menu.append(toggle,list);identity.after(menu);menu.addEventListener("keydown",event=>{if(list.hidden)return;if(event.key==="Escape"){event.preventDefault();event.stopPropagation();show(false);toggle.focus();return}
161
+ if(event.key==="Tab"){show(false);return}
162
+ const at=buttons.indexOf(document.activeElement);if(at<0||!["ArrowDown","ArrowUp","Home","End"].includes(event.key))return;event.preventDefault();event.stopPropagation();buttons[{ArrowDown:(at+1)%buttons.length,ArrowUp:(at-1+buttons.length)%buttons.length,Home:0,End:buttons.length-1}[event.key]].focus()});menu.addEventListener("focusout",event=>{if(!menu.contains(event.relatedTarget)&&event.relatedTarget)show(false)});dialog.addEventListener("pointerdown",event=>{if(!menu.contains(event.target))show(false)})}
163
+ async function recordCopy(view,dialog,text){if(!global.navigator.clipboard?.writeText)recordFail("the clipboard is not available.");await global.navigator.clipboard.writeText(text);recordAnnounce(dialog,view.labels.recordCopied)}
164
+ function recordFlat(cell,field,fmt){const kind=recordKind(cell),text=(value,spec=field)=>recordFlat(value,spec,fmt);if(kind==="items")return cell.items.map(item=>text(item)).join(", ");if(kind==="fields")return cell.fields.map(entry=>entry.name+": "+text(entry.value,{kind:entry.kind||"text"})).join("; ");if(kind==="records")return(cell.records.rows||cell.records.roots||[]).map(row=>cell.records.columns.map(column=>text(row.cells?.[column.id]??null,column)).filter(Boolean).join(" · ")).join("\n");if(kind==="events")return cell.events.map(event=>[event.time?formatValue(event.time,"datetime",fmt):"",event.kind,event.actor,event.summary].filter(Boolean).join(" · ")).join("\n");if(kind==="changes")return cell.changes.map(change=>change.name+": "+text(change.before??null)+ " → "+text(change.after??null)).join("\n");return cellText(cell,field,fmt)}
165
+ function recordData(view,dialog){const record=dialog._cxRecord,entry=recordEntry(view,record.id),payload=entry?.state==="ready"?entry.payload:null;const fields=recordFields(view),layout=recordLayout(view,fields),items=[],seen=new Set();const walk=(sections,path)=>{for(const section of sections){const name=path?path+" / "+section.label:section.label;for(const field of section.fields)if(!seen.has(field.id)){seen.add(field.id);items.push({section:name,field,cell:recordCell(view,record,payload,field)})}
166
+ walk(section.sections,name)}};walk(layout.tabs.flatMap(tab=>tab.sections),"");for(const field of fields)if(!seen.has(field.id))items.push({section:"",field,cell:recordCell(view,record,payload,field)});return{record,items}}
167
+ function recordExport(view,dialog,format){const{record,items}=recordData(view,dialog),labels=view.labels,title=recordTitle(dialog);if(format==="json")return JSON.stringify({view:view.view.id,id:record.id,title,fields:items.map(item=>
168
+ ({id:item.field.id,title:item.field.title,section:item.section,text:recordFlat(item.cell,item.field,view.fmt),value:item.cell===undefined?null:item.cell}))},null,2);const rows=items.map(item=>[item.section,item.field.title,recordFlat(item.cell,item.field,view.fmt)]);if(format==="text")return[title,...rows.map(row=>row[1]+ "\t"+row[2].replace(/\s*\n\s*/g, "; "))].join("\n");
169
+ const quote=value=>{const escaped=gridExportField(String(value),",");return escaped.startsWith('"')?escaped:'"'+escaped+'"'};return[[labels.recordSection,labels.recordField,labels.recordValue],...rows].map(row=>row.map(quote).join(",")).join("\r\n")}
170
+ function recordDownload(view,dialog,format){const text=recordExport(view,dialog,format),record=dialog._cxRecord;const blob=new Blob([format==="csv"?""+text:text],{type:format==="csv"?"text/csv;charset=utf-8":"application/json"});const link=h("a");link.href=URL.createObjectURL(blob);link.download=(view.view.id+"-"+record.id).replace(/[^\w.-]+/g, "_").slice(0, 100) + "." + format;
171
+ link.hidden=true;document.body.appendChild(link);link.click();link.remove();setTimeout(()=>URL.revokeObjectURL(link.href),10000)}
172
+ let recordPrintDispose;async function recordPrint(view,dialog){if(view.destroyed||!dialog.isConnected)return;recordPrintDispose?.();const record=dialog._cxRecord,entry=recordEntry(view,record.id),payload=entry?.state==="ready"?entry.payload:null;const controller=new AbortController(),signal=AbortSignal.any([controller.signal,view.lifetime.signal]);const sheetOwner=Object.create(dialog,{id:{value:dialog.id+"-print"}});const ctx=recordContext(view,record,sheetOwner,{signal,print:true,index:null},payload);const layout=recordLayout(view,recordFields(view)),showEmpty=RECORD_SHOW_EMPTY||!layout.hideEmpty,sheet=h("div","cx-host cx-record-print"),heading=h("h1");let disposed=false;const changed=()=>{if(dialog._cxRecord!==record)done()};const done=()=>{if(disposed)return;disposed=true;document.documentElement.classList.remove("cx-record-printing");sheet.remove();controller.abort();global.removeEventListener("afterprint",done);dialog.removeEventListener("close",done);dialog.removeEventListener("cx-drawer-paint",changed);signal.removeEventListener("abort",done);if(recordPrintDispose===done)recordPrintDispose=null};recordPrintDispose=done;signal.addEventListener("abort",done,{once:true});dialog.addEventListener("close",done,{once:true});dialog.addEventListener("cx-drawer-paint",changed);sheet.setAttribute("data-cx-theme","light");setText(heading,recordTitle(dialog));sheet.appendChild(heading);const subtitle=dialog.querySelector(".cx-drawer-h p");if(subtitle&&!subtitle.hidden){const line=h("p","cx-record-print-sub");setText(line,subtitle.textContent);sheet.appendChild(line)}
173
+ const summary=dialog.querySelector(".cx-record-summary");if(summary&&!summary.hidden)sheet.appendChild(summary.cloneNode(true));for(const tab of layout.tabs){const sections=tab.sections.map(section=>recordSection(ctx,section,{collapsed:new Map()},showEmpty)).filter(Boolean);if(!sections.length)continue;if(layout.tabs.length>1){const name=h("h2");setText(name,tab.label);sheet.appendChild(name)}
174
+ sheet.append(...sections)}
175
+ document.body.appendChild(sheet);const cancelled=new Promise((resolve,reject)=>{const abort=()=>reject(new DOMException("Record print cancelled.","AbortError"));if(signal.aborted)abort();else signal.addEventListener("abort",abort,{once:true})});try{await Promise.race([Promise.all(ctx.pending),cancelled])}
176
+ catch(error){done();if(error.name!=="AbortError")throw error;return}
177
+ if(signal.aborted)return;if(!recordEmit(view,"recordPrint",Object.freeze({id:record.id,element:sheet,dispose:done})))return;if(signal.aborted)return;document.documentElement.classList.add("cx-record-printing");global.addEventListener("afterprint",done);global.print()}
178
+ installed.add(context.RECORD_IMPL)}};(global.CanopyXParts||=[]).push(["record-panel",part])})(typeof window!=="undefined"?window:globalThis);