@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
@@ -0,0 +1,35 @@
1
+ .cx-stack-host > .cx-grid{display:none;}
2
+ .cx-stack{min-width:0;min-height:0;flex:1 1 auto;overflow:auto;padding:var(--hfx-space-3,0.75rem);color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));font:var(--hfx-weight-regular,400) var(--hfx-type-body-size,0.875rem) var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);}
3
+ .cx-stack-title-heading{font:var(--hfx-weight-semibold,600) var(--hfx-type-heading-size,0.9375rem) var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);line-height:var(--hfx-type-heading-line,1.4);margin:0 0 var(--hfx-space-4,1rem);}
4
+ .cx-stack-winner{border:var(--hfx-border-width,1px) solid var(--hfx-color-status-good-fg,light-dark(#177345,#4cc78a));border-radius:var(--hfx-radius-container,var(--hfx-radius-lg,10px));background:var(--hfx-color-status-good-bg,light-dark(#e2f0e9,#1f362f));padding:calc(var(--hfx-space-1,0.25rem)*3.5) var(--hfx-space-4,1rem);}
5
+ .cx-stack-winner h3{color:var(--hfx-color-status-good-fg,light-dark(#177345,#4cc78a));font-size:var(--hfx-type-caption-size,0.75rem);margin:0 0 var(--hfx-space-1-5,6px);}
6
+ .cx-stack-title{height:auto;text-align:start;white-space:normal;overflow-wrap:anywhere;}
7
+ .cx-stack-title:hover{text-decoration:underline;}
8
+ .cx-stack-order{font-size:var(--hfx-type-body-size,0.875rem);margin:var(--hfx-space-5,1.5rem) 0 calc(var(--hfx-space-1,0.25rem)*2.5);}
9
+ .cx-stack-layers{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:calc(var(--hfx-space-1,0.25rem)*2.5);}
10
+ .cx-stack-layer{display:flex;gap:var(--hfx-space-3,0.75rem);padding:calc(var(--hfx-space-1,0.25rem)*3.5);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-container,var(--hfx-radius-lg,10px));background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));break-inside:avoid;}
11
+ .cx-stack-number{display:grid;place-items:center;flex:0 0 calc(var(--hfx-space-1,0.25rem)*7);align-self:start;min-height:calc(var(--hfx-space-1,0.25rem)*7);border:var(--hfx-border-width,1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));border-radius:50%;font-size:var(--hfx-type-caption-size,0.75rem);font-variant-numeric:tabular-nums;color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));}
12
+ .cx-stack-body{min-width:0;flex:1;}
13
+ .cx-stack-selected{border-color:var(--hfx-color-status-good-fg,light-dark(#177345,#4cc78a));}
14
+ .cx-stack-filtered{border-style:dashed;}
15
+ .cx-stack-reason{margin:var(--hfx-space-1-5,6px) 0;line-height:var(--hfx-type-body-line,1.5);overflow-wrap:anywhere;white-space:pre-wrap;}
16
+ .cx-stack-context,.cx-stack-empty{color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));margin:var(--hfx-space-1-5,6px) 0;font-size:var(--hfx-type-caption-size,0.75rem);overflow-wrap:anywhere;}
17
+ .cx-stack-badges{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hfx-space-1,0.25rem);margin-top:var(--hfx-space-2,0.5rem);}
18
+ .cx-stack-badges[hidden]{display:none;}
19
+ @media (max-width: 640px){
20
+ .cx-stack{padding:calc(var(--hfx-space-1,0.25rem)*2.5);}
21
+ .cx-stack-layer{padding:var(--hfx-space-3,0.75rem) calc(var(--hfx-space-1,0.25rem)*2.5);gap:calc(var(--hfx-space-1,0.25rem)*2.5);}
22
+ .cx-stack-title{min-height:calc(var(--hfx-space-1,0.25rem)*9);}
23
+ .cx-stack-winner{padding:var(--hfx-space-3,0.75rem);}
24
+ }
25
+ @media print{
26
+ .cx-stack-host,.cx-stack{height:auto !important;max-height:none !important;overflow:visible !important;}
27
+ .cx-stack-host > .cx-grid{display:none !important;}
28
+ .cx-stack-layers{display:block;}
29
+ .cx-stack-layer{margin-bottom:calc(var(--hfx-space-1,0.25rem)*2.5);}
30
+ .cx-stack-title{color:inherit;text-decoration:none;}
31
+ .cx-stack-winner,.cx-stack-layer{break-inside:avoid;}
32
+ }
33
+ .cx-stack .cx-stack-title{color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));font-weight:var(--hfx-weight-semibold,600);font-size:var(--hfx-type-body-size,0.875rem);line-height:var(--hfx-type-body-line,1.5);padding:0;border:0;border-radius:0;background:transparent;box-shadow:none;justify-content:flex-start;min-height:0;}
34
+ .cx-stack .cx-stack-title:hover{color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));background:transparent;text-decoration:underline;}
35
+ .cx-stack .cx-stack-title: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);}
@@ -0,0 +1,24 @@
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"e29298edc07edb6d",install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,fill,cellValue,cellText,badgeElement,applyTone,toneOf,PROTOCOL}=context;const STACK_TEXT={stackWinner:"Winner",stackEnforced:"Enforced",stackFiltered:"Filtered",stackEmpty:"No layers to display.",stackOrder:"Processing order",stackTruncated:"{shown} of {total} layers shown in processing order; the winning layer is always included."};const stackHasText=value=>typeof value==="string"&&/[^\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]/.test(value);
2
+ const stackObject=(value,keys)=>!!value&&typeof value==="object"&&!Array.isArray(value)&&Object.keys(value).every(key=>keys.includes(key));function stackIdentifier(value){if(!stackHasText(value))return false;for(let index=0;index<value.length;index++){const code=value.charCodeAt(index);if(code>=0xd800&&code<=0xdbff){const next=value.charCodeAt(++index);if(!(next>=0xdc00&&next<=0xdfff))return false}
3
+ else if(code>=0xdc00&&code<=0xdfff)return false}
4
+ return true}
5
+ function stackSettings(grid){grid.validateStackSource();const input=grid.view.stack,known=id=>grid.columns.some(column=>column.id===id);if(!stackObject(input,["titleColumn","layers"])||
6
+ input.titleColumn!==undefined&&(!stackIdentifier(input.titleColumn)||!known(input.titleColumn))||
7
+ !Array.isArray(input.layers)||input.layers.length>1000)
8
+ throw new Error("CanopyX: a stack needs inline records, stable identities, known title columns and at most 1,000 layers.");const titleColumn=input.titleColumn||grid.columns.find(column=>column.rowHeader)?.id||grid.columns.find(column=>!column.hidden)?.id;if(!titleColumn)throw new Error("CanopyX: a stack needs a title column.");const records=new Map((grid.view.rows||[]).map(row=>[row.id,row])),ids=new Set();let winners=0;for(const layer of input.layers){if(!stackObject(layer,["id","record","reason","label","winner","enforced","filtered","badges"])||
9
+ !stackIdentifier(layer.id)||!stackIdentifier(layer.record)||ids.has(layer.id)||!records.has(layer.record)||
10
+ !stackHasText(layer.reason)||layer.label!==undefined&&typeof layer.label!=="string"||
11
+ ["winner","enforced","filtered"].some(name=>layer[name]!==undefined&&typeof layer[name]!=="boolean")||
12
+ layer.badges!==undefined&&(!Array.isArray(layer.badges)||layer.badges.some(badge=>!stackObject(badge,["text","tone","title"])||typeof badge.text!=="string"||!badge.text||
13
+ badge.tone!==undefined&&(typeof badge.tone!=="string"||!/^[a-z][a-z0-9-]{0,31}$/.test(badge.tone) || badge.tone.endsWith("-bg")) || badge.title !== undefined && typeof badge.title !== "string")))
14
+ throw new Error("CanopyX: stack layers need unique ids, existing records, reasons and valid badges.");ids.add(layer.id);if(layer.winner)winners++;if(layer.winner&&layer.filtered)throw new Error("CanopyX: a filtered stack layer cannot be the winner.")}
15
+ if(input.layers.length&&winners!==1)throw new Error("CanopyX: a nonempty stack needs exactly one host-supplied winner.");return{...input,titleColumn,records}}
16
+ Object.assign(DataGrid.prototype,{validateStackSource(){if(this.view.source.kind!=="inline"||this.opts.source||this.view.rowIdentity==="ordinal")
17
+ throw new Error("CanopyX: a stack requires stable inline records.")},startStack(){if(this.stack)return;const settings=stackSettings(this),labels={};for(const[key,text]of Object.entries(STACK_TEXT))labels[key]=this.opts.labels?.[key]||this.view.labels?.[key]||text;this.stack={settings,labels};const previousHidden=this.grid.hidden,pagerHidden=this.pager?.hidden;const toolbarHidden=this.toolbar.hidden,originalMaxHeight=this.fitInline??this.host.style.maxHeight;this.host.style.maxHeight=originalMaxHeight;this.toolbar.hidden=true;this.host.classList.add("cx-stack-host");this.grid.hidden=true;if(this.pager)this.pager.hidden=true;this.stackFrame=h("section","cx-stack");this.stackFrame.setAttribute("aria-label",this.view.label);this.host.insertBefore(this.stackFrame,this.grid.nextSibling);const repaint=()=>{try{this.stack.settings=stackSettings(this);if(this.stack.failure){this.stack.failure=false;this.setNotice("",false)}
18
+ this.stackPaint()}catch(error){this.stack.settings={...this.stack.settings,records:new Map()};this.stack.failure=true;this.stackFrame.replaceChildren();this.setNotice(error.message,true);this.emit("error",{error})}};this.host.addEventListener("canopyx:format",repaint,{signal:this.lifetime.signal});this.host.addEventListener("canopyx:rowsChanged",repaint,{signal:this.lifetime.signal});this.lifetime.signal.addEventListener("abort",()=>{this.stackFrame.remove();this.host.classList.remove("cx-stack-host");this.grid.hidden=previousHidden;this.toolbar.hidden=toolbarHidden;this.host.style.maxHeight=originalMaxHeight;if(this.pager)this.pager.hidden=pagerHidden},{once:true});this.stackPaint()}});function stackRecordTemplate(text){const button=h("button","cx-btn cx-stack-title");button.type="button";setText(button,text);return button}
19
+ function stackBadgesTemplate(layer,labels){const badges=h("div","cx-stack-badges");if(layer.winner)badges.appendChild(badgeElement({text:labels.stackWinner,tone:"success"}));if(layer.enforced)badges.appendChild(badgeElement({text:labels.stackEnforced,tone:"info"}));if(layer.filtered)badges.appendChild(badgeElement({text:labels.stackFiltered,tone:"neutral"}));for(const badge of layer.badges||[])badges.appendChild(badgeElement(badge));badges.hidden=!badges.childElementCount;return badges}
20
+ function stackFrameTemplate(stack,frame,layers,recordButton,attachLayer){const stackBadges=layer=>stackBadgesTemplate(layer,stack.labels);const viewTitle=h("h2","cx-stack-title-heading");setText(viewTitle,this.view.label);frame.appendChild(viewTitle);if(!layers.length){const empty=h("p","cx-stack-empty");setText(empty,stack.labels.stackEmpty);frame.appendChild(empty);return null}
21
+ const winner=layers.find(layer=>layer.winner),summary=h("header","cx-stack-winner"),summaryLabel=h("h3"),summaryTitle=recordButton(winner);applyTone(summary,"cx-stack-winner",toneOf("success"));setText(summaryLabel,stack.labels.stackWinner);summary.append(summaryLabel,summaryTitle);if(winner.label){const label=h("p","cx-stack-context");setText(label,winner.label);summary.appendChild(label)}
22
+ const summaryReason=h("p","cx-stack-reason");setText(summaryReason,winner.reason);summary.append(summaryReason,stackBadges(winner));frame.appendChild(summary);const heading=h("h3","cx-stack-order"),list=h("ol","cx-stack-layers");heading.id=this.id+"-stack-order";setText(heading,stack.labels.stackOrder);list.setAttribute("aria-labelledby",heading.id);list.setAttribute("role","list");frame.append(heading,list);layers.forEach((layer,index)=>{const item=h("li","cx-stack-layer"),number=h("span","cx-stack-number"),body=h("div","cx-stack-body");item.dataset.cxStackLayer=layer.id;item.dataset.cxStackRecord=layer.record;item.classList.toggle("cx-stack-filtered",!!layer.filtered);item.classList.toggle("cx-stack-selected",!!layer.winner);number.setAttribute("aria-hidden","true");setText(number,String(index+1));const title=recordButton(layer),reason=h("p","cx-stack-reason");reason.id=this.id+"-stack-reason-"+index;title.setAttribute("aria-describedby",reason.id);setText(reason,layer.reason);body.appendChild(title);if(layer.label){const label=h("p","cx-stack-context");setText(label,layer.label);body.appendChild(label)}
23
+ body.append(reason,stackBadges(layer));item.append(number,body);list.appendChild(item);attachLayer(title,list,index)});return list}
24
+ Object.assign(DataGrid.prototype,{stackTitle(layer){const stack=this.stack,row=stack.settings.records.get(layer.record),column=this.columns.find(column=>column.id===stack.settings.titleColumn);return cellText(row.cells[column.id],column,this.fmt)||row.id},stackRecordButton(layer){const button=stackRecordTemplate(this.stackTitle(layer));button.addEventListener("click",()=>this.openRecord(layer.record,{returnFocus:button}).catch(error=>{this.setNotice(error.message,true);this.emit("error",{error})}));return button},stackPaint(){const stack=this.stack,frame=this.stackFrame,layers=stack.settings.layers;const held=document.activeElement,focusLayer=frame.contains(held)?held.closest("[data-cx-stack-layer]")?.dataset.cxStackLayer:null;frame.replaceChildren();const list=stackFrameTemplate.call(this,stack,frame,layers,layer=>this.stackRecordButton(layer),(title,list,index)=>{title.addEventListener("keydown",event=>{if(event.altKey||event.ctrlKey||event.metaKey||event.shiftKey)return;const next=event.key==="Home"?0:event.key==="End"?layers.length-1:event.key==="ArrowDown"?Math.min(layers.length-1,index+1):event.key==="ArrowUp"?Math.max(0,index-1):null;if(next!==null){event.preventDefault();list.children[next].querySelector("button").focus()}})});if(!list)return;if(focusLayer)[...list.children].find(item=>item.dataset.cxStackLayer===focusLayer)?.querySelector("button").focus({preventScroll:true})}});installed.add(context.DataGrid.prototype)}};(global.CanopyXParts||=[]).push(["stack",part])})(typeof window!=="undefined"?window:globalThis);
@@ -0,0 +1,18 @@
1
+ .cx-time-host{display:flex;flex-direction:column;min-height:0;box-sizing:border-box;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-container,var(--hfx-radius-lg,10px));background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));overflow:auto;}
2
+ .cx-time-host > .cx-matrix{flex:1 1 auto;min-height:0;max-height:none;border:0;border-radius:0;background:inherit;}
3
+ .cx-time{flex:none;font:var(--hfx-weight-regular,400) var(--hfx-type-body-size,0.875rem) var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);display:grid;gap:var(--hfx-space-2,0.5rem);padding:var(--hfx-space-4,1rem) 0;color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));min-inline-size:0;background:inherit;}
4
+ .cx-time-controls{display:flex;align-items:center;gap:var(--hfx-space-2,0.5rem);min-inline-size:0;}
5
+ .cx-time-button{flex:none;min-block-size:var(--hfx-control-height-lg,calc(44px - var(--cx-compact,0) * 8px));min-inline-size:var(--hfx-control-height-lg,calc(44px - var(--cx-compact,0) * 8px));}
6
+ .cx-time-button svg{inline-size:var(--hfx-icon-lg,20px);block-size:var(--hfx-icon-lg,20px);fill:none;stroke:currentColor;stroke-width:2;stroke-linejoin:round;}
7
+ .cx-time[data-playing="true"] .cx-time-button[aria-pressed="true"]{color:var(--hfx-color-accent-contrast,light-dark(#ffffff,#0c0d10));background:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));border-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
8
+ .cx-time-scrubber{position:relative;min-inline-size:0;padding-inline:var(--hfx-space-2,0.5rem);}
9
+ .cx-time-range{display:block;box-sizing:border-box;inline-size:100%;margin:0;accent-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));block-size:var(--hfx-control-height-sm,calc(28px - var(--cx-compact,0) * 4px));}
10
+ .cx-time-range:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
11
+ .cx-time-ticks{position:relative;block-size:var(--hfx-space-2,0.5rem);margin-inline:var(--hfx-space-2,0.5rem);}
12
+ .cx-time-ticks i{position:absolute;inline-size:var(--hfx-border-width,1px);block-size:var(--hfx-space-1-5,6px);background:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));}
13
+ .cx-time-position{color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-variant-numeric:tabular-nums;font-size:var(--hfx-type-caption-size,0.75rem);}
14
+ .cx-time-stamp{font-weight:var(--hfx-weight-semibold,600);line-height:var(--hfx-type-body-line,1.5);margin-inline-start:var(--hfx-space-2,0.5rem);overflow-wrap:anywhere;}
15
+ .cx-time-reduced{margin:0;color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-size:var(--hfx-type-caption-size,0.75rem);}
16
+ .cx-time [hidden]{display:none;}
17
+ @media(max-width:480px){.cx-time{padding:var(--hfx-space-3,0.75rem) 0;}.cx-time-controls{flex-wrap:wrap;}.cx-time-stamp{flex-basis:100%;margin-inline-start:0;}}
18
+ @media print{.cx-time-host{border:0;}.cx-time{padding:0;}.cx-time-controls .cx-time-button,.cx-time-scrubber,.cx-time-reduced{display:none;}.cx-time-stamp{display:block;color:inherit;}}
@@ -0,0 +1,27 @@
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"5516099a165cc345",install(context){if(installed.has(context.TIME_SLIDER_IMPL))return;const{TIME_SLIDER_IMPL,h,setText,fill,PROTOCOL}=context;function humanTimeFormat(lang,local,utcTemplate){const formatter=new Intl.DateTimeFormat(lang||undefined,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:local?undefined:"UTC",...(local?{timeZoneName:"short"}:{})});return{format(value){const parts=formatter.formatToParts(new Date(value));const text=parts.map((part,index)=>part.type==="literal"&&parts[index+1]?.type==="timeZoneName"?part.value.replace(/\s/g,"\u00a0"):part.value).join("");
2
+ return local?text:fill(utcTemplate||"{time} UTC",{time:text}).replace(/ (\S+)$/,"\u00a0$1");
3
+ }}}
4
+ const TIME_TEXT={timePlay:"Play",timePause:"Pause",timePrevious:"Previous snapshot",timeNext:"Next snapshot",timePosition:"Snapshot {index} of {count}",timeFrame:"Snapshot at {time}",timeReducedMotion:"Timed playback is off because reduced motion is enabled. Step through snapshots manually."};function timeFail(message){throw new Error("CanopyX: the time slider is not valid: "+message+".")}
5
+ function timeKeys(value,names,what){if(!value||typeof value!=="object"||Array.isArray(value))timeFail(what+" must be an object");for(const name of Object.keys(value))if(!names.includes(name))timeFail(what+" has the unknown property '"+name+"'")}
6
+ function timeModel(source,kind,validate){const input=source.timeSlider;timeKeys(input,["interval","initial","snapshots"],"settings");const interval=input.interval===undefined?1000:input.interval;if(!Number.isInteger(interval)||interval<100||interval>60000)timeFail("interval must be 100 to 60000 milliseconds");if(!Array.isArray(input.snapshots)||!input.snapshots.length||input.snapshots.length>500)timeFail("supply 1 to 500 snapshots");let previous=-Infinity;const snapshots=input.snapshots.map(item=>{timeKeys(item,["at","label","view"],"snapshot");if(typeof item.at!=="string"||!/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d{1,7})?(?:Z|[+-]\d\d:\d\d)$/.test(item.at)) timeFail("snapshot time needs an ISO timestamp with a zone");
7
+ const parts=item.at.match(/\d+/g).map(Number), [year, month, day, hour, minute, second] = parts;
8
+ const zone=item.at.match(/([+-])(\d\d):(\d\d)$/);
9
+ const days=month===2?year%4===0&&(year%100!==0||year%400===0)?29:28:[4,6,9,11].includes(month)?30:31;if(!year||month<1||month>12||day<1||day>days||hour>23||minute>59||second>59||
10
+ zone&&(+zone[2]>14||+zone[3]>59||+zone[2]===14&&+zone[3]!==0))timeFail("snapshot time is outside the supported date range");const instant=Date.parse(item.at);if(!Number.isFinite(instant)||instant<=previous)timeFail("snapshot times must increase strictly");previous=instant;if(item.label!==undefined&&(typeof item.label!=="string"||!/\S/.test(item.label) || item.label.length > 200)) timeFail("snapshot label must be visible text of at most 200 characters");
11
+ if(!item.view||item.view.type!==kind||item.view.id!==source.id||Object.hasOwn(item.view,"timeSlider"))timeFail("snapshots need the same view type and id, without nested time sliders");validate(item.view);const view=JSON.parse(JSON.stringify(item.view));return Object.freeze({at:item.at,label:item.label,view})});const initial=input.initial===undefined?snapshots.length-1:input.initial;if(!Number.isInteger(initial)||initial<0||initial>=snapshots.length)timeFail("initial must identify a supplied snapshot");return{interval,initial,snapshots}}
12
+ function timeLabels(...sources){const labels={...TIME_TEXT};for(const source of sources)for(const[key,value]of Object.entries(source||{})){if(!Object.hasOwn(labels,key)){if(/^time[A-Z]/.test(key)) timeFail("unknown label '" + key + "'"); continue; }
13
+ if(typeof value!=="string"||!/\S/.test(value)) timeFail("label '" + key + "' needs visible text");
14
+ labels[key]=value}
15
+ return labels}
16
+ function timeIcon(button,playing,direction){const svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),path=document.createElementNS(svg.namespaceURI,"path");svg.setAttribute("viewBox","0 0 24 24");svg.setAttribute("aria-hidden","true");path.setAttribute("d",direction===-1?"M7 5V19M18 5L9 12L18 19Z":direction===1?"M17 5V19M6 5L15 12L6 19Z":playing?"M8 5V19M16 5V19":"M7 4L20 12L7 20Z");svg.appendChild(path);button.replaceChildren(svg)}
17
+ function timeControlsTemplate(model,labels,source,hostLabels,hostLang){const root=h("section","cx-time"),controls=h("div","cx-time-controls"),range=h("input","cx-time-range");const stamp=h("div","cx-time-stamp"),position=h("span","cx-time-position"),reduced=h("p","cx-time-reduced");const scrubber=h("div","cx-time-scrubber"),ticks=h("div","cx-time-ticks");ticks.setAttribute("aria-hidden","true");const formatter=humanTimeFormat(source.lang||hostLang||document.documentElement.lang,source.timeZone==="local",hostLabels?.changeUtcTime??source.labels?.changeUtcTime);const button=text=>{const result=h("button","cx-btn icon cx-time-button");result.type="button";result.setAttribute("aria-label",text);result.title=text;return result};const previous=button(labels.timePrevious),play=button(labels.timePlay),next=button(labels.timeNext);timeIcon(previous,false,-1);timeIcon(next,false,1);range.type="range";range.min="0";range.max=String(model.snapshots.length-1);range.step="1";range.setAttribute("aria-label",labels.timePosition.replace("{index}","").replace("{count}",String(model.snapshots.length)).trim());stamp.setAttribute("aria-live","polite");root.setAttribute("aria-label",labels.timeFrame.replace("{time}","").trim());setText(reduced,labels.timeReducedMotion);for(const[index,item]of model.snapshots.entries()){const tick=h("i");tick.style.insetInlineStart=(model.snapshots.length===1?0:index*100 / (model.snapshots.length - 1)) + "%";
18
+ tick.title=formatter.format(new Date(item.at));ticks.appendChild(tick)}
19
+ controls.append(previous,play,next,stamp);scrubber.append(range,ticks);root.append(controls,scrubber,position,reduced);return{root,range,stamp,position,reduced,previous,play,next,formatter}}
20
+ function timeStateTemplate(elements,model,labels,index,playing,reducedMotion){const{root,range,stamp,position,reduced,previous,play,next,formatter}=elements;const item=model.snapshots[index],text=fill(labels.timePosition,{index:index+1,count:model.snapshots.length});const time=formatter.format(new Date(item.at));range.value=String(index);range.setAttribute("aria-valuetext",text+": "+time);setText(position,text);setText(stamp,(item.label?item.label+" · ":"")+ fill(labels.timeFrame,{time}));previous.disabled=index===0;next.disabled=index===model.snapshots.length-1;play.disabled=reducedMotion||model.snapshots.length<2||!playing&&index===model.snapshots.length-1;root.dataset.playing=String(playing);play.setAttribute("aria-pressed",String(playing));const name=playing?labels.timePause:labels.timePlay;play.setAttribute("aria-label",name);play.title=name;timeIcon(play,playing);reduced.hidden=!reducedMotion}
21
+ function timeCreate(host,source,hostLabels,kind,validate,update){const model=timeModel(source,kind,validate),labels=timeLabels(source.labels,hostLabels);const lifetime=new AbortController(),signal=lifetime.signal,media=matchMedia("(prefers-reduced-motion: reduce)");const elements=timeControlsTemplate(model,labels,source,hostLabels,host.closest("[lang]")?.getAttribute("lang"));const{root,range,previous,play,next}=elements;const hadFrame=host.classList.contains("cx-time-host");host.classList.add("cx-time-host");let index=model.initial,playing=false,timer=null,disposed=false;const state=()=>Object.freeze({index,count:model.snapshots.length,at:model.snapshots[index].at,playing,reducedMotion:media.matches});const paint=()=>timeStateTemplate(elements,model,labels,index,playing,media.matches);const pause=()=>{playing=false;clearTimeout(timer);timer=null;if(!disposed)paint();return state()};const seek=target=>{if(disposed)throw new DOMException("Snapshot playback was destroyed.","AbortError");if(!Number.isInteger(target)||target<0||target>=model.snapshots.length)throw new RangeError("Snapshot index is outside the supplied history.");pause();update(model.snapshots[target].view);index=target;paint();return state()};const tick=()=>{timer=setTimeout(()=>{if(disposed||!playing)return;if(media.matches){pause();return}
22
+ try{update(model.snapshots[index+1].view);++index}
23
+ catch(error){pause();host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}));return}
24
+ if(index===model.snapshots.length-1)pause();else{paint();tick()}},model.interval)};const start=()=>{if(!disposed&&!playing&&!media.matches&&index<model.snapshots.length-1){playing=true;paint();tick()}return state()};previous.addEventListener("click",()=>seek(index-1),{signal});next.addEventListener("click",()=>seek(index+1),{signal});play.addEventListener("click",()=>playing?pause():start(),{signal});range.addEventListener("input",()=>seek(Number(range.value)),{signal});media.addEventListener("change",pause,{signal});window.addEventListener("beforeprint",pause,{signal});try{update(model.snapshots[index].view);paint();host.prepend(root)}
25
+ catch(error){lifetime.abort();root.remove();if(!hadFrame)host.classList.remove("cx-time-host");throw error}
26
+ return{play:start,pause,seek,step:(delta=1)=>{if(!Number.isInteger(delta))throw new RangeError("Snapshot step must be an integer.");return seek(Math.max(0,Math.min(model.snapshots.length-1,index+delta)))},getState:state,destroy:()=>{if(disposed)return;pause();disposed=true;lifetime.abort();root.remove();if(!hadFrame)host.classList.remove("cx-time-host")}}}
27
+ TIME_SLIDER_IMPL.create=timeCreate;installed.add(context.TIME_SLIDER_IMPL)}};(global.CanopyXParts||=[]).push(["time-slider",part])})(typeof window!=="undefined"?window:globalThis);
@@ -1,31 +1,31 @@
1
1
  /* Resource timeline: the resource tree at the start,the time header and lanes after it,sharing rows. */
