@evotecit/canopyx 0.3.16 → 0.3.20

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 (150) hide show
  1. package/CanopyX.Html/Assets/canopyx-board.css +50 -0
  2. package/CanopyX.Html/Assets/canopyx-board.js +39 -0
  3. package/CanopyX.Html/Assets/canopyx-buckets.js +15 -0
  4. package/CanopyX.Html/Assets/canopyx-calculations.css +7 -0
  5. package/CanopyX.Html/Assets/canopyx-calculations.js +52 -0
  6. package/CanopyX.Html/Assets/canopyx-calendar-edit.js +3 -3
  7. package/CanopyX.Html/Assets/canopyx-calendar.css +74 -80
  8. package/CanopyX.Html/Assets/canopyx-calendar.js +26 -31
  9. package/CanopyX.Html/Assets/canopyx-cell-range.css +4 -4
  10. package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
  11. package/CanopyX.Html/Assets/canopyx-changes.css +61 -79
  12. package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
  13. package/CanopyX.Html/Assets/canopyx-column-groups.css +5 -1
  14. package/CanopyX.Html/Assets/canopyx-column-groups.js +15 -9
  15. package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
  16. package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
  17. package/CanopyX.Html/Assets/canopyx-data.js +3 -3
  18. package/CanopyX.Html/Assets/canopyx-detail-rows.css +4 -4
  19. package/CanopyX.Html/Assets/canopyx-detail-rows.js +1 -1
  20. package/CanopyX.Html/Assets/canopyx-editing.css +5 -5
  21. package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
  22. package/CanopyX.Html/Assets/canopyx-enhance.js +5 -5
  23. package/CanopyX.Html/Assets/canopyx-export.js +54 -13
  24. package/CanopyX.Html/Assets/canopyx-facets.css +32 -22
  25. package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
  26. package/CanopyX.Html/Assets/canopyx-filter-editor.css +75 -89
  27. package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
  28. package/CanopyX.Html/Assets/canopyx-flow-checks.css +3 -3
  29. package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
  30. package/CanopyX.Html/Assets/canopyx-flow-command.css +3 -3
  31. package/CanopyX.Html/Assets/canopyx-flow-command.js +1 -1
  32. package/CanopyX.Html/Assets/canopyx-flow-dialog.css +4 -4
  33. package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
  34. package/CanopyX.Html/Assets/canopyx-flow-drafts.css +2 -2
  35. package/CanopyX.Html/Assets/canopyx-flow-drafts.js +1 -1
  36. package/CanopyX.Html/Assets/canopyx-flow-entry.css +142 -17
  37. package/CanopyX.Html/Assets/canopyx-flow-entry.js +5 -5
  38. package/CanopyX.Html/Assets/canopyx-flow-host.css +2 -2
  39. package/CanopyX.Html/Assets/canopyx-flow-host.js +1 -1
  40. package/CanopyX.Html/Assets/canopyx-flow-module.mjs +5 -5
  41. package/CanopyX.Html/Assets/canopyx-flow-pick.css +4 -4
  42. package/CanopyX.Html/Assets/canopyx-flow-pick.js +1 -1
  43. package/CanopyX.Html/Assets/canopyx-flow-preview.css +1 -1
  44. package/CanopyX.Html/Assets/canopyx-flow-preview.js +1 -1
  45. package/CanopyX.Html/Assets/canopyx-flow-records.css +2 -2
  46. package/CanopyX.Html/Assets/canopyx-flow-records.js +1 -1
  47. package/CanopyX.Html/Assets/canopyx-flow-tasks.css +4 -4
  48. package/CanopyX.Html/Assets/canopyx-flow-tasks.js +1 -1
  49. package/CanopyX.Html/Assets/canopyx-flow.css +41 -41
  50. package/CanopyX.Html/Assets/canopyx-flow.js +1 -1
  51. package/CanopyX.Html/Assets/canopyx-format-editor.css +9 -9
  52. package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
  53. package/CanopyX.Html/Assets/canopyx-formatting.css +13 -13
  54. package/CanopyX.Html/Assets/canopyx-formatting.js +12 -11
  55. package/CanopyX.Html/Assets/canopyx-forms.css +3 -3
  56. package/CanopyX.Html/Assets/canopyx-forms.js +1 -1
  57. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +220 -155
  58. package/CanopyX.Html/Assets/canopyx-grid-options.css +8 -8
  59. package/CanopyX.Html/Assets/canopyx-grid-options.js +9 -2
  60. package/CanopyX.Html/Assets/canopyx-grid.css +285 -150
  61. package/CanopyX.Html/Assets/canopyx-grid.js +220 -155
  62. package/CanopyX.Html/Assets/canopyx-grouping.css +23 -16
  63. package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
  64. package/CanopyX.Html/Assets/canopyx-highlight.css +10 -10
  65. package/CanopyX.Html/Assets/canopyx-highlight.js +1 -1
  66. package/CanopyX.Html/Assets/canopyx-interactive.css +215 -91
  67. package/CanopyX.Html/Assets/canopyx-interactive.js +47 -52
  68. package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
  69. package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
  70. package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
  71. package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
  72. package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
  73. package/CanopyX.Html/Assets/canopyx-layouts.css +49 -21
  74. package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
  75. package/CanopyX.Html/Assets/canopyx-link.css +3 -3
  76. package/CanopyX.Html/Assets/canopyx-link.js +4 -4
  77. package/CanopyX.Html/Assets/canopyx-links.js +2 -2
  78. package/CanopyX.Html/Assets/canopyx-live.css +3 -5
  79. package/CanopyX.Html/Assets/canopyx-live.js +3 -3
  80. package/CanopyX.Html/Assets/canopyx-matrix.css +32 -39
  81. package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
  82. package/CanopyX.Html/Assets/canopyx-module.mjs +47 -52
  83. package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
  84. package/CanopyX.Html/Assets/canopyx-pager.css +1 -1
  85. package/CanopyX.Html/Assets/canopyx-pager.js +1 -1
  86. package/CanopyX.Html/Assets/canopyx-path.css +45 -0
  87. package/CanopyX.Html/Assets/canopyx-path.js +28 -0
  88. package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
  89. package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
  90. package/CanopyX.Html/Assets/canopyx-plan.css +63 -0
  91. package/CanopyX.Html/Assets/canopyx-plan.js +71 -0
  92. package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
  93. package/CanopyX.Html/Assets/canopyx-record-panel.css +51 -45
  94. package/CanopyX.Html/Assets/canopyx-record-panel.js +30 -22
  95. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +262 -197
  96. package/CanopyX.Html/Assets/canopyx-reporting.css +300 -164
  97. package/CanopyX.Html/Assets/canopyx-reporting.js +262 -197
  98. package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
  99. package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
  100. package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
  101. package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
  102. package/CanopyX.Html/Assets/canopyx-timeline.css +19 -19
  103. package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
  104. package/CanopyX.Html/Assets/canopyx-tree-tools.css +47 -46
  105. package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
  106. package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
  107. package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
  108. package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
  109. package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
  110. package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
  111. package/CanopyX.Html/Assets/canopyx-ui-overlays.js +45 -0
  112. package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
  113. package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
  114. package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
  115. package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
  116. package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
  117. package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
  118. package/CanopyX.Html/Assets/canopyx-values.css +5 -0
  119. package/CanopyX.Html/Assets/canopyx-values.js +13 -0
  120. package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
  121. package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
  122. package/CanopyX.Html/Assets/canopyx.css +212 -85
  123. package/CanopyX.Html/Assets/canopyx.js +38 -26
  124. package/JavaScript/board.d.ts +30 -0
  125. package/JavaScript/changes.d.ts +4 -1
  126. package/JavaScript/column-groups.d.ts +24 -4
  127. package/JavaScript/facets.d.ts +5 -3
  128. package/JavaScript/grid.d.ts +161 -17
  129. package/JavaScript/hosts.d.ts +16 -1
  130. package/JavaScript/index.d.ts +4 -2
  131. package/JavaScript/locales/de.mjs +177 -9
  132. package/JavaScript/locales/es.mjs +177 -9
  133. package/JavaScript/locales/fr.mjs +176 -8
  134. package/JavaScript/locales/it.mjs +176 -8
  135. package/JavaScript/locales/pl.mjs +176 -8
  136. package/JavaScript/matrix.d.ts +4 -1
  137. package/JavaScript/path.d.ts +33 -0
  138. package/JavaScript/pivot.d.ts +135 -0
  139. package/JavaScript/plan.d.ts +23 -0
  140. package/JavaScript/protocol.d.ts +18 -3
  141. package/JavaScript/records.d.ts +4 -0
  142. package/JavaScript/stack.d.ts +28 -0
  143. package/JavaScript/time-slider.d.ts +58 -0
  144. package/JavaScript/ui.d.ts +261 -0
  145. package/JavaScript/view-intents.d.ts +45 -0
  146. package/README.md +76 -187
  147. package/README.nuget.md +63 -87
  148. package/ThirdParty/OfficeIMO/LICENSE +21 -0
  149. package/ThirdParty/OfficeIMO/README.md +13 -0
  150. package/package.json +76 -3