2
2
  .cx-tl{--cx-tl-side-w:var(--cx-tl-side,280px);display:grid;grid-template-columns:var(--cx-tl-side-w) minmax(0,1fr);height:100%;min-height:0;}
3
3
  .cx-tl.cx-tl-solo{grid-template-columns:minmax(0,1fr);}
4
- .cx-tl-side{display:flex;flex-direction:column;min-width:0;min-height:0;border-inline-end:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
4
+ .cx-tl-side{display:flex;flex-direction:column;min-width:0;min-height:0;border-inline-end:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
5
5
  .cx-tl-side > .cx-tl-tree.cx-host{flex:1 1 auto;height:auto;min-height:0;border:0;border-radius:0;}
6
6
  .cx-tl-tree.cx-host > .cx-grid{overflow-y:hidden;overflow-x:scroll;border:0;border-radius:0;}
7
7
  .cx-tl-tree .cx-head{display:flex;flex-direction:column;justify-content:flex-end;box-sizing:border-box;height:var(--cx-tl-head-h,57px);}
8
8
  .cx-tl-tree .cx-tl-agg{justify-content:flex-end;font-variant-numeric:tabular-nums;color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
9
9
  .cx-tl-main{position:relative;min-width:0;min-height:0;overflow:scroll;overscroll-behavior:contain;}
10
- .cx-tl-head{position:sticky;top:0;z-index:7;height:var(--cx-tl-head-h,57px);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
10
+ .cx-tl-head{position:sticky;top:0;z-index:7;height:var(--cx-tl-head-h,57px);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-bottom:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
11
11
  .cx-tl-hrow{position:relative;height:var(--cx-size-28px);}
12
- .cx-tl-upper{border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
13
- .cx-tl-hcell{position:absolute;top:0;height:100%;display:flex;align-items:center;padding:0 var(--cx-size-6px);border-inline-start:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));font-size:var(--cx-size-12px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums;}
14
- .cx-tl-hcell.cx-tl-hupper{overflow:visible;font-size:var(--cx-size-13px);font-weight:600;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));}
12
+ .cx-tl-upper{border-bottom:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
13
+ .cx-tl-hcell{position:absolute;top:0;height:100%;display:flex;align-items:center;padding:0 var(--cx-size-6px);border-inline-start:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));font-size:var(--cx-size-12px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums;}
14
+ .cx-tl-hcell.cx-tl-hupper{overflow:visible;font-size:var(--cx-size-13px);font-weight:600;color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));}
15
15
  .cx-tl-hupper > .cx-tl-hlabel{position:sticky;inset-inline-start:var(--cx-size-6px);max-width:100%;overflow:hidden;text-overflow:ellipsis;}
16
16
  .cx-tl-hcell > .cx-tl-hlabel{min-width:0;overflow:hidden;text-overflow:ellipsis;}
17
- .cx-tl-hcell.cx-tl-weekend{background:color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 5%,transparent);}
18
- .cx-tl-range-labels{position:relative;height:var(--cx-size-20px);border-top:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
17
+ .cx-tl-hcell.cx-tl-weekend{background:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 5%,transparent);}
18
+ .cx-tl-range-labels{position:relative;height:var(--cx-size-20px);border-top:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
19
19
  .cx-tl-head:not(.cx-tl-has-ranges) > .cx-tl-range-labels{display:none;}
20
- .cx-tl-range-label{position:absolute;top:var(--cx-size-2px);height:var(--cx-size-16px);padding:0 var(--cx-size-6px);border-radius:var(--hfx-radius-sm,4px);background:color-mix(in srgb,var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7)) 14%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));font-size:var(--cx-size-11d5px);line-height:var(--cx-size-16px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
20
+ .cx-tl-range-label{position:absolute;top:var(--cx-size-2px);height:var(--cx-size-16px);padding:0 var(--cx-size-6px);border-radius:var(--hfx-radius-sm,4px);background:color-mix(in srgb,var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7)) 14%,var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c))));font-size:var(--cx-size-11d5px);line-height:var(--cx-size-16px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
21
21
  .cx-tl-canvas{position:relative;}
22
22
  .cx-tl-layer{position:absolute;inset-inline-start:0;top:0;width:100%;pointer-events:none;}
23
- .cx-tl-weekend-col{position:absolute;top:0;bottom:0;background:color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 3.5%,transparent);}
23
+ .cx-tl-weekend-col{position:absolute;top:0;bottom:0;background:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 3.5%,transparent);}
24
24
  .cx-tl-range{position:absolute;top:0;bottom:0;background:color-mix(in srgb,var(--cx-bg-tone) 9%,transparent);box-shadow:inset var(--cx-size-2px) 0 0 color-mix(in srgb,var(--cx-bg-tone) 50%,transparent);}
25
25
  :where(.cx-cal-rtl) .cx-tl-range{box-shadow:inset calc(-1 * var(--cx-size-2px)) 0 0 color-mix(in srgb,var(--cx-bg-tone) 50%,transparent);}
26
26
  .cx-tl-now{position:absolute;top:0;bottom:0;width:var(--cx-size-2px);margin-inline-start:calc(-1 * var(--cx-size-1px));background:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));z-index:1;}
27
- .cx-tl-lane{position:absolute;inset-inline-start:0;inset-inline-end:0;border-bottom:var(--cx-size-1px) solid color-mix(in srgb,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)) 70%,transparent);}
28
- .cx-tl-lane.cx-tl-group{background:color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 2.5%,transparent);}
27
+ .cx-tl-lane{position:absolute;inset-inline-start:0;inset-inline-end:0;border-bottom:var(--cx-size-1px) solid color-mix(in srgb,var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30))) 70%,transparent);}
28
+ .cx-tl-lane.cx-tl-group{background:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 2.5%,transparent);}
29
29
  .cx-tl-cell{position:absolute;top:0;bottom:0;pointer-events:none;outline:none;}
30
30
  .cx-tl-cell:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:calc(-1 * var(--cx-size-2px));z-index:5;}
31
31
  .cx-tl-cell[aria-selected="true"]{background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));}