@@ -1,6 +1,9 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"ee95c5cc39223ef4",install(context){if(installed.has(context.TreeGrid.prototype))return;const{TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,exportTimeout,exportFormatsOf,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField,columnNumericTone,columnValueTone,overlayTheme}=context;const EXPORT_IMPL={formatsOf:exportFormatsOf};const GRID_ICONS={search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',filter:'<path d="M4 5h16l-6 7.5V19l-4-2v-4.5z"/>',columns:'<rect x="3.5" y="4.5" width="17" height="15" rx="2"/><path d="M9.5 4.5v15M14.5 4.5v15"/>',views:'<path d="M6 4h12v16l-6-4-6 4z"/>',export:'<path d="M12 4v11M7.5 10.5 12 15l4.5-4.5M5 19h14"/>',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"/>',close:'<path d="M6 6l12 12M18 6 6 18"/>',check:'<path d="m5 12.5 4.5 4.5L19 7.5"/>',chart:'<path d="M4 19h16M7 16V10M12 16V6M17 16v-4"/>',copy:'<rect x="8" y="8" width="11" height="11" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/>',up:'<path d="M12 19V5M6 11l6-6 6 6"/>',down:'<path d="M12 5v14M6 13l6 6 6-6"/>',retry:'<path d="M4 12a8 8 0 1 0 2.4-5.7M4 4v4.5h4.5"/>',previous:'<path d="m14 7-5 5 5 5"/>',next:'<path d="m10 7 5 5-5 5"/>',first:'<path d="m13 7-5 5 5 5M17 7l-5 5 5 5"/>',last:'<path d="m11 7 5 5-5 5M7 7l5 5-5 5"/>'};function gridIcon(name,shapes){return svgIcon(shapes||GRID_ICONS[name]||GRID_ICONS.more)}
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"ef0d06c82135ae2e",requires:["ui-overlays"],install(context){if(installed.has(context.TreeGrid.prototype))return;const{UI_IMPL,UI_TOOLS,TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField,columnNumericTone,columnValueTone,overlayTheme}=context;const EXPORT_IMPL={};function exportTimeout(grid,options){const timeout=options?.timeoutMs??grid.opts.exportTimeoutMs??600000;if(!Number.isInteger(timeout)||timeout<1||timeout>2147483647)throw new Error("CanopyX: invalid export timeout.");return timeout}
2
+ const OFFICE_EXPORT_PART={name:"office-export",label:"Office export writers",parts:{},context:()=>({EXPORT_IMPL})};const officeExportWrite=(capture,context)=>loadPart(OFFICE_EXPORT_PART).then(()=>EXPORT_IMPL.office(capture,context));function officeExportFormats(grid){return[{id:"xlsx",label:grid.labels.gridDownloadXlsx,extension:"xlsx",values:"raw",mime:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",write:officeExportWrite},{id:"pdf",label:grid.labels.gridDownloadPdf,extension:"pdf",values:"raw",mime:"application/pdf",write:officeExportWrite}]}
3
+ EXPORT_IMPL.formatsOf=function(grid){const list=grid.opts.exportFormats??grid.view.exportFormats,known=new Map(EXPORT_FORMATS);if(list!==undefined)for(const format of officeExportFormats(grid))if(!known.has(format.id))known.set(format.id,exportFormat(format));for(const format of grid.plugins.filter(item=>(grid.opts.plugins||[]).some(local=>local.name===item.name))
4
+ .flatMap(item=>item.exportFormats||[]))known.set(format.id,exportFormat(format));if(list===undefined)return[...known.values()];const formats=Array.isArray(list)?list.map(item=>typeof item==="string"?known.get(item):exportFormat(item)).filter(Boolean):null;if(!formats||new Set(formats.map(format=>format.id)).size!==formats.length)throw new Error("CanopyX: invalid exportFormats.");return formats};const GRID_ICONS={search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',filter:'<path d="M4 5h16l-6 7.5V19l-4-2v-4.5z"/>',columns:'<rect x="3.5" y="4.5" width="17" height="15" rx="2"/><path d="M9.5 4.5v15M14.5 4.5v15"/>',views:'<path d="M6 4h12v16l-6-4-6 4z"/>',export:'<path d="M12 4v11M7.5 10.5 12 15l4.5-4.5M5 19h14"/>',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"/>',close:'<path d="M6 6l12 12M18 6 6 18"/>',check:'<path d="m5 12.5 4.5 4.5L19 7.5"/>',chart:'<path d="M4 19h16M7 16V10M12 16V6M17 16v-4"/>',copy:'<rect x="8" y="8" width="11" height="11" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/>',up:'<path d="M12 19V5M6 11l6-6 6 6"/>',down:'<path d="M12 5v14M6 13l6 6 6-6"/>',retry:'<path d="M4 12a8 8 0 1 0 2.4-5.7M4 4v4.5h4.5"/>',previous:'<path d="m14 7-5 5 5 5"/>',next:'<path d="m10 7 5 5-5 5"/>',first:'<path d="m13 7-5 5 5 5M17 7l-5 5 5 5"/>',last:'<path d="m11 7 5 5-5 5M7 7l5 5-5 5"/>'};function gridIcon(name,shapes){return svgIcon(shapes||GRID_ICONS[name]||GRID_ICONS.more)}
2
5
  function gridDecorateButton(button,icon,ghost){button.classList.add("cx-btn");if(ghost)button.classList.add("ghost");if(icon)button.prepend(gridIcon(icon));return button}
3
- function gridFilterCount(query){const count=group=>group?group.filters.length+group.groups.reduce((sum,child)=>sum+count(child),0):0;return(query?.filters?.length||0)+ count(query?.filterGroup)}
6
+ function gridFilterCount(query){const count=group=>group?group.filters.length+group.groups.reduce((sum,child)=>sum+count(child),0):0;return(query?.filters?.length||0)+ count(query?.filterGroup)+(query?.tupleFilters?.length||0)}
4
7
  function gridPriority(value){return["essential","normal","optional"].includes(value)||Number.isInteger(value)&&value>=0&&value<=MAX_PROTOCOL_INTEGER}
5
8
  function gridRank(column){const value=column.priority;return typeof value==="number"?value:value==="optional"?10000:value==="essential"||value===undefined&&column.identity?0:5000}
6
9
  function gridLevel(column){const rank=gridRank(column);return rank<2?0:rank<10000?1:2}
@@ -36,23 +39,24 @@ gridTextual(column)&&gridLevel(column)===1).sort((a,b)=>b.need-a.need)[0];grow(i
36
39
  grow(identity,Infinity);grow(widest,Infinity);return target},fitHide(shown,width,phone,size=column=>this.fitSize(column,1),level=!phone){let total=0,remaining=shown.length;const order=(a,b)=>gridLevel(b)- gridLevel(a)||gridRank(b)- gridRank(a)||shown.indexOf(b)- shown.indexOf(a),identity=phone&&shown.find(column=>column.identity);const hide=(column,pinned)=>!column.fixed&&!column.sized&&!column.alwaysVisible&&(column.pin==="none")!==pinned&&!(phone&&column.identity)&&gridLevel(column)>level;for(const column of this.columns)column.fitHidden=false;if(this.layoutMode&&this.layoutMode!=="fit")return;for(const column of shown)total +=size(column);for(const column of shown.filter(column=>hide(column,false)).sort(order))
37
40
  if(total>width&&remaining>1){column.fitHidden=true;total -=size(column);remaining--}
38
41
  if(identity&&!identity.fixed&&!identity.sized)total +=Math.min(identity.need??identity.width,(identity.indentNeed||0)+ 2*(this.fitCh||88))+(identity.reserve||0)- size(identity);if(identity)for(const column of shown.filter(column=>hide(column,true)).sort(order))
39
- if(total>width){column.fitHidden=true;total -=size(column)}}};function gridButton(text,run){const button=h("button","cx-button");button.type="button";setText(button,text);button.onclick=event=>{button.focus({preventScroll:true});run(event)};return button}
42
+ if(total>width){column.fitHidden=true;total -=size(column)}}};function gridVariant(button,variant){button.dataset.variant=variant;return button}
43
+ function gridButton(text,run){const button=h("button","cx-button");button.type="button";setText(button,text);button.onclick=event=>{button.focus({preventScroll:true});run(event)};return button}
40
44
  let keyboardInput=false;if(typeof document!=="undefined"){document.addEventListener("keydown",()=>{keyboardInput=true},true);document.addEventListener("pointerdown",()=>{keyboardInput=false},true)}
41
45
  const focusDrawerTitle=title=>{if(keyboardInput&&title===document.activeElement&&!title.matches(":focus-visible"))title.blur();title.toggleAttribute("data-cx-pointer-focus",!keyboardInput);if(!keyboardInput)title.addEventListener("blur",()=>title.removeAttribute("data-cx-pointer-focus"),{once:true});title.focus({preventScroll:true,focusVisible:keyboardInput})};function gridInputLabel(text,input){const label=h("label","cx-grid-field");label.appendChild(document.createTextNode(text));label.appendChild(input);return label}
42
46
  function gridOption(value,text){const option=h("option");option.value=value;setText(option,text);return option}
43
- const MENU_EVENT="canopyx:closemenus",announceMenu=source=>document.dispatchEvent(new CustomEvent(MENU_EVENT,{detail:{source}}));const TOOLBAR_PANELS={startMenus(){this.controlFlyouts=[];this.disposeControls=()=>this.controlFlyouts.forEach(flyout=>flyout.dispose());let pressed=null;for(const type of["mouseup","click","keydown","pointercancel"])document.addEventListener(type,()=>{pressed=null},{capture:true,signal:this.lifetime.signal});for(const type of["pointerdown","focusin",MENU_EVENT])document.addEventListener(type,event=>{if(type==="pointerdown")pressed=event.target;const node=type==="focusin"&&pressed?.isConnected&&event.target.contains(pressed)?pressed:event.detail?.source||event.target;if(type!==MENU_EVENT||event.target.contains(this.host))this.closeMenusOutside(node)},{signal:this.lifetime.signal})},closeMenusOutside(node){for(const details of this.toolbar.querySelectorAll(".cx-columns[open]"))if(!details.contains(node))details.open=false;const popover=this.gridPopover;if(popover&&!popover.panel.contains(node)&&!popover.anchor?.contains(node))this.closeGridPopover(false)},closeMenus(){this.closeMenusOutside(document)},controlPanel(title,className,onOpen){const details=h("details","cx-columns "+className),summary=h("summary","cx-btn"),panel=h("div","cx-columns-list cx-grid-panel cx-pop");summary.setAttribute("role","button");if(className!=="cx-grid-filters")summary.classList.add("ghost");setText(summary,title);details.append(summary,panel);this.toolbar.appendChild(details);summary.prepend(gridIcon(className.slice(8).replace("rs","r")));panel.popover="manual";const flyout=watchFlyout(details,panel,()=>details.open);this.controlFlyouts.push(flyout);details.addEventListener("toggle",()=>{if(details.open){announceMenu(details);if(panel.isConnected)panel.showPopover?.();if(onOpen)onOpen(panel);flyout.position()}else{panel.hidePopover?.();for(const inner of panel.querySelectorAll("details[open]"))inner.open=false}});details.addEventListener("keydown",event=>{if(event.key==="Escape"&&details.open){details.open=false;summary.focus();event.preventDefault();event.stopPropagation()}});return{details,panel}},buildSavedViews(){const panel=this.controlPanel(this.labels.gridViews,"cx-grid-views").panel;const choice=this.savedChoice=h("select"),name=h("input");name.type="text";name.maxLength=100;choice.setAttribute("aria-label",this.labels.gridChooseView);panel.appendChild(choice);panel.appendChild(gridInputLabel(this.labels.gridViewName,name));const error=h("p","cx-grid-control-error");error.setAttribute("role","status");const run=action=>{try{Promise.resolve(action()).then(()=>setText(error,""),failure=>setText(error,failure.message))}
44
- catch(failure){setText(error,failure.message)}};panel.appendChild(gridButton(this.labels.gridApply,()=>run(()=>this.applySavedView(choice.value))));panel.appendChild(gridButton(this.labels.gridSaveView,()=>run(()=>this.saveView(name.value))));panel.appendChild(gridButton(this.labels.gridRemoveView,()=>run(()=>this.removeSavedView(choice.value))));panel.appendChild(error);this.syncSavedViews()},syncSavedViews(){if(!this.savedChoice)return;const selected=this.savedChoice.value;this.savedChoice.textContent="";this.savedChoice.appendChild(gridOption("",this.labels.gridChooseView));this.getSavedViews().forEach(name=>this.savedChoice.appendChild(gridOption(name,name)));if(this.savedViews.has(selected))this.savedChoice.value=selected},placeMenus(phone){if(this.overflow)for(const selector of[".cx-grid-views",".cx-grid-export"]){const item=this.toolbar.querySelector(selector);if(!item)continue;item.open=false;if(phone)this.overflow.panel.appendChild(item);else this.toolbar.insertBefore(item,selector===".cx-grid-views"?this.slots?.afterViews||this.spacer:this.overflow.details)}}};const COLUMNS_MENU={moveColumnChoice(column,target,after){column.pin=target.pin;const ids=this.columns.map(item=>item.id).filter(id=>id!==column.id);ids.splice(ids.indexOf(target.id)+ after,0,column.id);this.setColumnOrder(ids)},renderGridColumns(panel){if(!this.columnList){const find=this.columnFind=h("input","cx-grid-column-find"),actions=h("div","cx-grid-column-actions");find.type="search";find.placeholder=this.labels.gridFindColumn;find.setAttribute("aria-label",find.placeholder);find.hidden=this.columns.length<9;find.oninput=()=>this.syncColumnControls();actions.append(gridButton(this.labels.gridShowAllColumns,()=>this.showAllColumns()),gridButton(this.labels.gridResetColumns,()=>this.resetColumns()));panel.replaceChildren(find,this.columnList=h("div"),actions)}
47
+ const MENU_EVENT="canopyx:closemenus",announceMenu=source=>document.dispatchEvent(new CustomEvent(MENU_EVENT,{detail:{source}}));const TOOLBAR_PANELS={startMenus(){this.controlFlyouts=[];this.disposeControls=()=>this.controlFlyouts.forEach(flyout=>flyout.dispose());let pressed=null;for(const type of["mouseup","click","keydown","pointercancel"])document.addEventListener(type,()=>{pressed=null},{capture:true,signal:this.lifetime.signal});for(const type of["pointerdown","focusin",MENU_EVENT])document.addEventListener(type,event=>{if(type==="pointerdown")pressed=event.target;const node=type==="focusin"&&pressed?.isConnected&&event.target.contains(pressed)?pressed:event.detail?.source||event.target;if(type!==MENU_EVENT||event.target.contains(this.host))this.closeMenusOutside(node)},{signal:this.lifetime.signal})},closeMenusOutside(node){const holds=element=>element&&(UI_TOOLS.owns?.(element,node)??element.contains(node));if(this.pendingColumnMenu&&!holds(this.pendingColumnMenu.anchor))this.pendingColumnMenu=null;for(const details of this.toolbar.querySelectorAll(".cx-columns[open]"))if(!holds(details))details.open=false;const popover=this.gridPopover;if(popover&&!holds(popover.panel)&&!holds(popover.anchor))this.closeGridPopover(false);const cellMenu=this.cellMenuPanel;if(cellMenu&&!holds(cellMenu)&&!holds(this.cellMenuHit?.cell))this.cellMenuBinding?.close("menus",false,true)},closeMenus(){this.closeMenusOutside(document)},controlPanel(title,className,onOpen){const details=h("details","cx-columns "+className),summary=h("summary","cx-btn"),panel=h("div","cx-columns-list cx-grid-panel cx-pop");summary.setAttribute("role","button");panel.setAttribute("role","dialog");panel.setAttribute("aria-label",title);if(className!=="cx-grid-filters")summary.classList.add("ghost");setText(summary,title);details.append(summary,panel);this.toolbar.appendChild(details);summary.prepend(gridIcon(className.slice(8).replace("rs","r")));panel.popover="manual";const flyout=watchFlyout(details,panel,()=>details.open);this.controlFlyouts.push(flyout);details.addEventListener("toggle",()=>{if(details.open){announceMenu(details);if(onOpen)onOpen(panel);flyout.open()}else{flyout.close();for(const inner of panel.querySelectorAll("details[open]"))inner.open=false}});details.addEventListener("keydown",event=>{if(event.key==="Escape"&&details.open){details.open=false;flyout.close();summary.focus();event.preventDefault();event.stopPropagation()}});return{details,panel}},buildSavedViews(){const panel=this.controlPanel(this.labels.gridViews,"cx-grid-views").panel;const choice=this.savedChoice=h("select"),name=h("input");name.type="text";name.maxLength=100;choice.setAttribute("aria-label",this.labels.gridChooseView);panel.appendChild(choice);panel.appendChild(gridInputLabel(this.labels.gridViewName,name));const error=h("p","cx-grid-control-error");error.setAttribute("role","status");const run=action=>{try{Promise.resolve(action()).then(()=>setText(error,""),failure=>setText(error,failure.message))}
48
+ catch(failure){setText(error,failure.message)}};panel.appendChild(gridButton(this.labels.gridApply,()=>run(()=>this.applySavedView(choice.value))));panel.appendChild(gridButton(this.labels.gridSaveView,()=>run(()=>this.saveView(name.value))));panel.appendChild(gridButton(this.labels.gridRemoveView,()=>run(()=>this.removeSavedView(choice.value))));panel.appendChild(error);this.syncSavedViews()},syncSavedViews(){if(!this.savedChoice)return;const selected=this.savedChoice.value;this.savedChoice.textContent="";this.savedChoice.appendChild(gridOption("",this.labels.gridChooseView));this.getSavedViews().forEach(name=>this.savedChoice.appendChild(gridOption(name,name)));if(this.savedViews.has(selected))this.savedChoice.value=selected},placeMenus(phone){if(this.overflow)for(const selector of[".cx-grid-views",".cx-grid-export"]){const item=this.toolbar.querySelector(selector);if(!item)continue;item.open=false;if(phone)this.overflow.panel.appendChild(item);else this.toolbar.insertBefore(item,selector===".cx-grid-views"?this.slots?.afterViews||this.spacer:this.overflow.details)}}};const COLUMNS_MENU={moveColumnChoice(column,target,after){column.pin=target.pin;const ids=this.columns.map(item=>item.id).filter(id=>id!==column.id);ids.splice(ids.indexOf(target.id)+ after,0,column.id);this.setColumnOrder(ids)},renderGridColumns(panel){if(!this.columnList){const find=this.columnFind=h("input","cx-grid-column-find"),actions=h("div","cx-grid-column-actions");find.type="search";find.placeholder=this.labels.gridFindColumn;find.setAttribute("aria-label",find.placeholder);find.hidden=this.columns.length<9;find.oninput=()=>this.syncColumnControls();actions.append(gridButton(this.labels.gridShowAllColumns,()=>this.showAllColumns()),gridButton(this.labels.gridResetColumns,()=>this.resetColumns()));if(this.view.calculatedColumnsEditable)actions.append(gridButton(this.labels.gridCalculationAdd,event=>this.openCalculatedColumn(event.currentTarget)));panel.replaceChildren(find,this.columnList=h("div"),actions)}
45
49
  this.syncColumnControls()},syncColumnControls(){const list=this.columnList,active=document.activeElement,query=foldText(this.columnFind?.value.trim()||"");if(!list)return;const focus=list.contains(active)&&active.closest(".cx-grid-column-choice").dataset.cxColumn,held=focus&&active.matches(".cx-grid-column-handle"),last=this.columns.filter(item=>!item.hidden).length<2;list.textContent="";for(const column of this.columns){const row=h("div","cx-grid-column-choice"),label=h("label"),input=h("input"),name=h("span","cx-grid-column-name"),handle=h("button","cx-grid-column-handle"),note=column.fitHidden||column.responsiveHidden?this.labels.gridResponsiveHidden:column.pin==="left"?this.labels.gridPinnedLeft:column.pin==="right"?this.labels.gridPinnedRight:"";input.type="checkbox";input.checked=!column.hidden;input.disabled=!column.hidden&&last;input.onchange=()=>{input.focus({preventScroll:true});this.setColumnVisible(column.id,input.checked)};setText(name,name.title=column.title);handle.type="button";setText(handle,"⋮⋮");handle.setAttribute("aria-label",fill(this.labels.gridReorderColumn,{column:column.title}));label.append(input,name);row.append(handle,label);row.hidden=!!query&&!foldText(column.title).includes(query);if(note){const span=h("span","cx-grid-column-note");setText(span,note);row.append(span)}
46
50
  if(this.openColumnMenu&&this.tools.columnMenus!==false){const menu=gridDecorateButton(gridButton("",()=>this.openColumnMenu(column.id,menu)),"more",true);menu.classList.add("cx-grid-column-options","icon");menu.setAttribute("aria-label",fill(this.labels.gridColumnMenu,{column:column.title}));menu.setAttribute("aria-haspopup","menu");row.append(menu)}
47
51
  row.onkeydown=event=>{const target=event.altKey&&this.columns[this.columns.indexOf(column)+(event.key==="ArrowUp"?-1:event.key==="ArrowDown"?1:NaN)];if(target){event.preventDefault();event.stopPropagation();this.moveColumnChoice(column,target,event.key==="ArrowDown")}};handle.onpointerdown=event=>{if(event.button)return;event.preventDefault();handle.focus();handle.setPointerCapture(event.pointerId);let target,after;const clear=()=>{for(const item of list.children)item.classList.remove("cx-drop-before","cx-drop-after")};handle.onpointermove=move=>{clear();const over=document.elementFromPoint(move.clientX,move.clientY)?.closest(".cx-grid-column-choice");target=over!==row&&list.contains(over)&&this.columns[[...list.children].indexOf(over)];if(target){const box=over.getBoundingClientRect();after=move.clientY>box.top+box.height / 2; over.classList.add(after ? "cx-drop-after" : "cx-drop-before"); }
48
52
  };handle.onpointerup=handle.onpointercancel=up=>{handle.onpointermove=handle.onpointerup=handle.onpointercancel=null;clear();if(up.type==="pointerup"&&target)this.moveColumnChoice(column,target,after)}};row.dataset.cxColumn=column.id;list.appendChild(row);if(focus===column.id)(held?handle:input).focus({preventScroll:true})}}};function gridOperationActive(grid,signal){if(grid.destroyed||signal?.aborted)throw new DOMException("Grid cancelled.","AbortError")}
49
- const exportPartReady=()=>typeof loadExportPart==="function"?loadExportPart():Promise.resolve();function exportAs(grid,format,options={}){const{onProgress,timeoutMs,download,...capture}=options;let provider,resolutionError;try{provider=EXPORT_IMPL.formatsOf(grid).find(item=>item.id===format)}
53
+ const exportPartReady=()=>typeof loadExportPart==="function"?loadExportPart():Promise.resolve();function exportAs(grid,format,options={}){const{onProgress,onDiagnostic,includeMetadata,timeoutMs,download,...capture}=options;let provider,resolutionError;try{provider=EXPORT_IMPL.formatsOf(grid).find(item=>item.id===format)}
50
54
  catch(error){resolutionError=error}
51
- const prepared=grid.calIcsFormatWriter&&provider?.write===grid.calIcsFormatWriter?grid.calPrepareIcsExport(capture):grid.prepareExport(capture);return exportPartReady().then(()=>{if(resolutionError)throw resolutionError;return EXPORT_IMPL.run(grid,format,options,prepared,provider)})}
55
+ if(capture.values===undefined&&provider?.values!==undefined)capture.values=provider.values;const prepared=grid.calIcsFormatWriter&&provider?.write===grid.calIcsFormatWriter?grid.calPrepareIcsExport(capture):grid.prepareExport(capture);return exportPartReady().then(()=>{if(resolutionError)throw resolutionError;return EXPORT_IMPL.run(grid,format,options,prepared,provider)})}
52
56
  Object.assign(TreeGrid.prototype,TOOLBAR_PANELS,COLUMNS_MENU,{installTools(){this.checkTreeLayout();const bar=this.toolbar,tools=this.tools,labels=this.labels;this.host.classList.add("cx-chrome","cx-tree-tools");this.exportScopes=[["visible","gridVisibleRows"],["selected","gridSelectedRows"],["all","gridAllRows"]];this.toolbar.querySelector(".cx-search")?.prepend(gridIcon("search"));this.startMenus();this.lifetime.signal.addEventListener("abort",()=>{this.disposeControls();this.host.classList.remove("cx-chrome","cx-tree-tools","cx-phone")},{once:true});if(tools.columns!==false&&this.columns.length>1)this.controlPanel(labels.columns,"cx-grid-columns",panel=>this.renderGridColumns(panel));for(const item of pluginItems(this,"toolbarItems"))bar.appendChild(this.treeAction(item));this.prepareSavedViews();if(tools.views!==false&&this.stateKey()){this.buildSavedViews();bar.querySelector(".cx-grid-views .cx-grid-panel").appendChild(gridButton(labels.gridResetView,()=>this.resetView().catch(()=>{})))}
53
57
  bar.appendChild(this.spacer=h("span","cx-spacer"));if(tools.export!==false)this.exportControl=this.controlPanel(labels.gridExport,"cx-grid-export",panel=>this.renderGridExport(panel));if(tools.more!==false)this.buildMoreMenu();if(bar.childElementCount===1)bar.replaceChildren();this.syncToolbar();this.startFit()},buildMoreMenu(){const overflow=this.overflow=this.controlPanel(this.labels.gridMore,"cx-grid-overflow"),summary=overflow.details.firstChild;summary.replaceChildren(gridIcon("more"));summary.classList.add("icon");summary.setAttribute("aria-label",this.labels.gridMore);for(const action of[...this.opts.actions||[],...pluginItems(this,"menuItems")])overflow.panel.appendChild(this.treeAction(action));if(this.columns.length>1)overflow.panel.appendChild(Object.assign(gridButton(this.labels.gridDetails,()=>
54
58
  this.openDetails((this.focused||this.rows.find(w=>this.selected.has(w)))?.key).catch(error=>this.emit("error",{error}))),{className:"cx-button cx-grid-details"}));overflow.panel.appendChild(Object.assign(gridButton(this.labels.gridPrint,()=>global.print()),{className:"cx-button cx-grid-print"}))},treeSelection(){return Array.from(this.selected,w=>w.h)},treeAction(action){if(!action||typeof action.label!=="string"||typeof action.run!=="function")throw new Error("CanopyX: actions need a label and handler.");return gridButton(action.label,()=>Promise.resolve().then(()=>
55
- action.run({nodes:this.treeSelection(),signal:this.dataLifetime.signal,api:this.host.canopyx})).catch(error=>this.emit("error",{error})))},closeMenusOutside(node){TOOLBAR_PANELS.closeMenusOutside.call(this,node);const panel=this.interactionPanel;if(panel?.getAttribute("role")==="menu"&&!panel.contains(node))this.closeInteractionPanel(false)},renderGridColumns(panel){COLUMNS_MENU.renderGridColumns.call(this,panel);this.columnList.setAttribute("role","group");this.columnList.setAttribute("aria-label",this.labels.visibleColumns)},syncColumnControls(){COLUMNS_MENU.syncColumnControls.call(this);const row=this.columnList?.firstChild;if(row){row.querySelector(".cx-grid-column-handle").hidden=true;row.querySelector("input").disabled=true}},syncPhone(){const phone=this.host.clientWidth<=640;if(phone===this.phone)return;if(this.hiddenFieldCount())this.version++;this.phone=phone;this.host.classList.toggle("cx-phone",phone);this.placeMenus(phone)}});const OPEN_PANEL=TreeGrid.prototype.openInteractionPanel;if(OPEN_PANEL)TreeGrid.prototype.openInteractionPanel=function(...args){const panel=OPEN_PANEL.apply(this,args);if(panel?.getAttribute("role")==="menu")announceMenu(panel);return panel};const TREE_ACTIVATION={activate:TreeGrid.prototype.activate,onDblClick:TreeGrid.prototype.onDblClick};Object.assign(TreeGrid.prototype,{rowActivated(w,keyboard){const callback=this.opts.onRowActivate;let go=this.host.dispatchEvent(new CustomEvent("canopyx:rowActivate",{detail:{id:w.key,node:w.h,keyboard},bubbles:true,cancelable:true}));if(typeof callback==="function"){try{go=callback(w.h,{keyboard})!==false&&go}catch(error){global.console?.error(error)}}
59
+ action.run({nodes:this.treeSelection(),signal:this.dataLifetime.signal,api:this.host.canopyx})).catch(error=>this.emit("error",{error})))},closeMenusOutside(node){TOOLBAR_PANELS.closeMenusOutside.call(this,node);const panel=this.interactionPanel;if(panel?.getAttribute("role")==="menu"&&!panel.contains(node)&&!this.rendered.get(this.panelNode)?.contains(node))this.closeInteractionPanel(false)},renderGridColumns(panel){COLUMNS_MENU.renderGridColumns.call(this,panel);this.columnList.setAttribute("role","group");this.columnList.setAttribute("aria-label",this.labels.visibleColumns)},syncColumnControls(){COLUMNS_MENU.syncColumnControls.call(this);const row=this.columnList?.firstChild;if(row){row.querySelector(".cx-grid-column-handle").hidden=true;row.querySelector("input").disabled=true}},syncPhone(){const phone=this.host.clientWidth<=640;if(phone===this.phone)return;if(this.hiddenFieldCount())this.version++;this.phone=phone;this.host.classList.toggle("cx-phone",phone);this.placeMenus(phone)}});const OPEN_PANEL=TreeGrid.prototype.openInteractionPanel;if(OPEN_PANEL)TreeGrid.prototype.openInteractionPanel=function(...args){const panel=OPEN_PANEL.apply(this,args);if(panel?.getAttribute("role")==="menu")announceMenu(panel);return panel};const TREE_ACTIVATION={activate:TreeGrid.prototype.activate,onDblClick:TreeGrid.prototype.onDblClick};Object.assign(TreeGrid.prototype,{rowActivated(w,keyboard){const callback=this.opts.onRowActivate;let go=this.host.dispatchEvent(new CustomEvent("canopyx:rowActivate",{detail:{id:w.key,node:w.h,keyboard},bubbles:true,cancelable:true}));if(typeof callback==="function"){try{go=callback(w.h,{keyboard})!==false&&go}catch(error){global.console?.error(error)}}
56
60
  return go},activate(w,enter){if(!enter||w.status||this.rowActivated(w,true))TREE_ACTIVATION.activate.call(this,w,enter)},onDblClick(event){const w=this.rowFromEvent(event);if(!w||w.status||hostControl(event.target)||event.target.closest(".cx-exp")||this.rowActivated(w,false))TREE_ACTIVATION.onDblClick.call(this,event)}});const TREE_FIT={};for(const name of["applyWidths","visibleColumns","setColumnWidth","startResize","buildHeader","render","getState","readState","applyStatePresentation"])
57
61
  TREE_FIT[name]=TreeGrid.prototype[name];const TREE_FIT_ROWS=2000;Object.assign(TreeGrid.prototype,COLUMN_FIT,{checkTreeLayout(){for(const[index,column]of this.view.columns.entries()){if(column.priority!==undefined&&!gridPriority(column.priority)||column.flex!==undefined&&!(typeof column.flex==="number"&&column.flex>=0&&column.flex<=100)||
58
62
  [column.fixed,column.alwaysVisible,column.autoWidth].some(value=>value!==undefined&&typeof value!=="boolean")||
@@ -87,10 +91,9 @@ cols.forEach((column,i)=>{const index=this.columns.indexOf(column);const value=t
87
91
  td.appendChild(content.cloneNode(true))}finally{disposeHostSlot(slot)}})});return table}});const TREE_DETAILS={paintNodeRow:TreeGrid.prototype.paintNodeRow,active:null};Object.assign(TreeGrid.prototype,{focusRing:focusDrawerTitle,hiddenFieldCount(){return this.columns.filter(column=>column.hidden||column.fitHidden).length},paintNodeRow(rowEl,w){TREE_DETAILS.paintNodeRow.call(this,rowEl,w);const slot=rowEl._cells[0],count=this.phone&&this.fitReady&&this.hiddenFieldCount();let button=slot.hiddenFields;if(!count){button?.remove();slot.hiddenFields=null;return}
88
92
  if(!button){button=slot.hiddenFields=gridButton("",()=>this.openDetails(button.dataset.cxRecord).catch(error=>this.emit("error",{error})));button.classList.add("cx-hidden-fields");button.tabIndex=-1;button.addEventListener("click",event=>event.stopPropagation())}
89
93
  if(button.parentNode!==slot.cell)slot.cell.appendChild(button);button.dataset.cxRecord=w.h.id;button.setAttribute("aria-label",this.labels.gridDetails);setText(button,"+"+count)},async openDetails(id,options){const node=this.keyMap.get(id)?.h;if(node&&this.recordNeeded(node))await this.requirePart("record-panel");return this.showDetails(id,options)},showDetails(id,options={}){const rows=this.rows.filter(w=>!w.status&&!w.h.detail),returnFocus=options.returnFocus||document.activeElement,labels=this.labels,owner=this.dataLifetime;let index=rows.findIndex(w=>w.key===id);const loose=index<0?options.node||this.keyMap.get(id)?.h:null;if(index<0&&!loose||this.destroyed)throw new Error("CanopyX: open the details of a loaded node.");if(typeof this.opts.onDetails==="function"){const node=JSON.parse(JSON.stringify(loose||rows[index].h)),controller=new AbortController();owner.signal.addEventListener("abort",()=>controller.abort(),{once:true});return Promise.resolve(this.opts.onDetails({node,signal:controller.signal,returnFocus}))}
90
- if(TREE_DETAILS.active){TREE_DETAILS.active._replaced=true;TREE_DETAILS.active.close();TREE_DETAILS.active.remove()}
91
- const dialog=TREE_DETAILS.active=this.recordDrawer=h("dialog","cx-host cx-tree-tools cx-drawer"),head=h("div","cx-drawer-h"),title=h("h4"),body=h("div","cx-drawer-body");dialog._returnFocus=returnFocus;overlayTheme(this.host,dialog);title.id=this.id+"-record-title";title.tabIndex=-1;title.setAttribute("aria-level","2");dialog.setAttribute("aria-labelledby",title.id);const button=(icon,label,run)=>{const item=gridDecorateButton(gridButton("",run),icon,true);item.classList.add("icon");item.setAttribute("aria-label",labels[label]);return item};const step=position=>{paint(position);focusDrawerTitle(title)};const previous=button("up","gridPreviousRecord",()=>step(index-1)),next=button("down","gridNextRecord",()=>step(index+1));head.append(h("div"),previous,next,button("close","gridCloseRecord",()=>dialog.close()));head.firstChild.appendChild(title);dialog.append(head,body);let shown=loose,paints=null;const paint=position=>{if(!loose&&(position<0||position>=rows.length))return;if(!loose){index=position;shown=rows[index].h}
92
- const node=shown;paints?.abort();paints=new AbortController();setText(title,node.label);dialog._cxRecord=node;dialog.setAttribute("data-cx-record",node.id);dialog.setAttribute("data-cx-view",this.view.id);previous.disabled=!!loose||!index;next.disabled=!!loose||index===rows.length-1;this.paintDrawerBody(node,body,dialog,{index:loose?null:index,signal:paints.signal});dialog.dispatchEvent(new CustomEvent("cx-drawer-paint",{detail:{id:node.id,index:loose?null:index}}))};dialog._cxPaint=node=>{shown=node;paint(index)};dialog.addEventListener("keydown",event=>{if(event.defaultPrevented)return;if(event.key==="Escape"){event.preventDefault();dialog.close()}
93
- else if((event.key==="ArrowUp"||event.key==="ArrowDown")&&!event.target.matches("input,textarea,select,[role=tab]")&&!event.target.closest(".cx-data-grid,.cx-record-nested")){event.preventDefault();step(index +(event.key==="ArrowUp"?-1:1))}});const close=()=>dialog.close();owner.signal.addEventListener("abort",close,{once:true});dialog.addEventListener("close",()=>{owner.signal.removeEventListener("abort",close);paints?.abort();dialog.remove();if(TREE_DETAILS.active===dialog)TREE_DETAILS.active=null;if(this.recordDrawer!==dialog||this.destroyed)return;this.recordDrawer=null;if(TREE_DETAILS.active||dialog._replaced)return;const key=shown.id,row=this.rows.find(w=>w.key===key);if(returnFocus?.isConnected&&(!returnFocus.dataset.cxRecord||returnFocus.dataset.cxRecord===id))returnFocus.focus({preventScroll:true});else if(row)this.setFocus(row,true);else this.grid.focus({preventScroll:true})},{once:true});RECORD_IMPL.decorate?.(this,dialog,{head,identity:head.firstChild,title,body,options});document.body.appendChild(dialog);const phone=this.host.clientWidth<=640;dialog.classList.toggle("cx-phone",phone);if(phone)dialog.showModal();else dialog.show();paint(index);focusDrawerTitle(title);return dialog},paintDrawerBody(node,body,dialog,context){if(RECORD_IMPL.paint&&this.recordNeeded(node))return RECORD_IMPL.paint(this,node,body,dialog,context);const sections=new Map();body.replaceChildren();this.columns.forEach((column,position)=>{if(!position||column.drawer===false)return;const name=column.section||this.labels.gridDetailsSection;if(!sections.has(name)){const heading=h("div","cx-drawer-s"),list=h("dl","cx-dl");setText(heading,name);sections.set(name,list);body.append(heading,list)}
94
+ if(TREE_DETAILS.active){TREE_DETAILS.active._replaced=true;TREE_DETAILS.active._cxOverlay.close("replace",false,true);TREE_DETAILS.active.remove()}
95
+ const dialog=TREE_DETAILS.active=this.recordDrawer=h("dialog","cx-host cx-tree-tools cx-drawer"),head=h("div","cx-drawer-h"),title=h("h4"),body=h("div","cx-drawer-body");dialog._returnFocus=returnFocus;const restoreTheme=UI_TOOLS.theme(this.host,dialog);dialog.dataset.hfxPart="drawer";dialog.dataset.side="end";head.dataset.hfxPart="header";title.dataset.hfxPart="title";body.dataset.hfxPart="body";title.id=this.id+"-record-title";title.tabIndex=-1;title.setAttribute("aria-level","2");dialog.setAttribute("aria-labelledby",title.id);const button=(icon,label,run)=>{const item=gridDecorateButton(gridButton("",run),icon,true);item.classList.add("icon");item.setAttribute("aria-label",labels[label]);return item};const step=position=>{paint(position);focusDrawerTitle(title)};const previous=button("up","gridPreviousRecord",()=>step(index-1)),next=button("down","gridNextRecord",()=>step(index+1));head.append(h("div"),previous,next,button("close","gridCloseRecord",()=>dialog._cxOverlay.close()));head.firstChild.appendChild(title);dialog.append(head,body);let shown=loose,paints=null;const paint=position=>{if(!loose&&(position<0||position>=rows.length))return;if(!loose){index=position;shown=rows[index].h}
96
+ const node=shown;paints?.abort();paints=new AbortController();setText(title,node.label);dialog._cxRecord=node;dialog.setAttribute("data-cx-record",node.id);dialog.setAttribute("data-cx-view",this.view.id);previous.disabled=!!loose||!index;next.disabled=!!loose||index===rows.length-1;this.paintDrawerBody(node,body,dialog,{index:loose?null:index,signal:paints.signal});dialog.dispatchEvent(new CustomEvent("cx-drawer-paint",{detail:{id:node.id,index:loose?null:index}}))};dialog._cxPaint=node=>{shown=node;paint(index)};dialog.addEventListener("keydown",event=>{if(event.defaultPrevented)return;if((event.key==="ArrowUp"||event.key==="ArrowDown")&&!event.target.matches("input,textarea,select,[contenteditable],[role=tab]")&&!event.target.closest(".cx-data-grid,.cx-record-nested")){event.preventDefault();step(index +(event.key==="ArrowUp"?-1:1))}});const close=()=>dialog._cxOverlay.close("data",false,true);const lifetime=new AbortController();owner.signal.addEventListener("abort",close,{once:true});dialog.addEventListener("close",()=>{lifetime.abort();owner.signal.removeEventListener("abort",close);paints?.abort();dialog.remove();if(TREE_DETAILS.active===dialog)TREE_DETAILS.active=null;if(this.recordDrawer!==dialog||this.destroyed)return;this.recordDrawer=null;if(TREE_DETAILS.active||dialog._replaced||dialog._cxHidden)return;const key=shown.id,row=this.rows.find(w=>w.key===key);if(returnFocus?.isConnected&&(!returnFocus.dataset.cxRecord||returnFocus.dataset.cxRecord===id))returnFocus.focus({preventScroll:true});else if(row)this.setFocus(row,true);else this.grid.focus({preventScroll:true})},{once:true});RECORD_IMPL.decorate?.(this,dialog,{head,identity:head.firstChild,title,body,options});document.body.appendChild(dialog);const modal=(this.opts.recordDrawerModal??this.view?.recordDrawerModal)===true;const overlay=dialog._cxOverlay=UI_IMPL.drawer(dialog,{host:this.host,container:this.host,focus:false,dismissible:modal,modal,closeWhenHidden:true},lifetime.signal);lifetime.signal.addEventListener("abort",restoreTheme,{once:true});paint(index);if(overlay.open())focusDrawerTitle(title);return dialog},paintDrawerBody(node,body,dialog,context){if(RECORD_IMPL.paint&&this.recordNeeded(node))return RECORD_IMPL.paint(this,node,body,dialog,context);const sections=new Map();body.replaceChildren();this.columns.forEach((column,position)=>{if(!position||column.drawer===false)return;const name=column.section||this.labels.gridDetailsSection;if(!sections.has(name)){const heading=h("div","cx-drawer-s"),list=h("dl","cx-dl");setText(heading,name);sections.set(name,list);body.append(heading,list)}
94
97
  const term=h("dt"),value=h("dd");setText(term,column.title);term.setAttribute("data-cx-field",column.id);value.setAttribute("data-cx-field",column.id);this.paintDrawerValue(column,node,value,position,context);sections.get(name).append(term,value)})},paintDrawerValue(column,node,value,position,context){const cell=this.cellOf(node,column,position),object=isCellObject(cell);if(typeof column.render==="function"){try{if(column.render(node,value,{column:column.id,level:1,expanded:false,index:position,signal:context.signal,onDispose:cleanup=>{if(context.signal.aborted)cleanup();else context.signal.addEventListener("abort",cleanup,{once:true})}})===true)return}
95
98
  catch(error){this.emit("error",{error})}}
96
99
  const text=cellText(cell,column,this.fmt),blank=object&&cell.value==null&&cell.text==="",span=h("span");applyTone(span,"cx-drawer-text" +(text||blank?"":" p-missing"),toneOf(columnValueTone(column,cell)||(object?cell.tone:null)));setText(span,text||blank?text:"—");if(object&&cell.title)span.title=cell.title;value.appendChild(span);const rule=columnNumericTone(column,cellValue(cell));if(rule){span.title=rule.label;const label=h("span","p-sub");setText(label,rule.label);value.appendChild(label)}
@@ -0,0 +1,41 @@
1
+ @layer hfx.components{
2
+ .cx-menu{
3
+ position:fixed;inset:auto;margin:var(--hfx-space-1-5,6px);padding:var(--hfx-space-1,0.25rem);
4
+ min-inline-size:min(var(--cx-ui-popup-min),calc(var(--cx-ui-viewport-inline) - var(--hfx-space-4,1rem)));
5
+ max-inline-size:min(var(--cx-ui-menu-max),calc(var(--cx-ui-viewport-inline) - var(--hfx-space-4,1rem)));
6
+ max-block-size:calc(var(--cx-ui-viewport-block) - var(--hfx-space-4,1rem));overflow:auto;
7
+ border:var(--hfx-border-width,1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));
8
+ background:var(--hfx-color-surface-raised,light-dark(#ffffff,#1e2126));color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));
9
+ font-family:var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);font-size:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem));z-index:var(--hfx-z-popover,1000);
10
+ }
11
+ .cx-menu[hidden]{display:none!important;}
12
+ .cx-menu-item{
13
+ display:flex;align-items:center;inline-size:100%;min-block-size:var(--hfx-menu-item-height,calc(32px - var(--cx-compact,0) * 4px));
14
+ padding:0 var(--hfx-space-2,0.5rem);gap:var(--hfx-space-2,0.5rem);border:0;
15
+ border-radius:calc(var(--hfx-radius-overlay,var(--hfx-radius-lg,10px)) - var(--hfx-space-1,0.25rem));
16
+ background:transparent;color:inherit;font:inherit;text-align:start;cursor:pointer;
17
+ }
18
+ .cx-menu-item:is(:hover,:focus){background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));}
19
+ .cx-menu-item:active{background:var(--hfx-color-active,light-dark(#ebebec,#2e3034));}
20
+ .cx-menu-item:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:calc(-1 * var(--hfx-focus-width,2px));}
21
+ .cx-menu-label{flex:1;min-inline-size:0;overflow-wrap:anywhere;}
22
+ .cx-menu-icon{display:inline-flex;align-items:center;justify-content:center;flex:none;inline-size:var(--hfx-icon-md,16px);block-size:var(--hfx-icon-md,16px);color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));}
23
+ .cx-menu-icon > :is(svg,img){inline-size:100%;block-size:100%;}
24
+ .cx-menu-item[aria-checked="true"] .cx-menu-icon{color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));}
25
+ .cx-menu-item[aria-checked="true"] .cx-menu-icon > *{display:none;}
26
+ .cx-menu-item[aria-checked="true"] .cx-menu-icon{font-size:0;}
27
+ .cx-menu-item[aria-checked="true"] .cx-menu-icon::before{content:"✓" / "";font-size:var(--hfx-icon-md,16px);}
28
+ .cx-menu-chevron{flex:none;inline-size:var(--hfx-icon-sm,14px);color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));text-align:center;}
29
+ .cx-menu:dir(rtl) .cx-menu-chevron{transform:rotate(180deg);}
30
+ .cx-menu-item[data-danger="true"],.cx-menu-item[data-danger="true"] .cx-menu-icon{color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));}
31
+ .cx-menu-item[data-danger="true"]:is(:hover,:focus){background:var(--hfx-color-status-bad-bg,light-dark(#f9e4e4,#3c272a));}
32
+ .cx-menu-item[aria-disabled="true"],.cx-menu-item[aria-disabled="true"] .cx-menu-icon{color:var(--hfx-color-text-disabled,light-dark(#a3a8b0,#5a5f68));cursor:default;}
33
+ .cx-menu-item[aria-disabled="true"]:is(:hover,:focus,:active){background:transparent;}
34
+ .cx-menu-item kbd{flex:none;margin-inline-start:auto;padding:0 var(--hfx-space-1,0.25rem);border:var(--hfx-border-width,1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-family:var(--hfx-font-mono,"Cascadia Mono","Cascadia Code",Consolas,"SFMono-Regular",Menlo,monospace);font-size:var(--hfx-type-caption-size,0.75rem);line-height:var(--hfx-type-caption-line,1.35);}
35
+ .cx-menu-badge{flex:none;min-block-size:var(--hfx-badge-height,20px);padding:0 var(--hfx-space-1,0.25rem);border-radius:var(--hfx-radius-badge,var(--hfx-radius-sm,4px));background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));font-size:var(--hfx-type-caption-size,0.75rem);line-height:var(--hfx-type-caption-line,1.35);}
36
+ .cx-menu-group-label{padding:var(--hfx-space-1-5,6px) var(--hfx-space-2,0.5rem) var(--hfx-space-1,0.25rem);color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-size:var(--hfx-type-caption-size,0.75rem);font-weight:var(--hfx-weight-semibold,600);text-transform:uppercase;}
37
+ .cx-menu-separator{margin:var(--hfx-space-1,0.25rem) calc(-1 * var(--hfx-space-1,0.25rem));border-block-start:var(--hfx-border-width,1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
38
+ .cx-context-sheet > .cx-menu{position:static;margin:0;min-inline-size:0;max-inline-size:none;max-block-size:var(--cx-ui-sheet-max);inline-size:100%;border:0;box-shadow:none;}
39
+ @media print{.cx-menu,.cx-context-sheet{display:none!important;}}
40
+ @media (forced-colors:active){.cx-menu-item:focus{outline:var(--hfx-focus-width,2px) solid;outline-offset:calc(-1 * var(--hfx-focus-width,2px));}}
41
+ }
@@ -0,0 +1,64 @@
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"352b1ee391133ff0",requires:["ui-overlays"],install(context){if(installed.has(context.UI_IMPL))return;const{UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml}=context;let uiMenuIdentity=0;const uiMenuItemSelector='[role="menuitem"],[role="menuitemcheckbox"],[role="menuitemradio"]';const uiMenuModels=new WeakMap();UI_TOOLS.menuItems=(menu,items,options={})=>{menu.replaceChildren();const render=(container,entries)=>{for(const item of entries||[]){const kind=String(item.kind||item.type||'').toLowerCase();if(kind==='separator'||kind==='grouplabel'){const decoration=h('div',kind==='separator'?'cx-menu-separator':'cx-menu-group-label');decoration.setAttribute('role',kind==='separator'?'separator':'presentation');if(kind!=='separator')setText(decoration,item.label);container.append(decoration);continue}
2
+ const button=h('button','cx-menu-item');button.type='button';button.tabIndex=-1;button.id='cx-ui-menu-item-' + ++uiMenuIdentity;button.dataset.itemId=String(item.id);button.dataset.hfxPart='menu-item';const role=kind==='radio'||item.role==='menuitemradio'?'menuitemradio':
3
+ kind==='checkbox'||item.checked!=null?'menuitemcheckbox':'menuitem';button.setAttribute('role',role);if(role!=='menuitem')button.setAttribute('aria-checked',String(!!item.checked));if(item.disabled)button.setAttribute('aria-disabled','true');button.dataset.state=item.disabled?'disabled':item.checked?'selected':'';button.dataset.danger=String(!!item.danger);if(item.group!=null)button.dataset.radioGroup=String(item.group);const icon=h('span','cx-menu-icon');icon.setAttribute('aria-hidden','true');if(item.icon!=null){icon.dataset.icon=String(item.icon);const rendered=options.renderIcon?.(item.icon,item);if(rendered?.nodeType)icon.append(rendered.cloneNode(true));else if(rendered!=null)setText(icon,rendered)}
4
+ button.append(icon);const label=h('span','cx-menu-label');setText(label,item.label);button.append(label);if(item.badge!=null&&item.badge!==''){const badge=h('span','cx-menu-badge');badge.dataset.hfxPart='badge';setText(badge,item.badge);button.append(badge)}
5
+ if(item.shortcut){const shortcut=h('kbd');setText(shortcut,item.shortcut);button.append(shortcut)}
6
+ uiMenuModels.set(button,item);container.append(button);if(item.items?.length){button.setAttribute('aria-haspopup','menu');button.setAttribute('aria-expanded','false');const child=h('div','cx-menu');child.id=button.id+'-menu';child.hidden=true;child.setAttribute('role','menu');child.setAttribute('aria-labelledby',button.id);child.dataset.hfxPart='menu';child.dataset.state='closed';button.setAttribute('aria-controls',child.id);const chevron=h('span','cx-menu-chevron');chevron.setAttribute('aria-hidden','true');setText(chevron,'›');button.append(chevron);container.append(child);render(child,item.items)}}};render(menu,items)};function uiMenuTriangle(point,origin,box){if(!point||!origin||!box)return false;const x=Math.abs(box.left-origin.x)<Math.abs(box.right-origin.x)?box.left:box.right;const a=origin,b={x,y:box.top},c={x,y:box.bottom};const cross=(p,q,r)=>(p.x-r.x)*(q.y-r.y)-(q.x-r.x)*(p.y-r.y);const d=[cross(point,a,b),cross(point,b,c),cross(point,c,a)];return!(d.some(value=>value<0)&&d.some(value=>value>0))}
7
+ UI_IMPL.menu=(root,options={},signal)=>{const lifetime=new AbortController(),ownSignal=lifetime.signal;const trigger=options.trigger||document.getElementById(root.dataset.cxTrigger||root.getAttribute('aria-labelledby'));const surface=options.surface||root;const directionBefore=surface.getAttribute('dir'),rootDirectionBefore=root.getAttribute('dir');let entries=[],children=new Map(),active=null,hoverTimer,searchTimer,search='',destroyed=false;let pointer,origin,pending,graceUntil=0;root.classList.add('cx-menu');root.setAttribute('role','menu');root.tabIndex=-1;root.dataset.hfxPart='menu';if(!root.id)root.id='cx-ui-menu-' + ++uiMenuIdentity;if(trigger&&options.decorateTrigger!==false){if(!trigger.id)trigger.id=root.id+'-trigger';trigger.setAttribute('aria-haspopup','menu');trigger.setAttribute('aria-controls',root.id);trigger.setAttribute('aria-expanded','false');root.setAttribute('aria-labelledby',trigger.id)}
8
+ if(options.label){root.setAttribute('aria-label',options.label);root.removeAttribute('aria-labelledby')}
9
+ const overlay=UI_TOOLS.overlay(surface,{kind:options.surface?'drawer':'menu',trigger,host:options.host||trigger||root,portal:options.portal,anchored:options.anchored??!options.surface,decorateTrigger:options.decorateTrigger,placement:options.placement||root.dataset.placement||'bottom-start',modal:!!options.surface,dismissible:true,initialFocus:()=>root},ownSignal);const owned=element=>element?.closest('[role="menu"]')===root;function focus(item){if(!item){root.focus({preventScroll:true});return}
10
+ for(const entry of entries)entry.tabIndex=entry===item?0:-1;active=item;item.focus({preventScroll:true})}
11
+ function closeChildren(except){for(const[entry,controller]of children)if(entry!==except)controller.close('parent',false,true)}
12
+ function openChild(item,keyboard){if(item.getAttribute('aria-disabled')==='true')return;const child=children.get(item);closeChildren(item);if(child&&!child.opened())child.open({focus:keyboard?'first':'none'})}
13
+ function clearHover(){clearTimeout(hoverTimer);pending=null;origin=null}
14
+ function hover(item){clearTimeout(hoverTimer);pending=item;const attempt=()=>{if(destroyed||!overlay.opened||!pending)return;const opened=[...children.values()].find(child=>child.opened());if(opened&&Date.now()<graceUntil&&uiMenuTriangle(pointer,origin,opened.element.getBoundingClientRect())){hoverTimer=setTimeout(attempt,150);return}
15
+ focus(pending);openChild(pending,false);pending=null};hoverTimer=setTimeout(attempt,150)}
16
+ function syncState(item){item.dataset.state=item.getAttribute('aria-disabled')==='true'?'disabled':
17
+ item.getAttribute('aria-checked')==='true'?'selected':''}
18
+ function activate(item,event){if(!item||item.getAttribute('aria-disabled')==='true')return;if(children.has(item)){openChild(item,true);return}
19
+ const role=item.getAttribute('role'),model=uiMenuModels.get(item);if(role==='menuitemcheckbox'||role==='menuitemradio'){if(role==='menuitemradio'){for(const peer of entries)if(peer.getAttribute('role')===role&&peer.dataset.radioGroup===item.dataset.radioGroup){peer.setAttribute('aria-checked','false');syncState(peer)}}
20
+ item.setAttribute('aria-checked',String(role==='menuitemradio'||item.getAttribute('aria-checked')!=='true'));syncState(item)}
21
+ const checked=item.hasAttribute('aria-checked')?item.getAttribute('aria-checked')==='true':undefined;const selected={...(model||{id:item.dataset.itemId,label:item.querySelector('.cx-menu-label')?.textContent||item.textContent}),...(checked!==undefined?{checked}:{})};const detail={id:item.dataset.itemId,item:selected,checked,element:item,originalEvent:event};if(role!=='menuitemcheckbox')(options.closeAll||close)('select');UI_TOOLS.emit(options.eventRoot||root,'menu','select',detail);options.onSelect?.(detail.item,event,item,detail)}
22
+ function keydown(event){if(!owned(event.target))return;const index=entries.indexOf(event.target),rtl=getComputedStyle(root).direction==='rtl';const forward=rtl?'ArrowLeft':'ArrowRight',backward=rtl?'ArrowRight':'ArrowLeft';if(['ArrowDown','ArrowUp','Home','End'].includes(event.key)){event.preventDefault();clearHover();const at=event.key==='Home'?0:event.key==='End'?entries.length-1:
23
+ (index +(event.key==='ArrowDown'?1:-1)+ entries.length)%entries.length;closeChildren();focus(entries[at])}else if(event.key===forward){event.preventDefault();clearHover();openChild(event.target,true)}
24
+ else if(event.key===backward&&options.parentItem){event.preventDefault();close('back')}
25
+ else if(event.key==='Enter'||event.key===' '){event.preventDefault();activate(event.target,event)}
26
+ else if(event.key==='Tab'){clearHover();(options.closeAll||close)('tab',false);(options.tabTrigger||trigger)?.focus({preventScroll:true})}else if(event.key.length===1&&!event.ctrlKey&&!event.metaKey&&!event.altKey){event.preventDefault();clearTimeout(searchTimer);search +=event.key.toLocaleLowerCase();const term=[...search].every(letter=>letter===search[0])?search[0]:search;const start=term.length>1?Math.max(index,0):index+1;const ordered=entries.slice(start).concat(entries.slice(0,start));const found=ordered.find(item=>(item.querySelector('.cx-menu-label')?.textContent||item.textContent).trim().toLocaleLowerCase().startsWith(term));if(found){closeChildren();focus(found)}
27
+ searchTimer=setTimeout(()=>{search=''},700)}}
28
+ function refresh(){if(destroyed)return;clearHover();for(const child of children.values())child.destroy();children=new Map();entries=[...root.querySelectorAll(uiMenuItemSelector)].filter(owned);for(const entry of entries){entry.classList.add('cx-menu-item');entry.dataset.hfxPart='menu-item';entry.tabIndex=-1;if(entry.disabled){entry.disabled=false;entry.setAttribute('aria-disabled','true')}
29
+ syncState(entry);if(entry.hasAttribute('aria-checked')){let icon=entry.querySelector('.cx-menu-icon');if(!icon){icon=h('span','cx-menu-icon');icon.setAttribute('aria-hidden','true');entry.prepend(icon)}
30
+ if(icon.textContent.trim()==='✓')icon.textContent=''}
31
+ const icon=entry.querySelector('.cx-menu-icon[data-icon]');if(icon&&!uiMenuModels.has(entry)&&options.renderIcon){const rendered=options.renderIcon(icon.dataset.icon,{id:entry.dataset.itemId});if(rendered?.nodeType)icon.replaceChildren(rendered.cloneNode(true));else if(rendered!=null)setText(icon,rendered)}
32
+ const childRoot=document.getElementById(entry.getAttribute('aria-controls'));if(childRoot?.getAttribute('role')==='menu'){children.set(entry,UI_IMPL.menu(childRoot,{...options,surface:null,trigger:entry,decorateTrigger:true,label:undefined,parentItem:entry,placement:getComputedStyle(options.host||trigger||root).direction==='rtl'?'left':'right',tabTrigger:options.tabTrigger||trigger,eventRoot:options.eventRoot||root,closeAll:options.closeAll||close},ownSignal))}}
33
+ active=entries.includes(active)?active:null;if(overlay.opened&&root.contains(document.activeElement))focus(active||entries[0])}
34
+ function open(settings={}){if(destroyed)return false;clearHover();search='';clearTimeout(searchTimer);surface.dir=root.dir=getComputedStyle(options.host||trigger||root).direction;if(options.surface)root.hidden=false;if(!overlay.open(settings))return false;root.dataset.state='open';if(settings.focus==='none')trigger?.focus({preventScroll:true});else focus(settings.focus==='last'?entries.at(-1):entries[0]);return true}
35
+ function close(reason='close',restoreFocus,force=false){clearHover();return overlay.close(reason,restoreFocus,force)}
36
+ function destroy(){if(destroyed)return;destroyed=true;clearHover();clearTimeout(searchTimer);for(const child of children.values())child.destroy();children.clear();overlay.destroy();lifetime.abort();if(directionBefore===null)surface.removeAttribute('dir');else surface.setAttribute('dir',directionBefore);if(rootDirectionBefore===null)root.removeAttribute('dir');else root.setAttribute('dir',rootDirectionBefore);signal?.removeEventListener('abort',destroy)}
37
+ root.addEventListener('keydown',keydown,{signal:ownSignal});root.addEventListener('click',event=>{const item=event.target.closest(uiMenuItemSelector);if(owned(item)){event.preventDefault();clearHover();activate(item,event)}},{signal:ownSignal});root.addEventListener('pointerover',event=>{if(event.pointerType==='touch')return;const item=event.target.closest(uiMenuItemSelector);if(owned(item)&&!item.contains(event.relatedTarget))hover(item)},{signal:ownSignal});root.addEventListener('pointerout',event=>{const item=event.target.closest(uiMenuItemSelector);if(owned(item)&&!item.contains(event.relatedTarget)){origin=pointer||{x:event.clientX,y:event.clientY};graceUntil=Date.now()+ 750}},{signal:ownSignal});document.addEventListener('pointermove',event=>{if(!overlay.opened)return;pointer={x:event.clientX,y:event.clientY};if([...children.values()].some(child=>child.opened()&&child.element.contains(event.target)))clearHover();else if(!root.contains(event.target)&&![...children.values()].some(child=>child.opened()))clearHover()},{signal:ownSignal});surface.addEventListener(options.surface?'cx-drawer:close':'cx-menu:close',event=>{if(event.target!==surface)return;clearHover();search='';root.dataset.state='closed';for(const entry of entries)entry.tabIndex=-1},{signal:ownSignal});if(trigger&&options.bindTrigger!==false&&!options.parentItem){trigger.addEventListener('click',()=>overlay.opened?close():open(),{signal:ownSignal});trigger.addEventListener('keydown',event=>{if(['Enter',' ','ArrowDown','ArrowUp'].includes(event.key)){event.preventDefault();open({focus:event.key==='ArrowUp'?'last':'first'})}},{signal:ownSignal})}
38
+ signal?.addEventListener('abort',destroy,{once:true});refresh();if(signal?.aborted)destroy();return{element:root,open,close,refresh,destroy,opened:()=>overlay.opened}};UI_IMPL.contextMenu=(target,itemsOrFactory,options={})=>{const lifetime=new AbortController(),signal=lifetime.signal;const delegated=typeof target==='string',listener=delegated?document:target;const editable='a[href],area[href],input,textarea,select,[contenteditable]:not([contenteditable="false"]),[role="textbox"]';let current,pressTimer,press,suppressClick=false,destroyed=false,pressSelection=null;const nodeOf=event=>event?.target?.nodeType===1?event.target:event?.target?.parentElement;const match=event=>{const node=nodeOf(event),element=delegated?node?.closest(target):target.contains(node)?target:null;return element&&(options.match?options.match(event,element):element)};const keyboard=event=>event?.type==='keydown'||event?.type==='contextmenu'&&event.button!==2&&event.clientX===0&&event.clientY===0;const selected=event=>event?.type==='contextmenu'&&pressSelection!==null?!!pressSelection:!!document.getSelection()?.toString();const nativeMenu=event=>!!event&&((event.shiftKey&&!keyboard(event))||!!nodeOf(event)?.closest(editable)||selected(event));function clearPress(){clearTimeout(pressTimer);pressTimer=null;press=null}
39
+ function release(entry,reason){if(current!==entry)return;current=null;entry.surface.removeEventListener(entry.closeEvent,entry.closed);entry.surface.removeEventListener('contextmenu',entry.native);entry.controller?.destroy();entry.menu.remove();entry.sheet?.remove();for(const[name,value]of entry.before){const now=entry.anchor.getAttribute(name);if(now!==entry.written.get(name))continue;if(value===null)entry.anchor.removeAttribute(name);else entry.anchor.setAttribute(name,value)}
40
+ options.onClose?.({...entry.detail,reason})}
41
+ function close(reason='close',restoreFocus=true,force=false){clearPress();return current?current.controller.close(reason,restoreFocus,force):true}
42
+ function open(event,element,settings={}){if(destroyed||event?.defaultPrevented&&!settings.touch||nativeMenu(event)||!element?.isConnected)return false;const prepared=options.beforeOpen?.(event,element,settings);if(prepared===false||destroyed)return false;if(prepared?.nodeType===1)element=prepared;if(!element.isConnected)return false;const items=typeof itemsOrFactory==='function'?itemsOrFactory(event,element):itemsOrFactory;if(!items?.length||destroyed||!element.isConnected)return false;close('replace',false,true);const menu=h('div','cx-menu');menu.hidden=true;menu.dataset.contextMenu='';menu.setAttribute('role','menu');menu.dataset.hfxPart='menu';if(options.variant)menu.dataset.hfxVariant=options.variant;document.body.append(menu);UI_TOOLS.menuItems(menu,items,options);const touch=!!settings.touch,byKey=settings.keyboard??keyboard(event);const label=(typeof options.label==='function'?options.label(event,element):options.label)||
43
+ element.getAttribute('aria-label')||element.textContent.trim()||UI_TOOLS.labels(options.labels).stateDetails;let sheet;if(touch){sheet=h('dialog','cx-drawer cx-context-sheet');sheet.dataset.side='bottom';sheet.dataset.hfxPart='drawer';sheet.hidden=true;sheet.setAttribute('aria-label',label);document.body.append(sheet);sheet.append(menu)}
44
+ const anchor=options.anchor?.(event,element)||(byKey&&!options.match&&nodeOf(event))||element;const before=['tabindex'].map(name=>[name,anchor.getAttribute(name)]);if(!anchor.matches('button,input,select,textarea,a[href],[tabindex]'))anchor.tabIndex=-1;const surface=sheet||menu,detail={menu,surface,element,event,touch};const entry=current={menu,sheet,surface,anchor,before,detail,written:new Map(),closeEvent:sheet?'cx-drawer:close':'cx-menu:close'};entry.controller=UI_IMPL.menu(menu,{...options,trigger:anchor,host:options.host||element,eventRoot:options.eventRoot||options.host||element,surface:sheet,bindTrigger:false,decorateTrigger:false,label},signal);entry.closed=ev=>{if(ev.target===surface)release(entry,ev.detail.reason)};entry.native=ev=>{if(!nativeMenu(ev))ev.preventDefault()};surface.addEventListener(entry.closeEvent,entry.closed);surface.addEventListener('contextmenu',entry.native);entry.written=new Map(before.map(([name])=>[name,anchor.getAttribute(name)]));const opened=entry.controller.open({modal:touch,point:settings.point||
45
+ (!byKey&&!touch&&event?{x:event.clientX,y:event.clientY}:undefined)});if(current!==entry)return false;entry.written=new Map(before.map(([name])=>[name,anchor.getAttribute(name)]));if(!opened){release(entry,'cancel');return false}
46
+ options.onOpen?.(detail);return current===entry}
47
+ listener.addEventListener('contextmenu',event=>{if(event.defaultPrevented||nativeMenu(event))return;if(current?.surface.contains(event.target)){event.preventDefault();return}
48
+ const element=match(event);if(!element)return;if(suppressClick||press||event.pointerType==='touch'){event.preventDefault();return}
49
+ if(open(event,element)){event.preventDefault();if(pressSelection==='')document.getSelection()?.removeAllRanges()}},{signal});document.addEventListener('pointerdown',event=>{pressSelection=event.button===2?document.getSelection()?.toString()||'':null},{signal,capture:true});document.addEventListener('keydown',()=>{pressSelection=null},{signal,capture:true});listener.addEventListener('keydown',event=>{if(event.defaultPrevented||event.key!=='ContextMenu'&&!(event.key==='F10'&&event.shiftKey))return;const element=match(event);if(element&&open(event,element,{keyboard:true})){event.preventDefault();event.stopPropagation()}},{signal});listener.addEventListener('pointerdown',event=>{clearPress();suppressClick=false;const element=match(event);if(event.pointerType!=='touch'||!element||nativeMenu(event)||event.isPrimary===false||options.gesture?.(event,element)===false)return;press={id:event.pointerId,x:event.clientX,y:event.clientY};pressTimer=setTimeout(()=>{if(press&&open(event,element,{touch:true}))suppressClick=true;clearPress()},500)},{signal});document.addEventListener('pointermove',event=>{if(press&&event.pointerId===press.id&&Math.hypot(event.clientX-press.x,event.clientY-press.y)>10)clearPress()},{signal,passive:true});for(const type of['pointerup','pointercancel','scroll'])document.addEventListener(type,clearPress,{signal,capture:true,passive:true});listener.addEventListener('click',event=>{if(suppressClick&&match(event)){event.preventDefault();event.stopPropagation();suppressClick=false}},{signal,capture:true});if(options.closeOnFocusOutside)document.addEventListener('focusin',event=>{if(current&&!current.surface.contains(event.target)&&!current.anchor.contains(event.target))close('blur',false)},{signal});global.addEventListener('blur',clearPress,{signal});const dispose=()=>{if(!destroyed){destroyed=true;clearPress();close('destroy',false,true);lifetime.abort()}};dispose.open=open;dispose.close=close;return dispose};UI_IMPL.treeActions={start(hostControl){const signal=this.interactionUiLifetime.signal;this.grid.addEventListener("scroll",()=>{const panel=this.interactionPanel;if(panel&&(panel._cxScrollTop!==this.grid.scrollTop||panel._cxScrollLeft!==this.grid.scrollLeft))this.closeInteractionPanel(false)},{signal,passive:true});global.addEventListener("resize",()=>this.closeInteractionPanel(),{signal});this.actionMenuBinding=UI_IMPL.contextMenu(this.grid,(_event,row)=>{const w=row._w,items=this.actionMenuItems(w);return row._w===w&&this.rendered.get(w)===row?items:[]},{host:this.host,label:this.labels.actions,closeOnFocusOutside:true,match:event=>{const row=event.target.closest(".cx-row");return row&&this.grid.contains(row)&&!hostControl(event.target)?row:null},beforeOpen:(_event,row,settings)=>{const w=settings.node||row._w,revision=(this.uiWorkRevision||0)+(this.interactionPanel?1:0);if(!this.actionMenuEligible(w)||row._w!==w)return false;if(this.interactionPanel)this.closeInteractionPanel(false);if(this.interactionClosing||this.destroyed||(this.uiWorkRevision||0)!==revision)return false;this.render();return this.actionMenuEligible(w)&&(this.uiWorkRevision||0)===revision&&this.rendered.get(w)?.isConnected?this.rendered.get(w):false},onOpen:({menu,element})=>{this.interactionPanel=menu;this.panelNode=element._w;menu._cxScrollTop=this.grid.scrollTop;menu._cxScrollLeft=this.grid.scrollLeft;document.dispatchEvent(new CustomEvent("canopyx:closemenus",{detail:{source:menu}}))},onClose:({menu})=>{if(this.interactionPanel!==menu)return;this.interactionPanel=null;this.panelNode=null;this.uiWorkRevision=(this.uiWorkRevision||0)+ 1},onSelect:item=>{Promise.resolve().then(()=>item.run()).catch(error=>this.emit("error",{error}))}});signal.addEventListener("abort",()=>this.actionMenuBinding(),{once:true})},openInteractionPanel(w,anchor,role,label){const revision=(this.uiWorkRevision||0)+(this.interactionPanel?1:0);this.closeInteractionPanel(false);if(this.destroyed||this.interactionClosing||this.interactionPanel||(this.uiWorkRevision||0)!==revision)return null;this.render();anchor=this.rendered.get(w);if(this.destroyed||this.interactionClosing||this.interactionPanel||(this.uiWorkRevision||0)!==revision||!anchor?.isConnected)return null;const panel=this.interactionPanel=h("div","cx-interaction-panel"),lifetime=new AbortController();const signal=lifetime.signal;panel.setAttribute("role",role);panel.setAttribute("aria-label",label);panel.dataset.hfxPart="popover";panel.style.inset="auto";panel.style.margin="0";this.panelNode=w;this.host.appendChild(panel);panel._cxLifetime=lifetime;panel._cxOverlay=UI_TOOLS.overlay(panel,{host:this.host,trigger:anchor,kind:"popover",focus:false,decorateTrigger:false},signal);panel.addEventListener("pointerdown",()=>{panel._cxPointerFocus=panel.contains(document.activeElement)},{signal});const rememberFocus=event=>{if(event.target!==panel)return;const active=document.activeElement;panel._cxOwnedFocus=panel.contains(active)||panel._cxPointerFocus&&(active===document.body||active===document.documentElement)};for(const type of["cx-popover:cancel","cx-popover:beforeclose"])panel.addEventListener(type,rememberFocus,{signal});panel.addEventListener("cx-popover:close",event=>{if(event.target===panel&&this.interactionPanel===panel)this.closeInteractionPanel(event.detail.reason==="cancel")},{signal});this.interactionUiLifetime.signal.addEventListener("abort",()=>lifetime.abort(),{once:true,signal});panel._cxOverlay.open();return this.interactionPanel===panel&&!this.destroyed&&(this.uiWorkRevision||0)===revision?panel:null},closeInteractionPanel(restoreFocus=true){const panel=this.interactionPanel,controller=this.editorController,w=this.panelNode;if(!panel){this.actionMenuBinding?.close("replace",false,true);return null}
50
+ const active=document.activeElement;const owned=panel._cxOwnedFocus||panel.contains(active)||panel._cxPointerFocus&&(active===document.body||active===document.documentElement);if(panel.getAttribute("role")==="menu"){this.actionMenuBinding.close("close",false,true);const focus=owned?{node:w,revision:this.uiWorkRevision}:null;if(restoreFocus)this.restoreInteractionFocus(focus);return focus}
51
+ if(controller&&this.uiPendingOperation&&this.uiPendingOperation.controller===controller){this.uiPendingOperation=null;setText(this.live,"")}
52
+ this.uiWorkRevision=(this.uiWorkRevision||0)+ 1;const focus=owned?{node:w,revision:this.uiWorkRevision}:null;this.interactionPanel=null;this.panelNode=null;this.editorController=null;panel._cxLifetime.abort();panel.remove();this.abortInteractionController(controller);if(restoreFocus)this.restoreInteractionFocus(focus);return focus},placeInteractionPanel(anchor){const panel=this.interactionPanel;if(!panel||panel.getAttribute("role")==="menu")return;UI_TOOLS.position(panel,anchor,"bottom-start");panel._cxScrollTop=this.grid.scrollTop;panel._cxScrollLeft=this.grid.scrollLeft},async performInteraction(work,controller=null){this.uiWorkRevision=(this.uiWorkRevision||0)+ 1;const operation=this.uiPendingOperation={controller};setText(this.live,this.labels.interactionPending);try{const accepted=await work();if(!this.destroyed&&this.uiPendingOperation===operation)setText(this.live,accepted?"":this.labels.interactionRejected);return accepted}catch(error){if(!this.destroyed&&this.uiPendingOperation===operation)setText(this.live,fill(this.labels.interactionFailed,{error:error&&error.message||String(error)}));return false}finally{if(this.uiPendingOperation===operation)this.uiPendingOperation=null}},beginEdit(id,columnId,cellIsObject){if(this.destroyed||this.interactionClosing||this.initializing||this.restoring||!this.opts.onEdit)return false;const w=this.interactionNode(id),index=this.columns.findIndex(column=>column.id===columnId),column=this.columns[index];if(!w||!column||!column.editable||column.hidden||!this.eligible("canEdit",w.h,column))return false;const row=this.rendered.get(w);if(!row||!row.isConnected)return false;const label=fill(this.labels.editValue,{column:column.title});const panel=this.openInteractionPanel(w,row,"dialog",label);if(!panel)return false;const controller=this.editorController=new AbortController();const raw=this.cellOf(w.h,column,index),value=cellIsObject(raw)?raw.value:raw;const input=h("input","cx-editor");input.type=column.kind==="number"||typeof value==="number"?"number":typeof value==="boolean"?"checkbox":"text";if(input.type==="number"){input.step="any";input.required=true}
53
+ input.checked=value===true;input.value=value==null?"":String(value);input.setAttribute("aria-label",label);input.addEventListener("input",()=>input.setCustomValidity(""));const controls=h("div","cx-interaction-buttons");const save=h("button","cx-save"),cancel=h("button");save.type=cancel.type="button";setText(save,this.labels.saveEdit);setText(cancel,this.labels.cancelEdit);const title=h("div","cx-interaction-title");setText(title,label);controls.append(save,cancel);panel.append(title,input,controls);const submit=async()=>{if(save.disabled)return;let next=input.type==="checkbox"?input.checked:input.value;if(input.type==="number"){if(!input.value.trim()||!Number.isFinite(Number(input.value))){input.setCustomValidity(fill(this.labels.invalidEdit,{column:column.title}));input.reportValidity();return}
54
+ next=Number(input.value)}
55
+ input.setCustomValidity("");input.disabled=save.disabled=true;cancel.focus();const accepted=await this.performInteraction(()=>this.requestEdit(id,columnId,next,{signal:controller.signal,reason:"editor"}),controller);if(this.interactionPanel!==panel)return;if(accepted)this.closeInteractionPanel();else{input.disabled=save.disabled=false;input.focus()}};save.addEventListener("click",submit);cancel.addEventListener("click",()=>this.closeInteractionPanel());panel.addEventListener("keydown",event=>{if(event.key==="Enter"&&event.target===input){event.preventDefault();submit()}});this.placeInteractionPanel(row);input.focus();if(input.type!=="checkbox")input.select();return true},moveSources(w){if(!this.view.dragDrop||!this.opts.onDrop||this.destroyed||this.interactionClosing||this.initializing||this.restoring||!w||w.status||w.h.detail)return false;const nodes=this.selected.has(w)?Array.from(this.selected).filter(node=>!node.h.detail):[w];if(!nodes.length||!nodes.every(node=>this.keyMap.get(node.key)===node&&!node._invalidated&&this.eligible("canDrag",node.h)))return false;return nodes},markMove(w){const nodes=this.moveSources(w);if(!nodes)return false;this.moveNodes=nodes;this.cacheDirty=true;setText(this.live,this.labels.markMove);return true},moveTarget(w,placement="inside"){if(!this.moveNodes||!w||w.status||w.h.detail||this.destroyed)return false;const nodes=this.moveNodes;if(nodes.some(node=>node._invalidated||this.keyMap.get(node.key)!==node))return false;return!!this.prepareDrop(nodes.map(node=>node.key),w.key,placement)&&this.moveNodes===nodes},async moveTo(w,placement,reason="menu"){if(!this.moveTarget(w,placement))return false;const nodes=this.moveNodes;this.moveNodes=null;this.cacheDirty=true;return this.performInteraction(()=>this.requestDrop(nodes.map(node=>node.key),w.key,placement,{reason}))},actionMenuEligible(w){return!this.destroyed&&!this.interactionClosing&&!this.initializing&&!this.restoring&&
56
+ !!w&&!w.status&&!w.h.detail&&!w._invalidated&&this.keyMap.get(w.key)===w},actionMenuItems(w){if(!this.actionMenuEligible(w))return[];const items=[];if(this.opts.onEdit)for(const column of this.columns){if(column.editable&&!column.hidden)items.push({id:"edit:"+column.id,label:fill(this.labels.editValue,{column:column.title}),disabled:!this.eligible("canEdit",w.h,column),run:()=>this.beginEdit(w.key,column.id)})}
57
+ if(this.opts.onAction)for(const action of this.interactions.actions)items.push({id:"action:"+action.id,label:action.label,disabled:!this.eligible("isActionEnabled",w.h,action),run:()=>this.performInteraction(()=>this.requestAction(w.key,action.id,{reason:"menu"}))});if(this.view.dragDrop&&this.opts.onDrop){items.push({id:"move:mark",label:this.labels.markMove,disabled:!this.moveSources(w),run:()=>this.markMove(w)});if(this.moveNodes){for(const[placement,label]of[["inside","moveHere"],["before","moveBefore"],["after","moveAfter"]])
58
+ items.push({id:"move:"+placement,label:this.labels[label],disabled:!this.moveTarget(w,placement),run:()=>this.moveTo(w,placement)});items.push({id:"move:cancel",label:this.labels.cancelMove,run:()=>{this.moveNodes=null;this.cacheDirty=true}})}}
59
+ return this.actionMenuEligible(w)?items:[]},openActionMenu(w,anchor){if(!this.actionMenuEligible(w)||!anchor?.isConnected||!this.actionMenuBinding)return false;const hasItems=this.opts.onEdit&&this.columns.some(column=>column.editable&&!column.hidden)||
60
+ this.opts.onAction&&this.interactions.actions.length||this.view.dragDrop&&this.opts.onDrop;if(!hasItems)return false;const opened=this.actionMenuBinding.open(null,anchor,{keyboard:true,node:w});if(opened?.then){opened.catch(error=>{if(!this.destroyed)this.emit("error",{error})});return true}
61
+ return opened},onKey(event,hostControl){if(!event.defaultPrevented&&!event.isComposing&&!hostControl(event.target)&&event.ctrlKey&&event.shiftKey&&!event.altKey){const row=event.target.closest(".cx-row"),w=row&&row._w;if(event.key.toLowerCase()==="x"&&this.markMove(w)){event.preventDefault();event.stopPropagation();return true}
62
+ if(event.key.toLowerCase()==="v"&&this.moveTarget(w)){event.preventDefault();event.stopPropagation();this.moveTo(w,"inside","keyboard");return true}}
63
+ return false},};UI_IMPL.columnMenu=function(id,anchor,{gridIcon,gridQueryStart}){const grid=this,column=this.columns.find(item=>item.id===id);if(!column)return false;const title=fill(this.labels.gridColumnMenu,{column:column.title});return this.openGridPopover(anchor,"cx-column-menu",title,id,(panel,signal)=>{const actions=new Map();const icons=new Map([[this.labels.gridSortAscending,"up"],[this.labels.gridSortDescending,"down"],[this.labels.gridFilterColumn,"filter"],[this.labels.gridPinLeft,"pin"],[this.labels.gridPinRight,"pin"],[this.labels.gridFitContent,"fit"],[this.labels.gridHideColumn,"hide"]]);const paths={pin:'<path d="M9 4h6l-1 6 3 3H7l3-3zM12 13v7"/>',fit:'<path d="M4 12h16M7 9l-3 3 3 3M17 9l3 3-3 3M4 5v14M20 5v14"/>',hide:'<path d="M3 3l18 18M10.6 6.1A9.8 9.8 0 0 1 12 6c5 0 8.5 4.5 9 6-.3.8-1.2 2.3-2.6 3.6M6.4 7.6C4.6 8.9 3.4 10.8 3 12c.5 1.5 4 6 9 6 1.6 0 3-.4 4.3-1.1"/>'};const add=(label,action,disabled=false)=>{const button=h("button","cx-button cx-mi"),icon=h("span","ico cx-menu-icon"),name=icons.get(label);button.type="button";button.setAttribute("role","menuitem");button.disabled=disabled;button.dataset.itemId=String(actions.size);actions.set(button.dataset.itemId,action);icon.setAttribute("aria-hidden","true");if(name)icon.appendChild(gridIcon(name,paths[name]));const text=h("span","cx-menu-label");setText(text,label);button.append(icon,text);panel.appendChild(button)};const rule=()=>{const separator=h("hr","cx-menu-rule");separator.setAttribute("role","separator");panel.appendChild(separator)};const sort=direction=>this.setQuery(gridQueryStart(this.queryForChange(true),{sort:[...(this.queryForChange().sort||[]).filter(item=>item.column!==id),...(direction?[{column:id,direction}]:[])]}));add(this.labels.gridSortAscending,()=>sort("asc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridSortDescending,()=>sort("desc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridClearSort,()=>sort(null),!(this.getQuery()?.sort||[]).some(item=>item.column===id));rule();add(this.labels.gridFilterColumn,()=>{const target=this.resolveColumnAnchor(id,anchor);if(target)this.openColumnFilter(id,target)},column.filterable===false);rule();for(const[pin,label]of[["left","gridPinLeft"],["right","gridPinRight"],["none","gridUnpin"]])
64
+ add(this.labels[label],()=>this.setColumnPinned(id,pin));rule();add(this.labels.gridFitContent,()=>this.autoFitColumn(id),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridFitAllColumns,()=>this.autoFitColumns(),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridHideColumn,()=>this.setColumnVisible(id,false),this.columns.filter(item=>!item.hidden).length===1);this.appendColumnGroupActions?.(column,add,rule);return UI_IMPL.menu(panel,{host:this.host,trigger:anchor,anchored:false,label:title,bindTrigger:false,decorateTrigger:false,get tabTrigger(){return grid.resolveColumnAnchor(id,anchor)},onSelect:item=>{Promise.resolve().then(actions.get(item.id)).catch(error=>this.emit("error",{error}))}},signal)})};installed.add(context.UI_IMPL)}};(global.CanopyXParts||=[]).push(["ui-menu",part])})(typeof window!=="undefined"?window:globalThis);
@@ -0,0 +1,73 @@
1
+ @layer hfx.components{
2
+ :where([data-cx-tabs],[data-cx-stepper]){
3
+ color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));
4
+ font-family:var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);
5
+ font-size:var(--hfx-type-body-size,0.875rem);
6
+ line-height:var(--hfx-type-body-line,1.5);
7
+ min-inline-size:0;
8
+ }
9
+ .cx-tabs [hidden],.cx-stepper-host [hidden]{display:none;}
10
+ .cx-navigation-print{display:none;}
11
+ @media print{
12
+ .cx-navigation-print{display:block;}
13
+ :is(.cx-tabpanel,.cx-step-panel):has(> .cx-navigation-print) > .cx-navigation-body{display:none;}
14
+ }
15
+ :where([data-cx-tabs],[data-cx-stepper]) :where(button,[tabindex]):focus-visible{
16
+ outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));
17
+ outline-offset:var(--hfx-focus-offset,2px);
18
+ }
19
+ .cx-navigation-loading,.cx-navigation-error,.cx-step-errors{
20
+ padding:var(--hfx-space-4,1rem);
21
+ border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));
22
+ }
23
+ .cx-navigation-loading{
24
+ display:flex;
25
+ align-items:center;
26
+ gap:var(--hfx-space-2,0.5rem);
27
+ background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));
28
+ color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));
29
+ min-block-size:var(--hfx-control-height-lg,calc(44px - var(--cx-compact,0) * 8px));
30
+ }
31
+ .cx-navigation-spinner{
32
+ inline-size:var(--hfx-icon-lg,20px);
33
+ block-size:var(--hfx-icon-lg,20px);
34
+ border:var(--hfx-indicator-width,2px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));
35
+ border-block-start-color:var(--hfx-color-accent-indicator,light-dark(#11776f,#37c9b8));
36
+ border-radius:50%;
37
+ animation:cx-navigation-spin var(--hfx-motion-duration-slow,320ms) linear infinite;
38
+ }
39
+ .cx-navigation-skeleton{display:grid;gap:var(--hfx-space-2,0.5rem);padding:var(--hfx-space-4,1rem);}
40
+ .cx-navigation-skeleton > span{block-size:var(--hfx-type-body-size,0.875rem);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));}
41
+ .cx-navigation-skeleton > span:nth-child(2){inline-size:75%;}
42
+ .cx-navigation-skeleton > span:nth-child(3){inline-size:50%;}
43
+ .cx-navigation-error,.cx-step-errors{
44
+ background:var(--hfx-color-status-bad-bg,light-dark(#f9e4e4,#3c272a));
45
+ color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));
46
+ border:var(--hfx-border-width,1px) solid var(--hfx-color-status-bad-border,light-dark(#eeacac,#814345));
47
+ margin-block-end:var(--hfx-space-3,0.75rem);
48
+ }
49
+ .cx-step-errors p{margin:0;font-weight:var(--hfx-weight-semibold,600);}
50
+ .cx-step-errors ul{margin-block:var(--hfx-space-2,0.5rem) 0;padding-inline-start:var(--hfx-space-5,1.5rem);}
51
+ .cx-navigation-retry{
52
+ background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));
53
+ color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));
54
+ border:var(--hfx-border-width,1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));
55
+ border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));
56
+ min-block-size:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));
57
+ padding-inline:var(--hfx-control-padding-x,calc(14px - var(--cx-compact,0) * 4px));
58
+ font:inherit;
59
+ cursor:pointer;
60
+ }
61
+ :where([data-cx-stepper]) .cx-visually-hidden{
62
+ position:absolute;
63
+ inline-size:var(--hfx-border-width,1px);
64
+ block-size:var(--hfx-border-width,1px);
65
+ overflow:hidden;
66
+ clip-path:inset(50%);
67
+ white-space:nowrap;
68
+ }
69
+ @keyframes cx-navigation-spin{to{transform:rotate(1turn);}}
70
+ @media (prefers-reduced-motion: reduce){
71
+ .cx-navigation-spinner{animation:none;}
72
+ }
73
+ }
@@ -0,0 +1,39 @@
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"d14b60f4d16a1cf3",requires:["ui-picker"],install(context){if(installed.has(context.UI_IMPL))return;const{UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml}=context;UI_TOOLS.navigation=(()=>{const focusable='a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';function owned(root,selector){return Array.from(root.querySelectorAll(selector)).filter(el=>el.closest('[data-cx-tabs],[data-cx-stepper]')===root)}
2
+ function scope(signal){const life=new AbortController();if(signal?.aborted)life.abort();else signal?.addEventListener('abort',()=>life.abort(),{once:true,signal:life.signal});return life}
3
+ function records(root,kind,options){const tabs=kind==='tabs';const buttons=owned(root,tabs?'[role="tab"]':'[data-step-id]');const panels=owned(root,tabs?'[role="tabpanel"]':'.cx-step-panel');return buttons.map((element,index)=>{const id=tabs?element.dataset.tabId:element.dataset.stepId;const config=(options[tabs?'tabs':'steps']||[]).find(item=>item.id===id)||{};const panel=tabs?panels.find(el=>el.id===element.getAttribute('aria-controls')):panels[index];const iconSlot=element.querySelector('[data-icon]');if(iconSlot&&options.renderIcon){const rendered=options.renderIcon(iconSlot.dataset.icon,{...config,id,index,element,panel});if(rendered?.nodeType)iconSlot.replaceChildren(rendered);else setText(iconSlot,typeof rendered==='string'?rendered:'')}
4
+ return{...config,id,index,element,panel,label:element.querySelector(tabs?'.cx-tab-label':'.cx-step-label')?.textContent||config.label||id,badge:element.querySelector('.cx-tab-badge')?.textContent||config.badge,icon:iconSlot?iconSlot.firstElementChild||iconSlot.textContent||undefined:config.icon,disabled:element.getAttribute('aria-disabled')==='true'||element.dataset.state==='disabled',optional:element.dataset.optional==='true',visited:element.dataset.visited==='true',state:element.dataset.state||'upcoming'}})}
5
+ function selection(root,prefix,options,life,read,commit){let version=0,pending;function cancel(){version++;pending?.abort();pending?.element?.removeAttribute('aria-busy')}
6
+ async function request(target,prepare,context){cancel();if(!target||target.disabled||life.signal.aborted)return false;const controller=new AbortController(),ticket=version;controller.element=target.element;pending=controller;const live=()=>ticket===version&&!controller.signal.aborted&&!life.signal.aborted;const from=read();const restoreFocus=()=>{if(context==='auto')return;const target=prefix==='tabs'?from?.element:from?.element.querySelector('button')||from?.panel?.querySelector('[data-hfx-part="title"],h3');target?.focus()};target.element.setAttribute('aria-busy','true');const abort=()=>controller.abort();life.signal.addEventListener('abort',abort,{once:true});try{if(prepare&&await wait(prepare(from,target,controller.signal,live),controller.signal)===false)return false;if(!live())return false;const guard=from!==target||context==='finish';if(guard&&!UI_TOOLS.emit(root,prefix,'beforechange',{from,to:target,signal:controller.signal},true)){if(live())restoreFocus();return false}
7
+ if(guard&&await wait(options.beforeChange?.(from,target,controller.signal),controller.signal)===false){if(live())restoreFocus();return false}
8
+ if(!live())return false;await wait(commit(from,target,controller.signal,live,context),controller.signal);return live()}catch(error){if(live()&&error?.name!=='AbortError')UI_TOOLS.emit(root,prefix,'error',{from,to:target,error});return false}finally{life.signal.removeEventListener('abort',abort);if(ticket===version)target.element.removeAttribute('aria-busy')}}
9
+ life.signal.addEventListener('abort',cancel,{once:true});return{request,cancel}}
10
+ function wait(value,signal){return new Promise((resolve,reject)=>{const task=Promise.resolve(value);const abort=()=>reject(new DOMException('Navigation cancelled','AbortError'));if(signal.aborted){task.catch(()=>{});abort();return}
11
+ signal.addEventListener('abort',abort,{once:true});task.then(result=>{signal.removeEventListener('abort',abort);resolve(result)},error=>{signal.removeEventListener('abort',abort);reject(error)})})}
12
+ function resolve(items,value){return typeof value==='number'?items[value]:items.find(item=>item.id===value)}
13
+ function position(labels,key,index,total){return fill(labels[key],{current:index+1,total})}
14
+ function panelTabStop(panel){if(panel?.getAttribute('role')==='tabpanel'){const hasFocusable=Array.from(panel.querySelectorAll(focusable)).some(el=>el.checkVisibility()&&!el.closest('[inert]'));panel.tabIndex=hasFocusable?-1:0}}
15
+ function pickerItems(items,selected,disabled=item=>item.disabled){return items.map(item=>({id:item.id,label:item.label,icon:item.icon,badge:item.badge,disabled:disabled(item),checked:item.id===selected}))}
16
+ function button(label,className){const el=document.createElement('button');el.type='button';el.className=className;setText(el,label);return el}
17
+ return{owned,scope,records,selection,resolve,position,panelTabStop,pickerItems,button,focusable}})();UI_TOOLS.navigation.deferred=(root,prefix,options,life,retry)=>{const bodies=new Map();const printCache=new Map(),projections=new Map();let printJob,destroyed=false;const n=UI_TOOLS.navigation,labels=UI_TOOLS.labels(options.labels);const templateFor=panel=>Array.from(panel.children).find(el=>el.tagName==='TEMPLATE');function bodyFor(item){if(!item.panel)return null;if(!bodies.has(item.panel)){const template=templateFor(item.panel);const body=document.createElement('div');body.className='cx-navigation-body';for(const child of Array.from(item.panel.childNodes)){if(child===template||child.nodeType===1&&child.matches('h3,[data-hfx-part="title"],.cx-step-print-state,.cx-step-errors,.cx-navigation-print'))continue;body.append(child)}
18
+ item.panel.append(body);bodies.set(item.panel,{body,template,loaded:false})}
19
+ return bodies.get(item.panel)}
20
+ function isDeferred(item){return!!item&&(item.deferred??(options.deferred||!!item.loader||!!item.panel?.querySelector('template')))}
21
+ async function load(item,signal,live){if(destroyed||life.signal.aborted||signal.aborted||!live())return false;if(!isDeferred(item)||!item.panel){n.panelTabStop(item.panel);return true}
22
+ const entry=bodyFor(item);if(entry.loaded&&(item.keepAlive??options.keepAlive)!==false)return true;removeProjection(item.panel);printCache.delete(item.panel);entry.loaded=false;const{body,template}=entry;body.replaceChildren();const status=document.createElement('div');status.className='cx-navigation-loading';status.setAttribute('role','status');const spinner=document.createElement('span');spinner.className='cx-navigation-spinner';spinner.setAttribute('aria-hidden','true');status.append(spinner,document.createTextNode(labels.stateLoading));const skeleton=h('div','cx-navigation-skeleton');skeleton.setAttribute('aria-hidden','true');skeleton.append(h('span'),h('span'),h('span'));body.append(status,skeleton);item.panel.setAttribute('aria-busy','true');item.panel.dataset.state='loading';const token={};token.done=new Promise(resolve=>{token.resolve=resolve});entry.pending=token;const interrupted=()=>{if(entry.pending!==token)return;token.resolve();if(destroyed||life.signal.aborted)return;item.panel.removeAttribute('aria-busy');const again=n.button(labels.stateRetry,'cx-navigation-retry');again.addEventListener('click',()=>retry(item.id),{signal:life.signal});body.replaceChildren(again);item.panel.dataset.state='selected'};signal.addEventListener('abort',interrupted,{once:true});try{const loader=item.loader||options.loader;const content=loader?await loader(item,signal):template?.content.cloneNode(true);if(entry.pending!==token||!live()||signal.aborted||life.signal.aborted)return false;body.replaceChildren();if(content!=null)UI_TOOLS.content(body,content);entry.loaded=true;item.panel.dataset.state='selected';UI_TOOLS.emit(root,prefix,'load',{item,panel:item.panel});n.panelTabStop(item.panel);return true}catch(error){if(entry.pending!==token||!live()||signal.aborted||life.signal.aborted)return false;item.panel.dataset.state='error';const alert=document.createElement('div');alert.setAttribute('role','alert');alert.className='cx-navigation-error';setText(alert,error?.message||labels.stateDetails);const again=n.button(labels.stateRetry,'cx-navigation-retry');again.addEventListener('click',()=>retry(item.id),{signal:life.signal});body.replaceChildren(alert,again);UI_TOOLS.emit(root,prefix,'error',{item,error});n.panelTabStop(item.panel);return false}finally{signal.removeEventListener('abort',interrupted);token.resolve();if(entry.pending===token){entry.pending=null;if(live())item.panel.removeAttribute('aria-busy')}}}
23
+ function leave(item){const entry=item&&bodies.get(item.panel);item?.panel?.removeAttribute('aria-busy');if(entry&&(item.keepAlive??options.keepAlive)===false){if(entry.loaded)printCache.set(item.panel,snapshot(entry.body));entry.body.replaceChildren();entry.loaded=false}}
24
+ function snapshot(body){const fragment=document.createDocumentFragment();for(const child of body.childNodes)fragment.append(cloneForPrint(child));return fragment}
25
+ function cloneForPrint(node){const copy=node.cloneNode(true),selector='input,textarea,select';const fields=el=>[...(el.matches?.(selector)?[el]:[]),...(el.querySelectorAll?.(selector)||[])];const source=fields(node),copies=fields(copy);source.forEach((field,index)=>{const target=copies[index];if(field.tagName==='SELECT')Array.from(field.options).forEach((option,i)=>{target.options[i].selected=option.selected});else{if(field.type!=='file')target.value=field.value;if(field.tagName==='INPUT')target.checked=field.checked}});return copy}
26
+ function removeProjection(panel){projections.get(panel)?.remove();projections.delete(panel)}
27
+ function printItems(){return n.records(root,prefix,{...options,renderIcon:undefined}).filter(item=>item.panel&&
28
+ (root.dataset.print!=='selected'||!item.panel.hidden))}
29
+ function project(item,content){removeProjection(item.panel);const projection=h('div','cx-navigation-print');projection.setAttribute('aria-hidden','true');projection.inert=true;if(content!=null)UI_TOOLS.content(projection,content?.nodeType?cloneForPrint(content):content);for(const field of projection.querySelectorAll('input,textarea,select,button')){field.removeAttribute('name');field.removeAttribute('form')}
30
+ for(const element of projection.querySelectorAll('[id]'))element.removeAttribute('id');bodyFor(item);item.panel.append(projection);projections.set(item.panel,projection)}
31
+ function projectLocal(){if(destroyed||life.signal.aborted)return;const items=printItems(),panels=new Set(items.map(item=>item.panel));for(const panel of projections.keys())if(!panels.has(panel)||bodies.get(panel)?.loaded)removeProjection(panel);for(const item of items){if(!isDeferred(item)||bodies.get(item.panel)?.loaded||projections.has(item.panel))continue;const content=printCache.get(item.panel)||(!(item.loader||options.loader)&&templateFor(item.panel)?.content);if(content)project(item,content)}}
32
+ function cancelPrint(clearCache=true){printJob?.controller.abort();printJob=null;for(const panel of projections.keys())removeProjection(panel);if(clearCache)printCache.clear()}
33
+ function waitForPrint(value,signal){return new Promise((resolve,reject)=>{const abort=()=>reject(new DOMException('Print preparation cancelled','AbortError'));const task=Promise.resolve(value);if(signal.aborted){task.catch(()=>{});abort();return}
34
+ signal.addEventListener('abort',abort,{once:true});task.then(resolve,reject).finally(()=>signal.removeEventListener('abort',abort))})}
35
+ async function preparePrint(){if(destroyed||life.signal.aborted)throw new DOMException('UI component destroyed','AbortError');if(printJob)return printJob.task;const job={controller:new AbortController()};printJob=job;const signal=job.controller.signal;job.task=(async()=>{projectLocal();for(const item of printItems()){if(!isDeferred(item))continue;const entry=bodies.get(item.panel);if(entry?.pending)await waitForPrint(entry.pending.done,signal);if(entry?.loaded||projections.has(item.panel))continue;const loader=item.loader||options.loader;const content=loader?await waitForPrint(loader(item,signal),signal):templateFor(item.panel)?.content;if(signal.aborted||destroyed||life.signal.aborted)throw new DOMException('Print preparation cancelled','AbortError');if(!printItems().some(current=>current.panel===item.panel)||bodies.get(item.panel)?.loaded)continue;project(item,content)}
36
+ projectLocal()})().catch(error=>{if(printJob===job)cancelPrint(false);throw error}).finally(()=>{if(printJob===job)printJob=null});return job.task}
37
+ function destroy(){if(destroyed)return;destroyed=true;cancelPrint();for(const[panel,entry]of bodies){panel.removeAttribute('aria-busy');entry.pending?.resolve()}
38
+ bodies.clear()}
39
+ window.addEventListener('beforeprint',projectLocal,{signal:life.signal});window.addEventListener('afterprint',cancelPrint,{signal:life.signal});life.signal.addEventListener('abort',destroy,{once:true});return{load,leave,destroy,isDeferred,preparePrint}};installed.add(context.UI_IMPL)}};(global.CanopyXParts||=[]).push(["ui-navigation",part])})(typeof window!=="undefined"?window:globalThis);
@@ -0,0 +1,79 @@
1
+ /* Component size options from the public anatomy. Colour,type and rhythm come from shared roles. */
2
+ @layer hfx.components{
3
+ :where(.cx-dialog,.cx-drawer,.cx-popover,.cx-tooltip,.cx-menu){
4
+ --cx-ui-dialog-sm:25rem;--cx-ui-dialog-md:35rem;--cx-ui-dialog-lg:50rem;
5
+ --cx-ui-drawer-sm:22.5rem;--cx-ui-drawer-md:30rem;--cx-ui-drawer-lg:45rem;
6
+ --cx-ui-popup-min:12.5rem;--cx-ui-popup-max:22.5rem;--cx-ui-menu-max:20rem;--cx-ui-tooltip-max:17.5rem;
7
+ --cx-ui-dialog-body-max:70dvh;--cx-ui-sheet-max:90dvh;--cx-ui-viewport-block:100dvh;--cx-ui-viewport-inline:100dvw;
8
+ }
9
+ }
10
+ @layer hfx.components{
11
+ :where(.cx-tabs,.cx-stepper-host,.cx-dialog,.cx-drawer,.cx-popover,.cx-menu,.cx-tooltip,[data-cx-open]){box-sizing:border-box;font-family:var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);font-size:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem));color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));}
12
+ :where(.cx-tabs,.cx-stepper-host,.cx-dialog,.cx-drawer,.cx-popover,.cx-menu) *,:where(.cx-tabs,.cx-stepper-host,.cx-dialog,.cx-drawer,.cx-popover,.cx-menu) *::before{box-sizing:border-box;}
13
+ .cx-visually-hidden{position:absolute;inline-size:var(--hfx-border-width,1px);block-size:var(--hfx-border-width,1px);padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;}
14
+ :where(.cx-tabs,.cx-stepper-host,.cx-dialog,.cx-drawer,.cx-popover,.cx-menu) :focus-visible,[data-cx-open]: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);}
15
+ .cx-dialog,.cx-drawer,.cx-popover{padding:0;border:var(--hfx-border-width,1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));background:var(--hfx-color-surface-raised,light-dark(#ffffff,#1e2126));box-shadow:var(--hfx-elevation-3,0 2px 4px rgba(22,24,28,.06),0 16px 36px -16px rgba(22,24,28,.28));overflow:hidden;}
16
+ .cx-dialog[open]{display:flex;flex-direction:column;max-block-size:calc(var(--cx-ui-viewport-block) - var(--hfx-space-4,1rem) * 2);}
17
+ .cx-dialog{inline-size:min(var(--cx-ui-dialog-md),calc(100% - var(--hfx-space-4,1rem) * 2));max-inline-size:none;}
18
+ .cx-dialog[data-size="sm"]{inline-size:min(var(--cx-ui-dialog-sm),calc(100% - var(--hfx-space-4,1rem) * 2));}
19
+ .cx-dialog[data-size="lg"]{inline-size:min(var(--cx-ui-dialog-lg),calc(100% - var(--hfx-space-4,1rem) * 2));}
20
+ :is(.cx-dialog,.cx-drawer)::backdrop{background:var(--hfx-color-overlay,light-dark(rgba(22,24,28,0.42),rgba(0,0,0,0.66)));}
21
+ :is(.cx-dialog,.cx-drawer,.cx-popover) [data-hfx-part="header"]{display:flex;flex:none;align-items:center;gap:var(--hfx-space-3,0.75rem);min-block-size:var(--hfx-card-header-height,calc(52px - var(--cx-compact,0) * 8px));padding:var(--hfx-space-4,1rem) var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));border-block-end:var(--hfx-border-width,1px) solid transparent;}
22
+ :is(.cx-dialog,.cx-drawer,.cx-popover) [data-hfx-part="title"]{flex:1;margin:0;font-family:var(--hfx-font-display,"Segoe UI Variable Display","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);font-size:var(--hfx-type-heading-size,0.9375rem);font-weight:var(--hfx-weight-semibold,600);line-height:var(--hfx-type-heading-line,1.4);}
23
+ :is(.cx-dialog,.cx-drawer,.cx-popover) [data-hfx-part="body"]{flex:1;overflow:auto;overscroll-behavior:contain;min-block-size:0;padding:var(--hfx-card-padding-y,calc(16px - var(--cx-compact,0) * 4px)) var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));max-block-size:var(--cx-ui-dialog-body-max);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));font-size:var(--hfx-type-small-size,0.8125rem);line-height:var(--hfx-type-small-line,1.4);}
24
+ :is(.cx-dialog,.cx-drawer,.cx-popover) [data-hfx-part="footer"]{display:flex;flex:none;justify-content:flex-end;gap:var(--hfx-space-2,0.5rem);padding:var(--hfx-space-3,0.75rem) var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));border-block-start:var(--hfx-border-width,1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
25
+ :is(.cx-dialog,.cx-drawer)[data-scrolled="true"] [data-hfx-part="header"]{border-block-end-color:var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
26
+ .cx-overlay-close{flex:none;inline-size:var(--hfx-control-height-sm,calc(28px - var(--cx-compact,0) * 4px));min-block-size:var(--hfx-control-height-sm,calc(28px - var(--cx-compact,0) * 4px));padding:0;background:transparent;border-color:transparent;font-size:0;}
27
+ .cx-overlay-close::before{content:"\00d7" / "";font-size:var(--hfx-icon-lg,20px);line-height:1;}
28
+ .cx-drawer{position:fixed;inset:0 0 0 auto;margin:0;inline-size:min(var(--cx-ui-drawer-md),100%);max-inline-size:none;block-size:var(--cx-ui-viewport-block);max-block-size:none;border-radius:var(--hfx-radius-none,0);}
29
+ .cx-drawer[open]{display:flex;flex-direction:column;}
30
+ .cx-drawer [data-hfx-part="body"]{flex:1;max-block-size:none;}
31
+ .cx-drawer[data-size="sm"]{inline-size:min(var(--cx-ui-drawer-sm),100%);}
32
+ .cx-drawer[data-size="lg"]{inline-size:min(var(--cx-ui-drawer-lg),100%);}
33
+ .cx-drawer{z-index:var(--hfx-z-drawer,1100);}
34
+ .cx-drawer[data-side="start"]{inset-inline-start:0;inset-inline-end:auto;}
35
+ .cx-drawer[data-side="end"]{inset-inline-start:auto;inset-inline-end:0;}
36
+ .cx-drawer[data-side="bottom"]{inset-block-start:auto;inset-block-end:0;inline-size:100%;block-size:auto;max-block-size:var(--cx-ui-sheet-max);border-start-start-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));border-start-end-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));}
37
+ .cx-drawer[data-side="bottom"]::before{content:"";display:block;flex:none;inline-size:var(--hfx-space-6,2rem);block-size:var(--hfx-space-1,0.25rem);margin:var(--hfx-space-2,0.5rem) auto 0;background:var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));border-radius:var(--hfx-radius-pill,999px);}
38
+ .cx-drawer[data-phone="true"]{inset:0;inline-size:100%;block-size:var(--cx-ui-viewport-block);max-block-size:none;border-radius:var(--hfx-radius-none,0);}
39
+ .cx-drawer[data-phone="true"] [data-hfx-part="header"]{padding-block:var(--hfx-space-1,0.25rem);}
40
+ .cx-drawer[data-phone="true"] [data-hfx-part="header"]:has(> :nth-child(4)){padding-block:var(--hfx-space-3,0.75rem);flex-wrap:wrap;justify-content:flex-start;gap:var(--hfx-space-2,0.5rem);}
41
+ .cx-drawer[data-phone="true"] [data-hfx-part="header"]:has(> :nth-child(4)) > button{flex:none;}
42
+ .cx-drawer[data-phone="true"] [data-hfx-part="header"]:has(> :nth-child(4)) > :first-child{flex:1 0 100%;min-inline-size:0;}
43
+ .cx-drawer[data-phone="true"] [data-hfx-part="header"]:has(> :nth-child(4)) [data-hfx-part="title"]{inline-size:100%;}
44
+ .cx-drawer[data-phone="true"] [data-hfx-part="body"]{padding-block-start:var(--hfx-space-1,0.25rem);}
45
+ .cx-drawer[data-phone="true"] [data-hfx-part="body"] > :first-child{margin-block-start:0;}
46
+ :is(.cx-dialog,.cx-drawer)[data-phone="true"]{--cx-ui-touch-target:calc(var(--hfx-space-5,1.5rem) + var(--hfx-space-6,2rem));}
47
+ :is(.cx-dialog,.cx-drawer)[data-phone="true"] :is(.cx-button,.cx-btn,.cx-ui-button,.cx-overlay-close){min-block-size:var(--cx-ui-touch-target);min-inline-size:var(--cx-ui-touch-target);}
48
+ .cx-dialog[data-phone="true"]{position:fixed;inset:auto 0 0;margin:0;inline-size:100%;max-block-size:var(--cx-ui-viewport-block);border-end-start-radius:var(--hfx-radius-none,0);border-end-end-radius:var(--hfx-radius-none,0);}
49
+ .cx-popover{position:fixed;inset:auto;margin:var(--hfx-space-1-5,6px);min-inline-size:var(--cx-ui-popup-min);max-inline-size:min(var(--cx-ui-popup-max),calc(var(--cx-ui-viewport-inline) - var(--hfx-space-4,1rem) * 2));max-block-size:calc(var(--cx-ui-viewport-block) - var(--hfx-space-4,1rem) * 2);box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));z-index:var(--hfx-z-popover,1000);}
50
+ .cx-popover [data-hfx-part="header"]{min-block-size:0;padding:var(--hfx-space-3,0.75rem) var(--hfx-space-4,1rem) var(--hfx-space-1,0.25rem);}
51
+ .cx-popover [data-hfx-part="body"]{padding:var(--hfx-space-1,0.25rem) var(--hfx-space-4,1rem) var(--hfx-space-3,0.75rem);}
52
+ .cx-tooltip{position:fixed;inset:auto;margin:var(--hfx-space-1-5,6px);max-inline-size:var(--cx-ui-tooltip-max);padding:var(--hfx-space-1,0.25rem) var(--hfx-space-2,0.5rem);border-radius:var(--hfx-radius-sm,4px);border:0;background:var(--hfx-color-surface-inverse,light-dark(#16181c,#f2f3f5));color:var(--hfx-color-text-inverse,light-dark(#ffffff,#0c0d10));font-size:var(--hfx-type-caption-size,0.75rem);line-height:var(--hfx-type-caption-line,1.35);box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));z-index:var(--hfx-z-tooltip,1300);overflow:visible;}
53
+ .cx-tooltip::after{content:"";position:absolute;inline-size:var(--hfx-space-2,0.5rem);block-size:var(--hfx-space-2,0.5rem);background:inherit;transform:rotate(45deg);inset-inline-start:calc(50% - var(--hfx-space-1,0.25rem));inset-block-start:calc(-1 * var(--hfx-space-1,0.25rem));}
54
+ .cx-tooltip[data-side="top"]::after{inset-block-start:auto;inset-block-end:calc(-1 * var(--hfx-space-1,0.25rem));}
55
+ .cx-tooltip[data-side="left"]::after{inset-inline-start:auto;inset-inline-end:calc(-1 * var(--hfx-space-1,0.25rem));inset-block-start:calc(50% - var(--hfx-space-1,0.25rem));}
56
+ .cx-tooltip[data-side="right"]::after{inset-inline-start:calc(-1 * var(--hfx-space-1,0.25rem));inset-block-start:calc(50% - var(--hfx-space-1,0.25rem));}
57
+ :where(.cx-dialog,.cx-drawer,.cx-popover,.cx-tooltip)[hidden]{display:none!important;}
58
+ @media (prefers-reduced-motion:no-preference){
59
+ :is(.cx-dialog,.cx-drawer,.cx-popover,.cx-tooltip){transition:opacity var(--hfx-motion-duration-fast,120ms) var(--hfx-motion-easing-exit,cubic-bezier(.4,0,1,1)),transform var(--hfx-motion-duration-fast,120ms) var(--hfx-motion-easing-exit,cubic-bezier(.4,0,1,1)),display var(--hfx-motion-duration-fast,120ms) allow-discrete,overlay var(--hfx-motion-duration-fast,120ms) allow-discrete;}
60
+ :is(.cx-dialog,.cx-popover,.cx-tooltip)[data-state="closed"]{opacity:0;transform:scale(.98);}
61
+ :is(.cx-dialog,.cx-drawer,.cx-popover,.cx-tooltip)[data-state="open"]{opacity:1;transform:none;}
62
+ .cx-drawer[data-state="closed"]{transform:translateX(100%);}
63
+ .cx-drawer[data-side="start"][data-state="closed"],.cx-drawer[data-side="end"]:dir(rtl)[data-state="closed"]{transform:translateX(-100%);}
64
+ .cx-drawer[data-side="start"]:dir(rtl)[data-state="closed"]{transform:translateX(100%);}
65
+ .cx-drawer:is([data-side="bottom"],[data-phone="true"])[data-state="closed"],.cx-dialog[data-phone="true"][data-state="closed"]{transform:translateY(100%);}
66
+ :is(.cx-dialog,.cx-drawer)::backdrop{transition:opacity var(--hfx-motion-duration-base,200ms) var(--hfx-motion-easing-standard,cubic-bezier(.2,0,0,1)),display var(--hfx-motion-duration-fast,120ms) allow-discrete,overlay var(--hfx-motion-duration-fast,120ms) allow-discrete;}
67
+ :is(.cx-dialog,.cx-drawer)[data-state="closed"]::backdrop{opacity:0;}
68
+ .cx-dialog[open],.cx-drawer[open],.cx-popover:popover-open{animation:cx-ui-appear var(--hfx-motion-duration-base,200ms) var(--hfx-motion-easing-enter,cubic-bezier(0,0,.2,1));}
69
+ .cx-drawer[open]{animation:cx-ui-slide-end var(--hfx-motion-duration-slow,320ms) var(--hfx-motion-easing-enter,cubic-bezier(0,0,.2,1));}
70
+ .cx-drawer[data-side="start"][open],.cx-drawer[data-side="end"]:dir(rtl)[open]{animation-name:cx-ui-slide-start;}
71
+ .cx-drawer[data-side="start"]:dir(rtl)[open]{animation-name:cx-ui-slide-end;}
72
+ .cx-drawer[data-side="bottom"][open],.cx-drawer[data-phone="true"][open],.cx-dialog[data-phone="true"][open]{animation-name:cx-ui-slide-bottom;}
73
+ @keyframes cx-ui-appear{from{opacity:0;transform:scale(.98);}to{opacity:1;transform:none;}}
74
+ @keyframes cx-ui-slide-end{from{transform:translateX(100%);}to{transform:none;}}
75
+ @keyframes cx-ui-slide-start{from{transform:translateX(-100%);}to{transform:none;}}
76
+ @keyframes cx-ui-slide-bottom{from{transform:translateY(100%);}to{transform:none;}}
77
+ }
78
+ @media print{:where(.cx-dialog,.cx-drawer,.cx-popover,.cx-tooltip,.cx-menu){display:none!important;}}
79
+ }