@@ -43,15 +43,15 @@
43
43
  .cx-tl-lane .cx-cal-ev-lane.cx-tl-point.cx-tl-bare > .cx-cal-ev-title{display:none;}
44
44
  .cx-tl-shade{position:absolute;top:0;bottom:0;pointer-events:none;overflow:hidden;overflow:clip;}
45
45
  .cx-tl-shade > span{position:sticky;inset-inline-start:0;display:block;width:max-content;max-width:100%;box-sizing:border-box;padding:var(--cx-size-2px) var(--cx-size-6px);font-size:var(--cx-size-11px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
46
- .cx-tl-shade.cx-tl-off{background:color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 4.5%,transparent);}
47
- :is(.cx-tl-shade,.cx-tl-range).cx-tl-unavailable{background:repeating-linear-gradient(135deg,color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 9%,transparent) 0 var(--cx-size-6px),transparent var(--cx-size-6px) var(--cx-size-12px));box-shadow:none;}
46
+ .cx-tl-shade.cx-tl-off{background:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 4.5%,transparent);}
47
+ :is(.cx-tl-shade,.cx-tl-range).cx-tl-unavailable{background:repeating-linear-gradient(135deg,color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 9%,transparent) 0 var(--cx-size-6px),transparent var(--cx-size-6px) var(--cx-size-12px));box-shadow:none;}
48
48
  .cx-tl-shade.cx-tl-bg{background:color-mix(in srgb,var(--cx-bg-tone) 12%,transparent);box-shadow:inset var(--cx-size-2px) 0 0 color-mix(in srgb,var(--cx-bg-tone) 55%,transparent);}
49
49
  :where(.cx-cal-rtl) .cx-tl-shade.cx-tl-bg{box-shadow:inset calc(-1 * var(--cx-size-2px)) 0 0 color-mix(in srgb,var(--cx-bg-tone) 55%,transparent);}
50
- .cx-tl-heat{position:absolute;z-index:2;background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));top:var(--cx-size-5px);bottom:var(--cx-size-5px);display:grid;place-items:center;border-radius:var(--hfx-radius-sm,4px);font-size:var(--cx-size-11d5px);font-weight:600;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font-variant-numeric:tabular-nums;overflow:hidden;isolation:isolate;}
50
+ .cx-tl-heat{position:absolute;z-index:2;background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));top:var(--cx-size-5px);bottom:var(--cx-size-5px);display:grid;place-items:center;border-radius:var(--hfx-radius-sm,4px);font-size:var(--cx-size-11d5px);font-weight:600;color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));font-variant-numeric:tabular-nums;overflow:hidden;isolation:isolate;}
51
51
  .cx-tl-heat::before{content:"";position:absolute;inset:0 var(--cx-size-1px);z-index:-1;border-radius:inherit;background:var(--cx-bg-tone,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)));opacity:calc(.12 + var(--cx-heat,0) * .38);}
52
52
  .cx-tl-heat[data-cx-tone]::before{opacity:calc(.28 + var(--cx-heat,0) * .42);}
53
53
  .cx-tl-lane > .cx-tl-ghost{top:var(--cx-size-3px);bottom:var(--cx-size-3px);padding:0;overflow:visible;}
54
- .cx-tl-ghost > .cx-tl-ghost-label{position:absolute;inset-inline-start:calc(100% + var(--cx-size-6px));top:50%;transform:translateY(-50%);padding:var(--cx-size-2px) var(--cx-size-6px);border:var(--cx-size-1px) solid currentColor;border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));white-space:nowrap;box-shadow:var(--hfx-elevation-1,0 1px 2px rgba(22,24,28,.06));}
54
+ .cx-tl-ghost > .cx-tl-ghost-label{position:absolute;inset-inline-start:calc(100% + var(--cx-size-6px));top:50%;transform:translateY(-50%);padding:var(--cx-size-2px) var(--cx-size-6px);border:var(--cx-size-1px) solid currentColor;border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));white-space:nowrap;box-shadow:var(--hfx-elevation-1,0 1px 2px rgba(22,24,28,.06));}
55
55
  .cx-tl-print{display:none;}
56
56
  .cx-cal-phone .cx-tl{--cx-tl-side-w:176px;}
57
57
  .cx-cal-phone .cx-tl-tree .cx-hidden-fields{display:none;}
@@ -67,14 +67,14 @@
67
67
  .cx-tl > :is(.cx-tl-side,.cx-tl-main){display:none!important;}
68
68
  .cx-tl{display:block;height:auto;}
69
69
  .cx-tl-print{display:block;font-size:10px;}
70
- .cx-tl-print-row{display:grid;grid-template-columns:24% 1fr;align-items:stretch;min-height:18px;border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));break-inside:avoid;}
70
+ .cx-tl-print-row{display:grid;grid-template-columns:24% 1fr;align-items:stretch;min-height:18px;border-bottom:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));break-inside:avoid;}
71
71
  .cx-tl-print-head{font-weight:700;border-bottom-width:var(--cx-size-2px);}
72
- .cx-tl-print-group{background:color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 4%,transparent);font-weight:600;}
72
+ .cx-tl-print-group{background:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 4%,transparent);font-weight:600;}
73
73
  .cx-tl-print-name{padding:var(--cx-size-2px) var(--cx-size-4px);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}
74
74
  .cx-tl-print-lane{position:relative;min-height:18px;}
75
- .cx-tl-print-unit,.cx-tl-print-heat{position:absolute;top:0;bottom:0;padding:0 var(--cx-size-2px);border-inline-start:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));overflow:hidden;white-space:nowrap;}
75
+ .cx-tl-print-unit,.cx-tl-print-heat{position:absolute;top:0;bottom:0;padding:0 var(--cx-size-2px);border-inline-start:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));overflow:hidden;white-space:nowrap;}
76
76
  .cx-tl-print-bar.cx-tl-print-tiny{background:var(--cx-ev,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)));box-shadow:none;}
77
- .cx-tl-print-bar{position:absolute;top:var(--cx-size-2px);bottom:var(--cx-size-2px);padding:0 var(--cx-size-2px);border-radius:var(--cx-size-2px);background:color-mix(in srgb,var(--cx-ev,var(--hfx-color-accent,light-dark(#11776f,#37c9b8))) 22%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));box-shadow:inset var(--cx-size-2px) 0 0 var(--cx-ev,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)));overflow:hidden;white-space:nowrap;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
77
+ .cx-tl-print-bar{position:absolute;top:var(--cx-size-2px);bottom:var(--cx-size-2px);padding:0 var(--cx-size-2px);border-radius:var(--cx-size-2px);background:color-mix(in srgb,var(--cx-ev,var(--hfx-color-accent,light-dark(#11776f,#37c9b8))) 22%,var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c))));box-shadow:inset var(--cx-size-2px) 0 0 var(--cx-ev,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)));overflow:hidden;white-space:nowrap;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
78
78
  :where(.cx-cal-rtl) .cx-tl-print-bar{box-shadow:inset calc(-1 * var(--cx-size-2px)) 0 0 var(--cx-ev,var(--hfx-color-accent,light-dark(#11776f,#37c9b8)));}
79
79
  }
80
80
  @media (forced-colors:active){.cx-tl-ghost > .cx-tl-ghost-label{background:Canvas;color:CanvasText;border-color:CanvasText;}}
@@ -1,4 +1,4 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"22c9e15c108aeaa1",requires:["calendar"],install(context){if(installed.has(context.DataGrid.prototype))return;const{toneVariable,DataGrid,TreeGrid,h,setText,fill,numberFormat}=context;const{CAL_DAY,CAL_HOUR,CAL_MINUTE,calAddMonths,calCount,calDayNumber,calDayParts,calDow,calMonthStart,calWeekStart}=DataGrid.prototype.calKit;const TL_ZOOMS={hour:{width:56,unit:"hour"},day:{width:44,unit:"day"},week:{width:92,unit:"week"},month:{width:112,unit:"month"},quarter:{width:150,unit:"quarter"}};function tlSpan(zoom,date,firstDay){if(zoom==="hour")return{firstDay:date,lastDay:date};if(zoom==="day"){const month=calMonthStart(date);return{firstDay:month,lastDay:calAddMonths(month,1)- 1}}
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"cb9b9dd33154172c",requires:["calendar"],install(context){if(installed.has(context.DataGrid.prototype))return;const{toneVariable,DataGrid,TreeGrid,h,setText,fill,numberFormat}=context;const{CAL_DAY,CAL_HOUR,CAL_MINUTE,calAddMonths,calCount,calDayNumber,calDayParts,calDow,calMonthStart,calWeekStart}=DataGrid.prototype.calKit;const TL_ZOOMS={hour:{width:56,unit:"hour"},day:{width:44,unit:"day"},week:{width:92,unit:"week"},month:{width:112,unit:"month"},quarter:{width:150,unit:"quarter"}};function tlSpan(zoom,date,firstDay){if(zoom==="hour")return{firstDay:date,lastDay:date};if(zoom==="day"){const month=calMonthStart(date);return{firstDay:month,lastDay:calAddMonths(month,1)- 1}}
2
2
  if(zoom==="week"){const parts=calDayParts(date),quarter=calDayNumber(parts.y,Math.floor((parts.m-1)/ 3) * 3 + 1, 1);
3
3
  return{firstDay:calWeekStart(quarter,firstDay),lastDay:calWeekStart(calAddMonths(quarter,3)- 1,firstDay)+ 6}}
4
4
  const parts=calDayParts(date);if(zoom==="month")return{firstDay:calDayNumber(parts.y,1,1),lastDay:calDayNumber(parts.y+1,1,1)- 1};return{firstDay:calDayNumber(parts.y,1,1),lastDay:calDayNumber(parts.y+3,1,1)- 1}}
@@ -8,7 +8,8 @@ function tlCustomStep(span,date,direction){return span.unit==="month"?calAddMont
8
8
  function tlStep(zoom,date,direction){if(zoom==="hour")return date+direction;if(zoom==="day")return calAddMonths(date,direction);if(zoom==="week")return calAddMonths(date,3*direction);return calAddMonths(date,(zoom==="month"?12:36)*direction)}
9
9
  function tlUnits(zoom,span,zone,firstDay){const units=[],width=TL_ZOOMS[zoom].width;const push=(first,last,start,end)=>units.push({first,last,start,end,x:units.length*width});if(zoom==="hour"){for(let at=zone.start(span.firstDay),end=zone.start(span.lastDay+1);at<end;at +=CAL_HOUR){const day=zone.day(at);push(day,day,at,Math.min(at+CAL_HOUR,end))}}else if(zoom==="day"){for(let day=span.firstDay;day<=span.lastDay;day++)push(day,day,zone.start(day),zone.start(day+1))}else if(zoom==="week"){for(let day=calWeekStart(span.firstDay,firstDay);day<=span.lastDay;day +=7)push(day,day+6,zone.start(day),zone.start(day+7))}else{const months=zoom==="month"?1:3;for(let day=span.firstDay;day<=span.lastDay;day=calAddMonths(day,months)){const next=calAddMonths(day,months);push(day,next-1,zone.start(day),zone.start(next))}}
10
10
  return units}
11
- function tlAxis(zoom,span,zone,firstDay){const units=tlUnits(zoom,span,zone,firstDay),width=TL_ZOOMS[zoom].width,total=units.length*width;const unitOf=time=>{let low=0,high=units.length-1;while(low<high){const mid=(low+high+1)>>1;if(units[mid].start<=time)low=mid;else high=mid-1}
11
+ function tlAxis(zoom,span,zone,firstDay,minWidth=0){const units=tlUnits(zoom,span,zone,firstDay),width=Math.max(TL_ZOOMS[zoom].width,minWidth / units.length), total = units.length * width;
12
+ units.forEach((unit,index)=>{unit.x=index*width});const unitOf=time=>{let low=0,high=units.length-1;while(low<high){const mid=(low+high+1)>>1;if(units[mid].start<=time)low=mid;else high=mid-1}
12
13
  return low};return{zoom,units,width,total,from:units[0].start,to:units[units.length-1].end,x(time){if(time<=this.from)return 0;if(time>=this.to)return total;const unit=units[unitOf(time)];return unit.x +(time-unit.start)/ (unit.end - unit.start) * width;
13
14
  },time(x){const index=Math.max(0,Math.min(units.length-1,Math.floor(x / width))), unit = units[index];
14
15
  return unit.start+Math.max(0,Math.min(1,(x-unit.x)/ width)) * (unit.end - unit.start);
@@ -24,11 +25,11 @@ Object.assign(DataGrid.prototype,{startTimeline(){if(this.tl)return;const resour
24
25
  const inline=!resources.view.source||resources.view.source.kind==="inline";if(inline)this.tlLearnNodes(resources.view.roots||[],null);this.tlInline=inline},tlLearnNodes(nodes,parent){const stack=nodes.map(node=>[node,parent]).reverse();while(stack.length){const[node,owner]=stack.pop();if(!node||typeof node.id!=="string"||this.tl.learned.has(node.id))continue;this.tl.learned.add(node.id);this.tl.names.set(node.id,node.label??node.id);this.tl.parent.set(node.id,owner);this.tl.order.push(node.id);if(owner!==null){if(!this.tl.children.has(owner))this.tl.children.set(owner,[]);this.tl.children.get(owner).push(node.id)}
25
26
  if(Array.isArray(node.children))for(let i=node.children.length-1;i>=0;i--)stack.push([node.children[i],node.id])}},calResourceName(id){return this.tl?.names.get(id)??id},calResourceColumns(){if(!this.tl||!this.tlInline)return null;const leaves=this.tl.order.filter(id=>!this.tl.children.has(id));if(!leaves.length)return null;return leaves.map(id=>({id,label:this.calResourceName(id),group:this.tl.parent.get(id)==null?null:this.calResourceName(this.tl.parent.get(id))}))},calHoursFor(resource,dow){const list=this.cal.availability;if(!list.length)return undefined;let own=resource==null?[]:list.filter(item=>item.resource===resource);for(let parent=this.tl?.parent.get(resource);!own.length&&parent!=null;parent=this.tl.parent.get(parent))own=list.filter(item=>item.resource===parent);const entries=own.length?own:list.filter(item=>item.resource==null);return entries.length?entries.filter(item=>item.days.has(dow)):undefined},calResourceStep(resource,sign){if(this.tlSolo)return resource;const rows=this.tlTree?this.tlTree.rows.filter(row=>!row.status&&!this.tl.children.has(row.key)).map(row=>row.key):this.tl.order.filter(id=>!this.tl.children.has(id));const at=rows.indexOf(resource);return rows[Math.max(0,Math.min(rows.length-1,(at<0?0:at)+ sign))]??resource},calResourceWindow(){if(this.cal.resourceIds||this.calView!=="timeline"||this.tlSolo||this.view.source.kind==="inline"&&!this.opts.source)return null;this.tlEnsure();if(!this.tlTree?.rows?.length)return null;const range=this.tlMain.clientHeight?this.tlVisibleRows(40):{first:0,last:Math.min(this.tlTree.rows.length-1,80)},ids=new Set();for(let i=range.first;i<=range.last&&ids.size<1000;i++){const row=this.tlTree.rows[i];if(!row||row.status)continue;const stack=[row.key];while(stack.length&&ids.size<1000){const id=stack.pop();if(ids.has(id))continue;ids.add(id);const children=this.tl.children.get(id)||[];for(let at=children.length-1;at>=0;at--)stack.push(children[at])}}
26
27
  const window=[...ids];return window.length?window:null},tlCheckWindow(){if(this.view.source.kind==="inline"&&!this.opts.source)return;clearTimeout(this.tlWindowTimer);this.tlWindowTimer=setTimeout(()=>{if(this.destroyed||this.calView!=="timeline")return;const wanted=this.calResourceWindow(),loaded=JSON.parse(this.calWindowKey||"null"),known=new Set(loaded||[]);if(wanted&&(!loaded||wanted.some(id=>!known.has(id))))this.calReload({keep:true})},250)},calResourcesReady(){if(this.calView!=="timeline"||this.view.source.kind==="inline"&&!this.opts.source)return null;this.tlEnsure();return this.tlTree.ready?.catch(()=>{})},calTimelineRange(date){return this.cal.span?tlCustomSpan(this.cal.span,date,this.cal.firstDay):tlSpan(this.calZoom,date,this.cal.firstDay)},calTimelineStep(date,direction){return this.cal.span?tlCustomStep(this.cal.span,date,direction):tlStep(this.calZoom,date,direction)},calTimelineTitle(){const range=this.calRange,fmt=this.calFmt;if(this.cal.span)return range.firstDay===range.lastDay?fmt.longDay(range.firstDay):fmt.dayRange(range.firstDay,range.lastDay);if(this.calZoom==="hour")return fmt.longDay(range.firstDay);if(this.calZoom==="day")return fmt.monthTitle(range.firstDay);if(this.calZoom==="week")return fmt.monthRange(range.firstDay,range.lastDay);return range.lastDay-range.firstDay>400?fmt.year(range.firstDay)+ " – "+fmt.year(range.lastDay):fmt.year(range.firstDay)},calTimelineHasNow(){const now=Date.now();return this.tlAxis?now>=this.tlAxis.from&&now<this.tlAxis.to:false},tlEnsure(){if(this.tlRoot)return;const resources=this.cal.resources,root=this.tlRoot=h("div","cx-tl" +(this.tlSolo?" cx-tl-solo":"")),side=h("div","cx-tl-side"),host=this.tlTreeHost=h("div","cx-tl-tree");const main=this.tlMain=h("div","cx-tl-main"),head=this.tlHead=h("div","cx-tl-head"),canvas=this.tlCanvas=h("div","cx-tl-canvas");head.setAttribute("aria-hidden","true");const upper=this.tlUpper=h("div","cx-tl-hrow cx-tl-upper"),lower=this.tlLower=h("div","cx-tl-hrow cx-tl-lower");head.append(upper,lower);canvas.setAttribute("role","grid");canvas.setAttribute("aria-labelledby",this.calTitle.id);canvas.setAttribute("aria-readonly",String(!this.cal.editable));if(this.tlSolo){root.append(main);main.append(head,canvas);const signal=this.lifetime.signal;this.tlTree={rows:[],tops:[0],rowH:this.rowH||34,version:0,destroyed:false,ready:Promise.resolve(),grid:side,scheduleRender:()=>this.tlScheduleLanes(),setState:()=>Promise.resolve(),destroy(){this.destroyed=true}};main.addEventListener("scroll",()=>this.tlScheduleLanes(),{passive:true,signal});return}
27
- root.style.setProperty("--cx-tl-side",resources.width+"px");main.append(head,canvas);side.appendChild(host);root.append(side,main);const aggregates=resources.aggregates,renderers={};for(const[column,kind]of Object.entries(aggregates))renderers[column]=(node,element)=>{setText(element,this.tlAggregateText(node.id,kind));element.classList.add("cx-tl-agg");return true};const view={...resources.view,rowHeight:resources.view.rowHeight||this.rowH,labels:{...this.view.labels,...resources.view.labels}};const tree=this.tlTree=new TreeGrid(host,{view,toolbar:false,renderers,labels:this.opts.labels});tree.emit=(name,detail)=>{if(!tree.destroyed)host.dispatchEvent(new CustomEvent("canopyx:"+name,{detail}))};const render=tree.render.bind(tree);tree.render=()=>{const result=render();if(!this.tlRows||this.tlRows!==tree.rows.length+":"+tree.version){this.tlLearnLoaded()}this.tlPaintLanes();this.tlCheckWindow();return result};const signal=this.lifetime.signal;let syncing=false;main.addEventListener("scroll",()=>{if(!syncing&&tree.grid.scrollTop!==main.scrollTop){syncing=true;tree.grid.scrollTop=main.scrollTop;syncing=false}
28
+ root.style.setProperty("--cx-tl-side",resources.width+"px");main.append(head,canvas);side.appendChild(host);root.append(side,main);const aggregates=resources.aggregates,renderers={};for(const[column,kind]of Object.entries(aggregates))renderers[column]=(node,element)=>{setText(element,this.tlAggregateText(node.id,kind));element.classList.add("cx-tl-agg");return true};const view={...resources.view,rowHeight:this.view.plan?Math.max(64,resources.view.rowHeight||this.rowH):resources.view.rowHeight||this.rowH,labels:{...this.view.labels,...resources.view.labels}};const tree=this.tlTree=new TreeGrid(host,{view,toolbar:false,renderers,labels:this.opts.labels});main.setAttribute("aria-controls",tree.grid.id);tree.emit=(name,detail)=>{if(!tree.destroyed)host.dispatchEvent(new CustomEvent("canopyx:"+name,{detail}))};const render=tree.render.bind(tree);tree.render=()=>{const result=render();if(!this.tlRows||this.tlRows!==tree.rows.length+":"+tree.version){this.tlLearnLoaded()}this.tlPaintLanes();this.tlCheckWindow();return result};const signal=this.lifetime.signal;let syncing=false;main.addEventListener("scroll",()=>{if(!syncing&&tree.grid.scrollTop!==main.scrollTop){syncing=true;tree.grid.scrollTop=main.scrollTop;syncing=false}
28
29
  this.tlScheduleLanes();this.tlCheckWindow()},{passive:true,signal});tree.grid.addEventListener("scroll",()=>{if(!syncing&&Math.abs(tree.grid.scrollTop-main.scrollTop)>1){syncing=true;main.scrollTop=tree.grid.scrollTop;syncing=false}},{passive:true,signal});host.addEventListener("wheel",event=>{if(!event.deltaY||event.ctrlKey)return;event.preventDefault();main.scrollTop +=event.deltaY*(event.deltaMode===1?tree.rowH:event.deltaMode===2?main.clientHeight:1)},{passive:false,signal});host.addEventListener("canopyx:toggle",event=>{const node=event.detail.node;if(event.detail.expanded)this.calCollapsed.delete(node.id);else this.calCollapsed.add(node.id);this.stateChanged()},{signal});host.addEventListener("canopyx:select",event=>{const node=event.detail.node;if(!node){this.clearCalendarSelection();return}
29
30
  const zone=this.calZone,range=this.calRange,ids=new Set([node.id,...this.tlDescendants(node.id)]);this.calSelection={first:range.firstDay,last:range.lastDay,from:zone.start(range.firstDay),to:zone.start(range.lastDay+1),resource:node.id};const events=this.calEvents.filter(item=>!item.background&&this.calEventResources(item).some(id=>ids.has(id)));this.calAnnounce(fill(this.calLabels.calendarSelected,{range:this.calResourceName(node.id)}));this.calEmitLink("select",events,this.calResourceName(node.id),this.calSelection)},{signal});signal.addEventListener("abort",()=>{clearTimeout(this.tlWindowTimer);tree.destroy()},{once:true});tree.ready.then(()=>{if(!this.destroyed){this.calApplyCollapsed();this.tlPaintLanes()}},error=>this.emit("error",{error}))},tlLearnLoaded(){const tree=this.tlTree;this.tlRows=tree.rows.length+":"+tree.version;for(const row of tree.rows)if(!row.status&&row.key!=null&&!this.tl.learned.has(row.key)){this.tl.learned.add(row.key);this.tl.names.set(row.key,row.h.label??row.key);this.tl.order.push(row.key);const parent=row.parent?.key??null;this.tl.parent.set(row.key,parent);if(parent!==null){if(!this.tl.children.has(parent))this.tl.children.set(parent,[]);this.tl.children.get(parent).push(row.key)}
30
31
  if(row.h.hasChildren&&!this.tl.children.has(row.key))this.tl.children.set(row.key,[])}},tlDescendants(id){const out=[],stack=[...(this.tl.children.get(id)||[])];while(stack.length&&out.length<100000){const next=stack.pop();out.push(next);stack.push(...(this.tl.children.get(next)||[]))}
31
- return out},calApplyCollapsed(){const tree=this.tlTree;if(!tree||this.destroyed)return;const expanded=[];if(this.tlInline){const walk=(id,path)=>{if(!this.tl.children.has(id)||this.calCollapsed.has(id))return;expanded.push(path);for(const child of this.tl.children.get(id))walk(child,path.concat(child))};for(const id of this.tl.order)if(this.tl.parent.get(id)===null)walk(id,[id]);tree.setState({expanded}).catch?.(()=>{})}},calPaintTimeline(){this.tlEnsure();const span=this.calRange,axis=this.tlAxis=tlAxis(this.calZoom,span,this.calZone,this.cal.firstDay);this.tlIndex=this.tlIndexEvents();this.tl.heat.clear();if(this.tlRoot.parentNode!==this.calBody)this.calBody.replaceChildren(this.tlRoot);this.tlCanvas.style.width=axis.total+"px";this.tlHead.style.width=axis.total+"px";const header=tlHeader(this,axis),paint=(row,cells,cls)=>{row.replaceChildren(...cells.map(cell=>{const element=h("div",cls +(cell.weekend?" cx-tl-weekend":"")),text=h("span","cx-tl-hlabel");element.style.insetInlineStart=cell.x+"px";element.style.width=cell.width+"px";setText(text,cell.text);element.appendChild(text);element.title=cell.label;return element}))};paint(this.tlUpper,header.upper,"cx-tl-hcell cx-tl-hupper");paint(this.tlLower,header.lower,"cx-tl-hcell");this.tlHeader=header;this.calGrid=this.tlCanvas;if(this.tlScrolledFor!==this.calZoom+":"+span.firstDay){this.tlScrolledFor=this.calZoom+":"+span.firstDay;const now=Date.now(),target=now>=axis.from&&now<axis.to?axis.x(now)- this.tlMain.clientWidth / 3 : 0;
32
+ return out},calApplyCollapsed(){const tree=this.tlTree;if(!tree||this.destroyed)return;const expanded=[];if(this.tlInline){const walk=(id,path)=>{if(!this.tl.children.has(id)||this.calCollapsed.has(id))return;expanded.push(path);for(const child of this.tl.children.get(id))walk(child,path.concat(child))};for(const id of this.tl.order)if(this.tl.parent.get(id)===null)walk(id,[id]);tree.setState({expanded}).catch?.(()=>{})}},calPaintTimeline(){this.tlEnsure();if(this.tlRoot.parentNode!==this.calBody)this.calBody.replaceChildren(this.tlRoot);const span=this.calRange,axis=this.tlAxis=tlAxis(this.calZoom,span,this.calZone,this.cal.firstDay,this.view.plan?this.tlMain.clientWidth:0);if(this.view.plan)this.planFitWidth=this.tlMain.clientWidth;this.tlIndex=this.tlIndexEvents();this.tl.heat.clear();if(this.tlRoot.parentNode!==this.calBody)this.calBody.replaceChildren(this.tlRoot);this.tlCanvas.style.width=axis.total+"px";this.tlHead.style.width=axis.total+"px";const header=tlHeader(this,axis),paint=(row,cells,cls)=>{row.replaceChildren(...cells.map(cell=>{const element=h("div",cls +(cell.weekend?" cx-tl-weekend":"")),text=h("span","cx-tl-hlabel");element.style.insetInlineStart=cell.x+"px";element.style.width=cell.width+"px";setText(text,cell.text);element.appendChild(text);element.title=cell.label;return element}))};paint(this.tlUpper,header.upper,"cx-tl-hcell cx-tl-hupper");paint(this.tlLower,header.lower,"cx-tl-hcell");this.tlHeader=header;this.calGrid=this.tlCanvas;if(this.tlScrolledFor!==this.calZoom+":"+span.firstDay){this.tlScrolledFor=this.calZoom+":"+span.firstDay;const selected=this.calZone.start(this.calDate),target=selected>=axis.from&&selected<axis.to?axis.x(selected)- this.tlMain.clientWidth / 3 : 0;
32
33
  this.tlScrollTo(Math.max(0,target))}
33
34
  this.tlTree.version++;this.tlTree.scheduleRender();this.tlPaintLanes()},tlScrollX(){return Math.abs(this.tlMain.scrollLeft)},tlScrollTo(x){this.tlMain.scrollLeft=this.calRtl?-x:x},calTimelineScroll(){return this.tlMain?{timeline:true,top:this.tlMain.scrollTop,left:this.tlScrollX(),view:"timeline",date:this.calDate,zoom:this.calZoom}:null},calRestoreTimelineScroll(state){if(state.zoom!==this.calZoom||state.date!==this.calDate)return false;this.tlMain.scrollTop=state.top;this.tlScrollTo(state.left);return true}});Object.assign(DataGrid.prototype,{calWindowTimeColumns(columns){this.calTimeWindow=null;if(this.calPhone||this.calPrinting||columns.length<=24)return columns;const size=Math.max(2,Math.min(24,Math.floor((this.calBody.clientWidth-this.calKit.CAL_GUTTER)/ 150)));
34
35
  const first=Math.max(0,Math.min(columns.length-size,this.calTimeFirst||0));this.calTimeFirst=first;this.calTimeWindow={first,size,total:columns.length,columns};return columns.slice(first,first+size).map((column,index)=>({...column,index:first+index}))},calTimeReveal(index,minutes){const window=this.calTimeWindow;if(!window||index<0||index>=window.total)return false;const column=window.columns[index];this.calTimeFirst=index<window.first?index:index>=window.first+window.size?index-window.size+1:window.first;this.calFocus={day:column.day,minutes,resource:column.resource,event:null};this.calPaint({keep:true});this.calRestoreFocus(true);return true}});const TL_MARGIN=480,TL_STACK=4,TL_MIN_BAR=8,TL_SOLID_BAR=16;Object.assign(DataGrid.prototype,{tlIndexEvents(){const byResource=new Map(),backgrounds=new Map();for(const event of this.calEvents){const span=this.calDisplaySpan(event);event.tlStart=span.start;event.tlEnd=span.end}
@@ -41,7 +42,7 @@ for(const event of events){let lane=ends.findIndex(end=>end<=event.tlStart);if(l
41
42
  ends[lane]=Math.max(event.tlEnd,event.tlStart+1);const key="lane-"+lane;event.tlLane=0;event.tlRow=key;if(!byResource.has(key)){const list=[];list.lanes=1;byResource.set(key,list)}
42
43
  byResource.get(key).push(event)}
43
44
  const count=Math.max(1,ends.length);tree.rows=Array.from({length:count},(_,index)=>({key:"lane-"+index,level:1,status:null,h:{label:String(index+1)}}));tree.tops=Array.from({length:count+1},(_,index)=>index*tree.rowH);for(const row of tree.rows)this.tl.names.set(row.key,row.h.label);tree.version++;this.tl.stats=null;return{byResource,backgrounds}},tlVisibleRows(margin){const tree=this.tlTree,tops=tree.tops,count=tree.rows.length,main=this.tlMain;if(!count)return{first:0,last:-1};const top=main.scrollTop,bottom=top+main.clientHeight,find=y=>{let low=0,high=count-1;while(low<high){const mid=(low+high+1)>>1;if(tops[mid]<=y)low=mid;else high=mid-1}return low};return{first:Math.max(0,find(top)- margin),last:Math.min(count-1,find(bottom)+ margin)}},tlScheduleLanes(){if(this.tlFrame)return;this.tlFrame=requestAnimationFrame(()=>{this.tlFrame=0;if(!this.destroyed)this.tlPaintLanes()})},tlPaintLanes(){const tree=this.tlTree,axis=this.tlAxis,canvas=this.tlCanvas;if(!tree||!axis||this.calView!=="timeline"||!canvas.isConnected)return;const rows=tree.rows,tops=tree.tops,total=tops[rows.length]||0,main=this.tlMain;canvas.style.height=total+"px";canvas.setAttribute("aria-rowcount",String(rows.length));const visible=this.tlVisibleRows(3),bucket=Math.floor(this.tlScrollX()/ TL_MARGIN), left = (bucket - 1) * TL_MARGIN, right = (bucket + 2) * TL_MARGIN + main.clientWidth;
44
- const lanes=this.tlLanes||=new Map(),keep=new Set(),signature=[this.calEpoch,this.calVersion,this.calSourceVersion||0,axis.zoom,axis.from,bucket,this.linkHighlight?.size||0,this.calSelection?.resource??""].join("|");for(let i=visible.first;i<=visible.last;i++){const row=rows[i],key=row.status?"status:"+i:row.key;keep.add(key);let lane=lanes.get(key);if(!lane){lane=h("div","cx-tl-lane");lane.setAttribute("role","row");lanes.set(key,lane)}
45
+ const lanes=this.tlLanes||=new Map(),keep=new Set(),signature=[this.calEpoch,this.calVersion,this.calSourceVersion||0,axis.zoom,axis.from,axis.width,bucket,this.linkHighlight?.size||0,this.calSelection?.resource??""].join("|");for(let i=visible.first;i<=visible.last;i++){const row=rows[i],key=row.status?"status:"+i:row.key;keep.add(key);let lane=lanes.get(key);if(!lane){lane=h("div","cx-tl-lane");lane.setAttribute("role","row");lanes.set(key,lane)}
45
46
  const height=(tops[i+1]??total)- tops[i];lane.style.top=tops[i]+ "px";lane.style.height=height+"px";lane.setAttribute("aria-rowindex",String(i+1));if(lane._sig!==signature+"|"+height||lane._row!==row){lane._sig=signature+"|"+height;lane._row=row;this.tlPaintLane(lane,row,height,left,right)}
46
47
  if(lane.parentNode!==canvas)canvas.appendChild(lane)}
47
48
  for(const[key,lane]of lanes)if(!keep.has(key)){if(lane.contains(document.activeElement))continue;lane.remove();lanes.delete(key)}
@@ -1,29 +1,23 @@
1
- /* Graphite chrome shared by flat grids and trees: the card,toolbar,search,buttons,menus,header and cells. */
2
- .cx-tree-tools{border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-container,var(--hfx-radius-lg,10px));overflow:hidden;font:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem))/1.4 var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);}
1
+ /* Graphite chrome shared by flat grids and trees: the card,toolbar,search,menus,header and cells. Buttons,fields,chips
2
+ and badges are the shared controls (canopyx.source/controls.css). */
3
+ .cx-tree-tools{border:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));border-radius:var(--hfx-radius-container,var(--hfx-radius-lg,10px));overflow:hidden;font:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem))/1.4 var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);}
3
4
  .cx-page > .cx-tree-tools,.cx-page > .cx-main > .cx-tree-tools{padding:0;}
4
5
  body .cx-host.cx-tree-tools{padding:0;}
5
6
  .cx-tree-tools [hidden]{display:none!important;}
6
7
  .cx-tree-tools .cx-grid{border:0;border-radius:0;overflow-anchor:none;}
7
- .cx-tree-tools .cx-toolbar{flex:none;gap:var(--cx-size-8px);padding:var(--cx-size-10px) var(--cx-size-12px);border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
8
- .cx-tree-tools .cx-search{flex:1 1 var(--cx-size-240px);max-width:var(--cx-size-360px);height:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));display:flex;align-items:center;gap:var(--cx-size-8px);padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid var(--hfx-color-border-control,light-dark(#8a8f98,#6e737c));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));min-width:0;}
8
+ .cx-tree-tools .cx-toolbar{flex:none;gap:var(--cx-size-8px);padding:var(--cx-size-10px) var(--cx-size-12px);border-bottom:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
9
+ .cx-tree-tools .cx-search{flex:1 1 var(--cx-size-240px);max-width:var(--cx-size-360px);height:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));display:flex;align-items:center;gap:var(--cx-size-8px);padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid var(--hfx-color-border-control,light-dark(#8a8f98,#6e737c));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));min-width:0;}
9
10
  .cx-tree-tools .cx-search::before,.cx-tree-tools .cx-search::after{display:none;}
10
11
  .cx-tree-tools .cx-search-input{flex:1;min-width:0;width:100%;max-width:none;min-height:0;height:100%;border:0;padding:0;border-radius:0;background:transparent;}
11
12
  .cx-tree-tools .cx-search:focus-within{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
12
13
  .cx-tree-tools .cx-search .cx-search-input:focus-visible{outline:0;}
13
- .cx-tree-tools .cx-search kbd{font:var(--cx-size-11px) var(--hfx-font-mono,"Cascadia Mono","Cascadia Code",Consolas,"SFMono-Regular",Menlo,monospace);border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));padding:0 var(--cx-size-5px);}
14
- .cx-tree-tools .cx-button,.cx-tree-tools .cx-btn{height:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));min-height:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));display:inline-flex;align-items:center;justify-content:center;gap:var(--cx-size-6px);padding:0 var(--cx-size-11px);border:var(--cx-size-1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font:var(--hfx-weight-medium,500) var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem)) var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);cursor:pointer;white-space:nowrap;}
14
+ .cx-tree-tools .cx-search kbd{font:var(--cx-size-11px) var(--hfx-font-mono,"Cascadia Mono","Cascadia Code",Consolas,"SFMono-Regular",Menlo,monospace);border:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));padding:0 var(--cx-size-5px);}
15
15
  .cx-tree-tools .cx-columns > summary::after{display:none;}
16
- .cx-tree-tools .cx-button:hover,.cx-tree-tools .cx-btn:hover{background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));}
17
- .cx-tree-tools .ghost{border-color:transparent;color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
18
- .cx-tree-tools .icon{width:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));padding:0;}
19
- .cx-tree-tools .active{border-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));}
20
- .cx-tree-tools .badge{min-width:var(--cx-size-18px);height:var(--cx-size-18px);padding:0 var(--cx-size-5px);border-radius:var(--hfx-radius-badge,var(--hfx-radius-sm,4px));background:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));color:var(--hfx-color-accent-contrast,light-dark(#ffffff,#0c0d10));font-size:var(--cx-size-11d5px);font-weight:700;display:inline-grid;place-items:center;}
21
- .cx-tree-tools .cx-button:disabled{opacity:.4;cursor:default;}
22
16
  .cx-spacer{flex:1;}
23
- .cx-sep{width:var(--cx-size-1px);height:var(--cx-size-20px);background:var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
17
+ .cx-sep{width:var(--cx-size-1px);height:var(--cx-size-20px);background:var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
24
18
  .cx-tree-tools .cx-hrow{height:var(--hfx-table-header-height,calc(40px - var(--cx-compact,0) * 8px));}
25
19
  .cx-tree-tools .cx-hcell{padding:0 var(--hfx-cell-padding-x,calc(12px - var(--cx-compact,0) * 4px));border-right:0;overflow:visible;gap:var(--cx-size-4px);}
26
- .cx-tree-tools .cx-hcell::after{content:"";position:absolute;right:0;top:var(--cx-size-9px);bottom:var(--cx-size-9px);width:var(--cx-size-1px);background:var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
20
+ .cx-tree-tools .cx-hcell::after{content:"";position:absolute;right:0;top:var(--cx-size-9px);bottom:var(--cx-size-9px);width:var(--cx-size-1px);background:var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
27
21
  .cx-tree-tools .cx-hcell:last-child::after{display:none;}
28
22
  .cx-tree-tools .cx-hcell:last-child .cx-resize{right:0;}
29
23
  .cx-tree-tools .cx-hcell .cx-sort{min-width:var(--cx-size-24px);overflow:hidden;}
@@ -31,14 +25,26 @@ body .cx-host.cx-tree-tools{padding:0;}
31
25
  .cx-tree-tools .cx-cell{padding:0 var(--hfx-cell-padding-x,calc(12px - var(--cx-compact,0) * 4px));font-variant-numeric:tabular-nums;}
32
26
  .cx-tree-tools .cx-row > .cx-cell:first-child:not([data-cx-pin]){position:relative;}
33
27
  .cx-tree-tools .cx-row[aria-selected="true"] > .cx-cell:first-child::before{content:"";position:absolute;inset:0 auto 0 0;width:var(--cx-size-2px);background:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));pointer-events:none;z-index:4;}
34
- .cx-tree-tools .cx-grid-panel{position:fixed;height:auto;color:inherit;width:var(--cx-size-280px);max-width:calc(var(--cx-size-100vw) - var(--cx-size-32px));display:flex;flex-wrap:wrap;gap:var(--cx-size-8px);padding:var(--cx-size-10px) var(--cx-size-12px);border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));}
28
+ .cx-tree-tools .cx-grid-panel{position:fixed;height:auto;color:inherit;width:var(--cx-size-280px);max-width:calc(var(--cx-size-100vw) - var(--cx-size-32px));display:flex;flex-wrap:wrap;gap:var(--cx-size-8px);padding:var(--cx-size-10px) var(--cx-size-12px);border:var(--cx-size-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));box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));}
35
29
  .cx-tree-tools .cx-grid-columns > .cx-grid-panel{display:block;width:var(--cx-size-320px);padding:var(--cx-size-8px);max-height:var(--cx-size-420px);overflow:auto;}
36
30
  .cx-tree-tools .cx-grid-field{display:flex;flex-direction:column;gap:var(--cx-size-4px);align-items:stretch;min-width:0;}
37
- .cx-tree-tools .cx-grid-field :is(input:not([type="checkbox"]),select,textarea),.cx-tree-tools .cx-grid-panel > :is(select,input){min-width:0;width:100%;height:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid var(--hfx-color-border-control,light-dark(#8a8f98,#6e737c));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font:inherit;}
31
+ .cx-tree-tools .cx-grid-field :is(input:not([type="checkbox"]),select,textarea),.cx-tree-tools .cx-grid-panel > :is(select,input){min-width:0;width:100%;height:var(--hfx-control-height-md,calc(36px - var(--cx-compact,0) * 8px));padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid var(--hfx-color-border-control,light-dark(#8a8f98,#6e737c));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));font:inherit;}
38
32
  .cx-grid-control-error{color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));margin:0;width:100%;overflow-wrap:anywhere;}
39
33
  .cx-grid-delivery-status{margin:0;font-size:var(--cx-size-d875em);overflow-wrap:anywhere;}
40
34
  .cx-grid-delivery-status:empty{display:none;}
41
35
  .cx-grid-export progress{width:100%;max-width:100%;accent-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
36
+ .cx-tree-tools .cx-export-panel{display:flex;flex-direction:column;flex-wrap:nowrap;width:min(44ch,calc(100vw - var(--hfx-space-4,1rem)));gap:var(--hfx-space-2,0.5rem);overflow:auto;}
37
+ .cx-tree-tools .cx-export-panel > *{flex-shrink:0;}
38
+ .cx-tree-tools.cx-phone .cx-grid-panel.cx-export-panel::before{flex:0 0 var(--hfx-space-1,0.25rem);}
39
+ .cx-export-count{margin:0;padding:0 var(--hfx-space-0-5,2px) 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);}
40
+ .cx-export-formats,.cx-export-actions{display:flex;flex-direction:column;gap:var(--hfx-space-0-5,2px);}
41
+ .cx-export-actions{border-top:var(--hfx-border-width,1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));padding-top:var(--hfx-space-2,0.5rem);margin-top:var(--hfx-space-1,0.25rem);}
42
+ .cx-tree-tools .cx-export-choice{width:100%;height:auto;min-height:var(--hfx-control-height-lg,calc(44px - var(--cx-compact,0) * 8px));justify-content:flex-start;text-align:left;padding:var(--hfx-space-2,0.5rem) var(--hfx-space-2,0.5rem);gap:var(--hfx-space-3,0.75rem);border:0;background:transparent;white-space:normal;}
43
+ .cx-export-icon{flex:none;display:grid;place-items:center;box-sizing:border-box;width:calc(var(--hfx-icon-md,16px)*2.5);height:var(--hfx-menu-item-height,calc(32px - var(--cx-compact,0) * 4px));padding: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-control,var(--hfx-radius-md,6px));color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font:var(--hfx-weight-semibold,600) var(--hfx-type-caption-size,0.75rem) var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);}
44
+ .cx-export-actions .cx-export-icon{font-size:var(--hfx-icon-md,16px);}
45
+ .cx-export-choice-text{display:flex;flex-direction:column;min-width:0;gap:var(--hfx-space-1,0.25rem);}
46
+ .cx-export-choice-title{font-weight:var(--hfx-weight-semibold,600);}
47
+ .cx-export-hint{font-size:var(--hfx-type-caption-size,0.75rem);font-weight:normal;color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));line-height:var(--hfx-type-caption-line-height,1.35);}
42
48
  .cx-tree-tools .cx-grid-views .cx-grid-field{width:100%;}
43
49
  .cx-tree-tools :is(button,summary,select,input,textarea):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);}
44
50
  .cx-tree-tools .cx-grid-overflow .cx-grid-panel{right:0;left:auto;width:var(--cx-size-244px);}
@@ -50,7 +56,7 @@ body .cx-host.cx-tree-tools{padding:0;}
50
56
  .cx-tree-tools.cx-phone .cx-grid-columns > summary .cx-ico{width:var(--cx-size-16px);height:var(--cx-size-16px);}
51
57
  .cx-tree-tools.cx-phone .cx-toolbar :is(.cx-btn,.cx-button){min-height:var(--cx-size-44px);}
52
58
  .cx-tree-tools.cx-phone .cx-grid-panel{position:fixed!important;inset:auto 0 0!important;width:100%!important;max-width:100%!important;max-height:var(--cx-size-85vh)!important;overflow:auto;border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));z-index:30;}
53
- .cx-tree-tools.cx-phone .cx-grid-panel::before{content:"";display:block;width:var(--cx-size-32px);height:var(--cx-size-4px);border-radius:var(--hfx-radius-pill,999px);background:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));margin:0 auto var(--cx-size-8px);flex-basis:var(--cx-size-32px);}
59
+ .cx-tree-tools.cx-phone .cx-grid-panel::before{content:"";display:block;width:var(--cx-size-32px);height:var(--cx-size-4px);border-radius:var(--hfx-radius-pill,999px);background:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));margin:0 auto var(--cx-size-8px);}
54
60
  .cx-tree-tools.cx-phone .cx-grid-panel:has(> [open])::before{display:none;}
55
61
  .cx-tree-tools.cx-phone .cx-hrow{height:var(--cx-size-44px);}
56
62
  .cx-tree-tools.cx-phone .cx-hidden-fields::after{content:"";position:absolute;inset:calc(-1 * var(--cx-size-10px)) calc(-1 * var(--cx-size-8px));}
@@ -60,36 +66,31 @@ body .cx-host.cx-tree-tools{padding:0;}
60
66
  .cx-grid-column-choice{display:flex;align-items:center;border-radius:var(--hfx-radius-sm,4px);}
61
67
  .cx-grid-column-choice label{flex:1;min-width:0;white-space:nowrap;}
62
68
  .cx-grid-column-name{flex:1;overflow:hidden;text-overflow:ellipsis;}
63
- :is(.cx-grid-column-note,.cx-grid-column-handle){flex:none;padding:0 var(--cx-size-6px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--cx-size-12px);white-space:nowrap;}
64
- .cx-grid-column-handle{height:var(--cx-size-28px);border:0;background:none;cursor:grab;touch-action:none;}
65
- .cx-grid-column-choice.cx-drop-before{box-shadow:inset 0 var(--cx-size-2px) var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
66
- .cx-grid-column-choice.cx-drop-after{box-shadow:inset 0 var(--cx-size-neg-2px) var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
67
- .cx-grid-column-actions{display:flex;justify-content:space-between;margin-top:var(--cx-size-4px);padding-top:var(--cx-size-4px);border-top:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
69
+ :is(.cx-grid-column-note,.cx-grid-column-handle){flex:none;padding:0 var(--hfx-space-1-5,6px);color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-size:var(--hfx-type-caption-size,0.75rem);white-space:nowrap;}
70
+ .cx-grid-column-handle{height:calc(var(--hfx-space-1,0.25rem)*7);border:0;background:none;cursor:grab;touch-action:none;}
71
+ .cx-grid-column-choice.cx-drop-before{box-shadow:inset 0 var(--hfx-space-0-5,2px) var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
72
+ .cx-grid-column-choice.cx-drop-after{box-shadow:inset 0 calc(var(--hfx-space-0-5,2px)*-1) var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
73
+ .cx-grid-column-actions{display:flex;justify-content:space-between;margin-top:var(--hfx-space-1,0.25rem);padding-top:var(--hfx-space-1,0.25rem);border-top:var(--hfx-border-width,1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
68
74
  .cx-grid-column-actions .cx-button{border:0;color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));background:none;}
69
- .cx-drawer{width:100%;max-width:var(--cx-size-440px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));box-shadow:var(--hfx-elevation-2,0 1px 2px rgba(22,24,28,.05),0 6px 18px -10px rgba(22,24,28,.18));font:var(--cx-size-14px)/1.45 var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));overflow:hidden;}
70
- .cx-drawer-h{display:flex;align-items:flex-start;gap:var(--cx-size-12px);padding:var(--cx-size-14px) var(--cx-size-16px);border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
71
- .cx-drawer-h h4{margin:0;font-size:var(--cx-size-17px);width:fit-content;}
72
- .cx-drawer-h p{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--cx-size-13px);}
73
- .cx-drawer-h .cx-btn{margin-left:auto;}
74
- .cx-dl{display:grid;grid-template-columns:var(--cx-size-140px) 1fr;gap:var(--cx-size-8px) var(--cx-size-16px);padding:var(--cx-size-14px) var(--cx-size-16px);margin:0;}
75
- .cx-dl dt{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--cx-size-13px);padding-top:var(--cx-size-1px);}
75
+ @layer hfx.components{
76
+ .cx-drawer-h h4{width:fit-content;}
77
+ .cx-drawer-h p{color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-size:var(--hfx-type-small-size,0.8125rem);}
78
+ .cx-drawer-h .cx-btn{margin-inline-start:auto;}
79
+ .cx-dl{display:grid;grid-template-columns:calc(var(--hfx-space-1,0.25rem)*35) 1fr;gap:var(--hfx-space-2,0.5rem) var(--hfx-space-4,1rem);padding:calc(var(--hfx-space-1,0.25rem)*3.5) 0;margin:0;}
80
+ .cx-dl dt{color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-size:var(--hfx-type-small-size,0.8125rem);padding-block-start:var(--hfx-border-width,1px);}
76
81
  .cx-dl dd{margin:0;}
77
- .cx-drawer-s{padding:var(--cx-size-4px) var(--cx-size-16px) 0;font-size:var(--cx-size-11d5px);letter-spacing:var(--cx-size-d06em);text-transform:uppercase;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-weight:700;}
78
- body .cx-host.cx-drawer{position:fixed;left:auto;right:var(--cx-size-12px);top:var(--cx-size-12px);bottom:var(--cx-size-12px);margin:0;width:calc(100% - var(--cx-size-24px));max-width:var(--cx-size-440px);height:calc(100% - var(--cx-size-24px));padding:0;display:flex;flex-direction:column;z-index:1000;}
79
- .cx-drawer-body{overflow:auto;flex:1;}
80
- .cx-drawer .cx-drawer-h > div{flex:1;min-width:0;}
81
- .cx-drawer .cx-drawer-h{flex:none;}
82
- .cx-drawer .cx-drawer-h p{margin:var(--cx-size-4px) 0 0;overflow-wrap:anywhere;}
83
- .cx-drawer dd{overflow-wrap:anywhere;min-width:0;}
82
+ .cx-drawer-s{padding:var(--hfx-space-1,0.25rem) 0 0;font-size:calc(var(--hfx-type-caption-size,0.75rem)*.9583);letter-spacing:.06em;text-transform:uppercase;color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-weight:700;}
83
+ .cx-drawer .cx-drawer-h > div{flex:1;min-inline-size:0;}
84
+ .cx-drawer .cx-drawer-h p{margin:var(--hfx-space-1,0.25rem) 0 0;overflow-wrap:anywhere;}
85
+ .cx-drawer dd{overflow-wrap:anywhere;min-inline-size:0;}
84
86
  .cx-drawer .cx-button{flex:none;}
85
- .cx-drawer :is(.p-strip,.p-spark,.p-line){max-width:100%;}
86
- body .cx-host.cx-drawer.cx-phone{inset:0;width:100%;max-width:none;height:100%;max-height:none;border-radius:var(--hfx-radius-none,0);}
87
- .cx-drawer.cx-phone .cx-dl{grid-template-columns:1fr;gap:var(--cx-size-2px) 0;}
88
- .cx-drawer.cx-phone dd{margin-bottom:var(--cx-size-8px);}
89
- .cx-drawer.cx-phone .cx-button{min-height:var(--cx-size-44px);min-width:var(--cx-size-44px);}
90
- .cx-drawer::backdrop{background:var(--hfx-color-overlay,light-dark(rgba(22,24,28,0.42),rgba(0,0,0,0.66)));}
91
- .cx-grid-overlay{color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem))/1.45 var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);}
92
- body .cx-host.cx-grid-overlay{height:auto;min-height:0;padding:0;}
87
+ .cx-drawer :is(.p-strip,.p-spark,.p-line){max-inline-size:100%;}
88
+ .cx-drawer[data-phone="true"] .cx-dl{grid-template-columns:1fr;gap:var(--hfx-space-0-5,2px) 0;}
89
+ .cx-drawer[data-phone="true"] dd{margin-block-end:var(--hfx-space-2,0.5rem);}
90
+ .cx-drawer[data-phone="true"] .cx-button{min-block-size:calc(var(--hfx-space-1,0.25rem)*11);min-inline-size:calc(var(--hfx-space-1,0.25rem)*11);}
91
+ }
92
+ .cx-grid-overlay{color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));font:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem))/1.45 var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);}
93
+ body .cx-host.cx-grid-overlay:not(.cx-drawer){height:auto;min-height:0;padding:0;}
93
94
  .cx-grid-overlay [hidden]{display:none!important;}
94
95
  .cx-tree-tools.cx-pin-tree .cx-row > .cx-cell.cx-tree:first-child{position:sticky;}
95
96
  .cx-tree-tools .cx-row > [data-cx-pin]{position:sticky;z-index:1;background:inherit;}
@@ -98,7 +99,7 @@ body .cx-host.cx-grid-overlay{height:auto;min-height:0;padding:0;}
98
99
  .cx-tree-tools .cx-hcell[aria-sort="ascending"] .cx-sort::after{content:"↑";font-size:var(--cx-size-14px);color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
99
100
  .cx-tree-tools .cx-hcell[aria-sort="descending"] .cx-sort::after{content:"↓";font-size:var(--cx-size-14px);color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
100
101
  .cx-tree-tools .cx-switch{font-size:var(--cx-size-14px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));white-space:nowrap;}
101
- .cx-tree-tools .cx-hidden-fields{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font:var(--cx-size-12d5px) var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);border:0;background:transparent;padding:0;flex:none;height:auto;min-height:var(--cx-size-24px);min-width:var(--cx-size-24px);margin-left:var(--cx-size-4px);position:relative;}
102
+ .cx-tree-tools .cx-hidden-fields{color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font:var(--cx-size-12d5px) var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);border:0;background:transparent;padding:0;flex:none;height:auto;min-height:var(--cx-size-24px);min-width:var(--cx-size-24px);margin-left:var(--cx-size-4px);position:relative;}
102
103
  .cx-tree-tools.cx-drawer :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);}
103
104
  .cx-tree-tools.cx-drawer [data-cx-pointer-focus]:focus-visible{outline:none;}
104
- .cx-tree-tools.cx-drawer .p-sub{margin-inline-start:var(--cx-size-6px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--cx-size-12d5px);}
105
+ .cx-tree-tools.cx-drawer .p-sub{margin-inline-start:var(--cx-size-6px);color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));font-size:var(--cx-size-12d5px);}