@evotecit/canopyx 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CanopyX.Html/Assets/canopyx-calendar-edit.js +113 -0
- package/CanopyX.Html/Assets/canopyx-calendar-ics.js +87 -0
- package/CanopyX.Html/Assets/canopyx-calendar-recurrence.js +36 -0
- package/CanopyX.Html/Assets/canopyx-calendar.css +279 -0
- package/CanopyX.Html/Assets/canopyx-calendar.js +307 -0
- package/CanopyX.Html/Assets/canopyx-cell-range.css +38 -0
- package/CanopyX.Html/Assets/canopyx-cell-range.js +141 -0
- package/CanopyX.Html/Assets/canopyx-column-groups.css +18 -0
- package/CanopyX.Html/Assets/canopyx-column-groups.js +51 -0
- package/CanopyX.Html/Assets/canopyx-data.js +14 -0
- package/CanopyX.Html/Assets/canopyx-detail-rows.css +18 -0
- package/CanopyX.Html/Assets/canopyx-detail-rows.js +51 -0
- package/CanopyX.Html/Assets/canopyx-editing.css +44 -0
- package/CanopyX.Html/Assets/canopyx-editing.js +134 -0
- package/CanopyX.Html/Assets/canopyx-enhance.js +126 -0
- package/CanopyX.Html/Assets/canopyx-export.js +18 -0
- package/CanopyX.Html/Assets/canopyx-facets.css +86 -0
- package/CanopyX.Html/Assets/canopyx-facets.js +65 -0
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +15 -18
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +23 -17
- package/CanopyX.Html/Assets/canopyx-format-editor.css +77 -0
- package/CanopyX.Html/Assets/canopyx-format-editor.js +30 -0
- package/CanopyX.Html/Assets/canopyx-formatting.css +40 -0
- package/CanopyX.Html/Assets/canopyx-formatting.js +101 -0
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +352 -246
- package/CanopyX.Html/Assets/canopyx-grid.css +139 -117
- package/CanopyX.Html/Assets/canopyx-grid.js +352 -246
- package/CanopyX.Html/Assets/canopyx-grouping.css +39 -0
- package/CanopyX.Html/Assets/canopyx-grouping.js +85 -0
- package/CanopyX.Html/Assets/canopyx-highlight.css +34 -0
- package/CanopyX.Html/Assets/canopyx-highlight.js +80 -0
- package/CanopyX.Html/Assets/canopyx-history.js +13 -0
- package/CanopyX.Html/Assets/canopyx-interactive.css +18 -6
- package/CanopyX.Html/Assets/canopyx-interactive.js +179 -100
- package/CanopyX.Html/Assets/canopyx-labels-de.js +304 -0
- package/CanopyX.Html/Assets/canopyx-labels-es.js +304 -0
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +529 -0
- package/CanopyX.Html/Assets/canopyx-labels-it.js +529 -0
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +304 -0
- package/CanopyX.Html/Assets/canopyx-layouts.css +48 -0
- package/CanopyX.Html/Assets/canopyx-layouts.js +39 -0
- package/CanopyX.Html/Assets/canopyx-link.css +19 -0
- package/CanopyX.Html/Assets/canopyx-link.js +38 -0
- package/CanopyX.Html/Assets/canopyx-links.js +14 -0
- package/CanopyX.Html/Assets/canopyx-live.css +24 -0
- package/CanopyX.Html/Assets/canopyx-live.js +88 -0
- package/CanopyX.Html/Assets/canopyx-module.mjs +180 -100
- package/CanopyX.Html/Assets/canopyx-pager.css +10 -0
- package/CanopyX.Html/Assets/canopyx-pager.js +14 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.css +111 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.js +178 -0
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +406 -342
- package/CanopyX.Html/Assets/canopyx-reporting.css +140 -135
- package/CanopyX.Html/Assets/canopyx-reporting.js +406 -342
- package/CanopyX.Html/Assets/canopyx-search.js +32 -0
- package/CanopyX.Html/Assets/canopyx-timeline.css +80 -0
- package/CanopyX.Html/Assets/canopyx-timeline.js +88 -0
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +103 -0
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +92 -0
- package/CanopyX.Html/Assets/canopyx.css +17 -5
- package/CanopyX.Html/Assets/canopyx.js +175 -96
- package/JavaScript/calendar.d.ts +362 -0
- package/JavaScript/cell-ranges.d.ts +76 -0
- package/JavaScript/column-groups.d.ts +32 -0
- package/JavaScript/editing.d.ts +257 -0
- package/JavaScript/enhance.d.ts +202 -0
- package/JavaScript/facets.d.ts +58 -0
- package/JavaScript/formatting.d.ts +88 -0
- package/JavaScript/grid.d.ts +409 -56
- package/JavaScript/hosts.d.ts +177 -2
- package/JavaScript/index.d.ts +53 -4
- package/JavaScript/live.d.ts +115 -0
- package/JavaScript/locales/de.mjs +304 -0
- package/JavaScript/locales/es.mjs +304 -0
- package/JavaScript/locales/fr.d.ts +6 -0
- package/JavaScript/locales/fr.mjs +527 -0
- package/JavaScript/locales/it.d.ts +6 -0
- package/JavaScript/locales/it.mjs +527 -0
- package/JavaScript/locales/pl.mjs +304 -0
- package/JavaScript/plugins.d.ts +113 -0
- package/JavaScript/protocol.d.ts +139 -6
- package/JavaScript/records.d.ts +136 -0
- package/README.md +61 -9
- package/README.nuget.md +1 -1
- package/package.json +99 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"521eebd6e1bbbd35",install(context){if(installed.has(context.SEARCH_IMPL))return;const{SEARCH_IMPL,checkDocument,badIndex,isCount,isIdentifier,recentCache,packBytes,shardKey,foldText,trimSeparators,rankHits,validateSearchHit,PACK_CACHE,PACK_CACHE_BYTES,SHARD_CACHE,ENTRY_CACHE,ENTRY_BATCH,SEARCH_CANDIDATES}=context;function resolveShards(shards,keys,word){const bases=keys.filter((key)=>!/\.\d+$/.test(key));
|
|
2
|
+
const parts=(selected)=>selected.flatMap((key)=>[key].concat(keys.filter((part)=>part.startsWith(key+"."))
|
|
3
|
+
.sort((a,b)=>Number(a.slice(a.lastIndexOf(".")+ 1))- Number(b.slice(b.lastIndexOf(".")+ 1)))));for(let length=Math.min(2,word.length);length<=word.length;length++){const key=shardKey(word.slice(0,length));if(Object.hasOwn(shards,key))return parts([key]);const deeper=bases.filter((k)=>k.length>key.length&&k.startsWith(key));if(!deeper.length)return[];if(length===word.length)return parts(deeper)}
|
|
4
|
+
return[]}
|
|
5
|
+
function checkShard(doc,key,count,entryCount){checkDocument(doc,"searchShard");if(doc.key!==key)throw badIndex("shard key");if(!Array.isArray(doc.words)||!Array.isArray(doc.postings)||doc.words.length!==doc.postings.length)throw badIndex("shard");let total=0;doc.postings.forEach((list,i)=>{if(typeof doc.words[i]!=="string"||!Array.isArray(list)||!isCount(list[0]))throw badIndex("shard");let last=list[0];for(let j=1;j<list.length;j++){if(!Number.isInteger(list[j])||!list[j])throw badIndex("shard");last +=Math.abs(list[j]);total +=list[j]<0?-list[j]- 1:0}
|
|
6
|
+
total +=list.length;if(last>=entryCount)throw badIndex("shard")});if(total!==count)throw badIndex("shard posting count");return doc}
|
|
7
|
+
function mergePostings(lists){const out=[];let ascending=true;for(const list of lists){let value=0;list.forEach((step,i)=>{for(let n=i&&step<0?-step:1;n>0;n--){value=i?value +(step<0?1:step):step;if(out.length&&value<=out[out.length-1])ascending=false;out.push(value)}})}
|
|
8
|
+
if(ascending)return out;out.sort((a,b)=>a-b);return out.filter((value,i)=>!i||value!==out[i-1])}
|
|
9
|
+
function intersectPostings(a,b){let j=0;return a.filter((value)=>{while(j<b.length&&b[j]<value)j++;return b[j]===value})}
|
|
10
|
+
function labelToken(folded){let hash=2166136261;for(let i=0;i<folded.length;i++){hash=Math.imul(hash^folded.charCodeAt(i),16777619)}
|
|
11
|
+
return "\u0000" +("0000000" +(hash>>>0).toString(16)).slice(-8)}
|
|
12
|
+
function entryReference(value){return value===undefined||value===null||isIdentifier(value)}
|
|
13
|
+
function entryFile(doc,first,count){checkDocument(doc,"searchEntries");if(doc.first!==first||!Array.isArray(doc.stem)||!Array.isArray(doc.entries)||doc.entries.length!==count)throw badIndex("entry file");const stem=new Map(doc.stem.map((item)=>(Array.isArray(item)?[item[0],item.slice(1)]:[])));const records=new Map();const raw=(n)=>{const item=n>=first&&n<first+count?doc.entries[n-first]:stem.get(n);if(!Array.isArray(item)||item.length<5||item.length>8||!Number.isInteger(item[0])||item[0]<-1||item[0]>=n||
|
|
14
|
+
!isCount(item[1])||typeof item[2]!=="string"||!isCount(item[3])||typeof item[4]!=="string"||
|
|
15
|
+
(item[5]!=null&&!isCount(item[5]))||!entryReference(item[6])||!(item[7]===undefined||isIdentifier(item[7]))){throw badIndex("entry "+n)}
|
|
16
|
+
return item};return(n)=>{const pending=[];for(let k=n;k>=0&&!records.has(k);k=raw(k)[0])pending.push(k);while(pending.length){const number=pending.pop();const item=raw(number);const parent=item[0]<0?null:records.get(item[0]);const base=parent?parent.id:"";if(item[1]+ item[3]>base.length)throw badIndex("entry "+number);records.set(number,{parent,id:base.slice(0,item[1])+ item[2]+ base.slice(base.length-item[3]),label:item[4],kind:item[5]==null?undefined:item[5],ref:item[6]||null,at:item[7]||null})}
|
|
17
|
+
return records.get(n)}}
|
|
18
|
+
function entryHit(record,kinds){const path=[];for(let r=record;r;r=r.parent)path.unshift(r.id);const hit={path,label:record.label};if(record.kind!==undefined){if(record.kind>=kinds.length)throw badIndex("entry kind");hit.kind=kinds[record.kind]}
|
|
19
|
+
const parent=record.parent;if(parent)hit.context=parent.parent?parent.parent.label+" / "+parent.label:parent.label;validateSearchHit(hit);return hit}
|
|
20
|
+
function entryFileOf(starts,n){let low=0;let high=starts.length-1;while(low<high){const mid=(low+high+1)>>1;if(starts[mid]<=n)low=mid;else high=mid-1}
|
|
21
|
+
return low}
|
|
22
|
+
function sidecarSearch(load,manifest,hints){const index=async()=>(await manifest()).search;const loadPack=recentCache(PACK_CACHE,async(number)=>{const doc=checkDocument(await load("q/"+number),"pack");if(!Array.isArray(doc.pages)||doc.pages.some(text=>typeof text!=="string"))throw badIndex("pack");return doc.pages},PACK_CACHE_BYTES,packBytes);const sortedKeys=new WeakMap();const packed=async(pack,slot)=>{const text=(await loadPack(pack))[slot];if(typeof text!=="string")throw badIndex("pack");return JSON.parse(text)};const loadIndexDoc=async(search,kind,name)=>{if(!search.entryPacks)return load(kind==="e"?"e/"+name:"s/k-"+name);if(kind==="e"){const pack=entryFileOf(search.entryPacks,name);return packed(pack,name-search.entryPacks[pack])}
|
|
23
|
+
let keys=sortedKeys.get(search);if(!keys)sortedKeys.set(search,keys=Object.keys(search.shards).sort());let pack=0;while(pack+1<search.shardPacks.length&&search.shardPacks[pack+1]<=name)pack++;return packed(search.entryPacks.length+pack,keys.indexOf(name)- keys.indexOf(search.shardPacks[pack]))};const loadShard=recentCache(SHARD_CACHE,async(key)=>{const search=await index();return checkShard(await loadIndexDoc(search,"s",key),key,search.shards[key],search.entryCount)});const loadEntries=recentCache(ENTRY_CACHE,async(file)=>{const search=await index();const first=search.entryFiles[file];const end=file+1<search.entryFiles.length?search.entryFiles[file+1]:search.entryCount;return entryFile(await loadIndexDoc(search,"e",file),first,end-first)});async function postingsOf(search,keys,word){const lists=[];for(const shard of await Promise.all(resolveShards(search.shards,keys,word).map(loadShard))){shard.words.forEach((indexed,i)=>indexed.startsWith(word)&&lists.push(shard.postings[i]))}
|
|
24
|
+
return mergePostings(lists)}
|
|
25
|
+
async function run(query,queryWords,limit,sequence){const search=await index();if(!search){return{hits:[],total:0,truncated:false}}
|
|
26
|
+
const keyWords=queryWords.filter((word,i)=>queryWords.indexOf(word)===i&&
|
|
27
|
+
!queryWords.some((other)=>other.length>word.length&&other.startsWith(word)));const keys=Object.keys(search.shards);const folded=trimSeparators(foldText(query));const[exact,lists]=await Promise.all([postingsOf(search,keys,labelToken(folded)),Promise.all(keyWords.map((word)=>postingsOf(search,keys,word)))]);const candidates=lists.sort((a,b)=>a.length-b.length).reduce(intersectPostings);const order=exact.concat(candidates);const wanted=limit*SEARCH_CANDIDATES;const taken=new Set();const hits=[];const records=new Map();let next=0;while(next<order.length&&hits.length<limit){const files=[];let end=next;for(;end<order.length&&hits.length+end-next<wanted;end++){const file=entryFileOf(search.entryFiles,order[end]);if(files.indexOf(file)<0){if(files.length>=ENTRY_BATCH&&hits.length+end-next>=limit)break;files.push(file)}}
|
|
28
|
+
const loaded=await Promise.all(files.map(loadEntries));for(;next<end;next++){const number=order[next];if(taken.has(number))continue;const record=loaded[files.indexOf(entryFileOf(search.entryFiles,number))](number);if(next>=exact.length||trimSeparators(foldText(record.label))===folded){taken.add(number);const hit=entryHit(record,search.kinds);records.set(hit,record);hits.push(hit)}}}
|
|
29
|
+
const ranked=rankHits(hits,query,limit);ranked.total=candidates.length;ranked.truncated=candidates.length>ranked.hits.length;if(sequence===latest){hints.clear();ranked.hits.forEach((hit)=>{for(let r=records.get(hit);r;r=r.parent)hints.set(r.id,r)})}
|
|
30
|
+
return ranked}
|
|
31
|
+
let latest=0;return(query,queryWords,limit)=>run(query,queryWords,limit,++latest).catch((err)=>{loadShard.clear();loadEntries.clear();loadPack.clear();throw err})}
|
|
32
|
+
SEARCH_IMPL.create=sidecarSearch;installed.add(context.SEARCH_IMPL)}};(global.CanopyXParts||=[]).push(["search",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* Resource timeline: the resource tree at the start,the time header and lanes after it,sharing rows. */
|
|
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
|
+
.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(--cx-line);}
|
|
5
|
+
.cx-tl-side > .cx-tl-tree.cx-host{flex:1 1 auto;height:auto;min-height:0;border:0;border-radius:0;--cx-head-h:var(--cx-tl-head-h,57px);}
|
|
6
|
+
.cx-tl-tree.cx-host > .cx-grid{overflow-y:hidden;overflow-x:scroll;border:0;border-radius:0;}
|
|
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
|
+
.cx-tl-tree .cx-tl-agg{justify-content:flex-end;font-variant-numeric:tabular-nums;color:var(--cx-text-2);}
|
|
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(--cx-head-bg);border-bottom:var(--cx-size-1px) solid var(--cx-line);}
|
|
11
|
+
.cx-tl-hrow{position:relative;height:var(--cx-size-28px);}
|
|
12
|
+
.cx-tl-upper{border-bottom:var(--cx-size-1px) solid var(--cx-line);}
|
|
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(--cx-line);font-size:var(--cx-size-12px);color:var(--cx-text-2);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(--cx-text);}
|
|
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
|
+
.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(--cx-text) 5%,transparent);}
|
|
18
|
+
.cx-tl-range-labels{position:relative;height:var(--cx-size-20px);border-top:var(--cx-size-1px) solid var(--cx-line);}
|
|
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(--cx-radius-sm);background:color-mix(in srgb,var(--cx-tone-info) 14%,var(--cx-surface));font-size:var(--cx-size-11d5px);line-height:var(--cx-size-16px);color:var(--cx-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
21
|
+
.cx-tl-canvas{position:relative;}
|
|
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(--cx-text) 3.5%,transparent);}
|
|
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
|
+
: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
|
+
.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(--cx-tone-danger);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(--cx-line) 70%,transparent);}
|
|
28
|
+
.cx-tl-lane.cx-tl-group{background:color-mix(in srgb,var(--cx-text) 2.5%,transparent);}
|
|
29
|
+
.cx-tl-cell{position:absolute;top:0;bottom:0;pointer-events:none;outline:none;}
|
|
30
|
+
.cx-tl-cell:focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:calc(-1 * var(--cx-size-2px));z-index:5;}
|
|
31
|
+
.cx-tl-cell[aria-selected="true"]{background:var(--cx-selected-bg);}
|
|
32
|
+
.cx-tl-lane .cx-cal-ev-lane{position:absolute;z-index:2;pointer-events:auto;padding:0 var(--cx-size-6px);font-size:var(--cx-size-12px);line-height:1.2;}
|
|
33
|
+
.cx-tl-lane .cx-cal-ev-lane > .cx-cal-ev-sub{display:none;}
|
|
34
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-thin{font-size:var(--cx-size-11px);padding:0 var(--cx-size-4px);}
|
|
35
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-narrow{padding:0;justify-content:center;}
|
|
36
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-narrow > *{display:none;}
|
|
37
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-tiny{background:var(--cx-ev);box-shadow:none;}
|
|
38
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-point{width:auto!important;max-width:var(--cx-size-180px);padding-inline-start:var(--cx-size-14px);margin-inline-start:calc(-1 * var(--cx-size-6px));background:transparent;box-shadow:none;overflow:visible;}
|
|
39
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-point::before{content:"";position:absolute;inset-inline-start:var(--cx-size-2px);top:50%;width:var(--cx-size-8px);height:var(--cx-size-8px);margin-top:calc(-1 * var(--cx-size-4px));transform:rotate(45deg);background:var(--cx-ev);border-radius:var(--cx-size-1px);}
|
|
40
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-point > *{display:none;}
|
|
41
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-point > .cx-cal-ev-title{display:block;overflow:hidden;text-overflow:ellipsis;}
|
|
42
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-point.cx-tl-bare{width:var(--cx-size-14px)!important;padding-inline-start:0;}
|
|
43
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-point.cx-tl-bare > .cx-cal-ev-title{display:none;}
|
|
44
|
+
.cx-tl-shade{position:absolute;top:0;bottom:0;pointer-events:none;overflow:hidden;overflow:clip;}
|
|
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(--cx-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
46
|
+
.cx-tl-shade.cx-tl-off{background:color-mix(in srgb,var(--cx-text) 4.5%,transparent);}
|
|
47
|
+
:is(.cx-tl-shade,.cx-tl-range).cx-tl-unavailable{background:repeating-linear-gradient(135deg,color-mix(in srgb,var(--cx-text) 9%,transparent) 0 var(--cx-size-6px),transparent var(--cx-size-6px) var(--cx-size-12px));box-shadow:none;}
|
|
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
|
+
: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(--cx-surface);top:var(--cx-size-5px);bottom:var(--cx-size-5px);display:grid;place-items:center;border-radius:var(--cx-radius-sm);font-size:var(--cx-size-11d5px);font-weight:600;color:var(--cx-text);font-variant-numeric:tabular-nums;overflow:hidden;isolation:isolate;}
|
|
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(--cx-accent));opacity:calc(.12 + var(--cx-heat,0) * .38);}
|
|
52
|
+
.cx-tl-heat[data-cx-tone]::before{opacity:calc(.28 + var(--cx-heat,0) * .42);}
|
|
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(--cx-radius-sm);background:var(--cx-surface);white-space:nowrap;box-shadow:var(--cx-shadow-1,0 1px 3px rgb(0 0 0 / 18%));}
|
|
55
|
+
.cx-tl-print{display:none;}
|
|
56
|
+
.cx-cal-phone .cx-tl{--cx-tl-side-w:176px;}
|
|
57
|
+
.cx-cal-phone .cx-tl-tree .cx-hidden-fields{display:none;}
|
|
58
|
+
@media (forced-colors:active){
|
|
59
|
+
.cx-tl-heat{forced-color-adjust:none;border:var(--cx-size-1px) solid CanvasText;background:Canvas;color:CanvasText;}
|
|
60
|
+
.cx-tl-heat::before{display:none;}
|
|
61
|
+
.cx-tl-heat[data-cx-tone]{border-width:var(--cx-size-2px);font-weight:700;}
|
|
62
|
+
.cx-tl-now{forced-color-adjust:none;background:Highlight;}
|
|
63
|
+
.cx-tl-cell[aria-selected="true"]{forced-color-adjust:none;background:Highlight;}
|
|
64
|
+
.cx-tl-lane .cx-cal-ev-lane.cx-tl-point::before,.cx-tl-lane .cx-cal-ev-lane.cx-tl-tiny{forced-color-adjust:none;background:CanvasText;}
|
|
65
|
+
}
|
|
66
|
+
@media print{
|
|
67
|
+
.cx-tl > :is(.cx-tl-side,.cx-tl-main){display:none!important;}
|
|
68
|
+
.cx-tl{display:block;height:auto;}
|
|
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(--cx-line);break-inside:avoid;}
|
|
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(--cx-text) 4%,transparent);font-weight:600;}
|
|
73
|
+
.cx-tl-print-name{padding:var(--cx-size-2px) var(--cx-size-4px);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}
|
|
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(--cx-line);overflow:hidden;white-space:nowrap;}
|
|
76
|
+
.cx-tl-print-bar.cx-tl-print-tiny{background:var(--cx-ev,var(--cx-accent));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(--cx-accent)) 22%,#fff);box-shadow:inset var(--cx-size-2px) 0 0 var(--cx-ev,var(--cx-accent));overflow:hidden;white-space:nowrap;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
|
|
78
|
+
:where(.cx-cal-rtl) .cx-tl-print-bar{box-shadow:inset calc(-1 * var(--cx-size-2px)) 0 0 var(--cx-ev,var(--cx-accent));}
|
|
79
|
+
}
|
|
80
|
+
@media (forced-colors:active){.cx-tl-ghost > .cx-tl-ghost-label{background:Canvas;color:CanvasText;border-color:CanvasText;}}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"3f04ba99401e9ebd",requires:["calendar"],install(context){if(installed.has(context.DataGrid.prototype))return;const{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
|
+
if(zoom==="week"){const parts=calDayParts(date),quarter=calDayNumber(parts.y,Math.floor((parts.m-1)/ 3) * 3 + 1, 1);
|
|
3
|
+
return{firstDay:calWeekStart(quarter,firstDay),lastDay:calWeekStart(calAddMonths(quarter,3)- 1,firstDay)+ 6}}
|
|
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}}
|
|
5
|
+
function tlCustomSpan(span,date,firstDay){if(span.unit==="day")return{firstDay:date,lastDay:date+span.count-1};if(span.unit==="week"){const first=calWeekStart(date,firstDay);return{firstDay:first,lastDay:first+7*span.count-1}}
|
|
6
|
+
const month=calMonthStart(date);return{firstDay:month,lastDay:calAddMonths(month,span.count)- 1}}
|
|
7
|
+
function tlCustomStep(span,date,direction){return span.unit==="month"?calAddMonths(date,span.count*direction):date +(span.unit==="week"?7:1)*span.count*direction}
|
|
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
|
+
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
|
+
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}
|
|
12
|
+
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
|
+
},time(x){const index=Math.max(0,Math.min(units.length-1,Math.floor(x / width))), unit = units[index];
|
|
14
|
+
return unit.start+Math.max(0,Math.min(1,(x-unit.x)/ width)) * (unit.end - unit.start);
|
|
15
|
+
},unitOf}}
|
|
16
|
+
function tlHeader(view,axis){const fmt=view.calFmt,upper=[],lower=[],zoom=axis.zoom;const group=(key,text,label,unit)=>{const last=upper[upper.length-1];if(last&&last.key===key)last.width +=axis.width;else upper.push({key,x:unit.x,width:axis.width,text,label})};for(const unit of axis.units){let text,label;if(zoom==="hour"){const minutes=view.calZone.parts(unit.start).minutes;text=fmt.hour(minutes);label=fmt.longDay(unit.first)+ " "+fmt.clock(minutes);group(unit.first,fmt.longDay(unit.first),fmt.longDay(unit.first),unit)}
|
|
17
|
+
else if(zoom==="day"){text=fmt.dayNumber(unit.first);label=fmt.longDay(unit.first);group(calMonthStart(unit.first),fmt.monthTitle(unit.first),fmt.monthTitle(unit.first),unit)}
|
|
18
|
+
else if(zoom==="week"){text=fmt.shortDay(unit.first);label=fmt.dayRange(unit.first,unit.last);group(calMonthStart(unit.first),fmt.monthTitle(unit.first),fmt.monthTitle(unit.first),unit)}
|
|
19
|
+
else if(zoom==="month"){text=fmt.monthShort(unit.first);label=fmt.monthTitle(unit.first);group(calDayParts(unit.first).y,fmt.year(unit.first),fmt.year(unit.first),unit)}
|
|
20
|
+
else{text=fmt.range({month:"short"},unit.first,unit.last);label=fmt.monthRange(unit.first,unit.last);group(calDayParts(unit.first).y,fmt.year(unit.first),fmt.year(unit.first),unit)}
|
|
21
|
+
const dow=calDow(unit.first),off=view.cal.working?!view.cal.working.days.has(dow):dow===0||dow===6;lower.push({x:unit.x,width:axis.width,text,label,weekend:zoom==="day"&&off,unit})}
|
|
22
|
+
return{upper,lower}}
|
|
23
|
+
Object.assign(DataGrid.prototype,{startTimeline(){if(this.tl)return;const resources=this.cal.resources;this.tl={names:new Map(),parent:new Map(),children:new Map(),order:[],learned:new Set(),stats:null,heat:new Map()};this.tlSolo=!resources;if(this.tlSolo){this.tlInline=true;return}
|
|
24
|
+
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
|
+
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||leaves.length>24)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.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
|
+
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);host.setAttribute("data-cx-theme",this.host.getAttribute("data-cx-theme")||"auto");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
|
+
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
|
+
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&&ids.has(item.resource));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
|
+
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
|
+
this.tlScrollTo(Math.max(0,target))}
|
|
33
|
+
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}});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}
|
|
34
|
+
if(this.tlSolo)return this.tlIndexSolo(backgrounds);for(const event of this.calEvents){const target=event.background?backgrounds:byResource,key=event.resource??"";if(!target.has(key))target.set(key,[]);target.get(key).push(event)}
|
|
35
|
+
for(const list of byResource.values()){list.sort((a,b)=>a.tlStart-b.tlStart||b.tlEnd-a.tlEnd);const ends=[];for(const event of list){let lane=ends.findIndex(end=>end<=event.tlStart);if(lane<0){lane=ends.length;ends.push(0)}
|
|
36
|
+
ends[lane]=Math.max(event.tlEnd,event.tlStart+1);event.tlLane=lane}
|
|
37
|
+
list.lanes=Math.max(1,ends.length)}
|
|
38
|
+
this.tl.stats=null;return{byResource,backgrounds}},tlIndexSolo(backgrounds){const byResource=new Map(),ends=[],tree=this.tlTree,events=this.calEvents.filter(event=>!event.background).sort((a,b)=>a.tlStart-b.tlStart||b.tlEnd-a.tlEnd);for(const event of this.calEvents)if(event.background){if(!backgrounds.has(""))backgrounds.set("",[]);backgrounds.get("").push(event)}
|
|
39
|
+
for(const event of events){let lane=ends.findIndex(end=>end<=event.tlStart);if(lane<0){lane=ends.length;ends.push(0)}
|
|
40
|
+
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)}
|
|
41
|
+
byResource.get(key).push(event)}
|
|
42
|
+
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;
|
|
43
|
+
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)}
|
|
44
|
+
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)}
|
|
45
|
+
if(lane.parentNode!==canvas)canvas.appendChild(lane)}
|
|
46
|
+
for(const[key,lane]of lanes)if(!keep.has(key)){if(lane.contains(document.activeElement))continue;lane.remove();lanes.delete(key)}
|
|
47
|
+
this.tlPaintCanvas(left,right,total);this.calMarkSelection();if(this.calRoot.contains(document.activeElement)&&!this.calBody.contains(document.activeElement))return;if(!canvas.querySelector('[tabindex="0"]'))this.calRestoreFocus(false)},tlPaintLane(lane,row,height,left,right){lane.replaceChildren();if(row.status){lane.removeAttribute("aria-label");return}
|
|
48
|
+
const axis=this.tlAxis,id=row.key,group=this.tl.children.has(id),events=group?[]:this.tlIndex.byResource.get(id)||[];lane.classList.toggle("cx-tl-group",group);lane.dataset.cxResource=id;const name=this.calResourceName(id),count=group?this.tlStats(id).count:events.length;lane.setAttribute("aria-label",fill(this.calLabels.calendarLane,{resource:name,events:calCount(this,this.calLabels.calendarEvents,count)}));const cells=[];axis.units.forEach((unit,index)=>{if(unit.x+axis.width<=left||unit.x>right)return;const cell=h("div","cx-tl-cell");cell.setAttribute("role","gridcell");cell.tabIndex=-1;cell.dataset.cxDay=String(unit.first);cell.dataset.cxUnit=String(index);cell.dataset.cxResource=id;if(!this.calInValid({firstDay:unit.first,lastDay:unit.last})){cell.classList.add("cx-cal-invalid");cell.setAttribute("aria-disabled","true")}
|
|
49
|
+
cell.style.insetInlineStart=unit.x+"px";cell.style.width=axis.width+"px";cell.setAttribute("aria-label",name+", "+this.tlUnitLabel(unit));cells.push(cell);lane.appendChild(cell)});if(group){this.tlPaintHeat(lane,id,left,right);return}
|
|
50
|
+
this.tlPaintShade(lane,id,left,right);const stack=Math.min(TL_STACK,events.lanes||1),inner=height-6,bar=Math.max(6,inner / stack - (stack > 1 ? 2 : 0));
|
|
51
|
+
const firstVisible=cells.length?Number(cells[0].dataset.cxUnit):0;const nextInRow=new Map(),after=new Map();for(let i=events.length-1;i>=0;i--){const row=Math.min(events[i].tlLane,stack-1);nextInRow.set(events[i],after.get(row));after.set(row,events[i].tlStart)}
|
|
52
|
+
for(const event of events){if(event.tlEnd<axis.from||event.tlStart>=axis.to)continue;const x1=axis.x(event.tlStart),x2=event.tlEnd>event.tlStart?axis.x(event.tlEnd):x1;if(x2<left||x1>right)continue;const span=x2-x1,point=event.marker||span<1;const element=this.calEventElement(event,"lane"),slot=Math.min(event.tlLane,stack-1),room=nextInRow.get(event)===undefined?Infinity:axis.x(nextInRow.get(event))- x1-1,width=point?0:Math.max(Math.min(span,2),Math.min(Math.max(TL_MIN_BAR,span),room));const unit=Math.max(firstVisible,axis.unitOf(event.tlStart)),cell=cells.find(item=>Number(item.dataset.cxUnit)===unit)||cells[0];const offset=cell?Number.parseFloat(cell.style.insetInlineStart):0;element.style.insetInlineStart=(x1-offset)+ "px";element.style.width=width+"px";element.style.top=(3+slot*(inner / stack)) + "px"; element.style.height = bar + "px";
|
|
53
|
+
if(bar<16)element.classList.add("cx-tl-thin");if(point)element.classList.add("cx-tl-point");else if(span<TL_SOLID_BAR){element.classList.add("cx-tl-tiny");element.title=this.calEventName(event)}
|
|
54
|
+
if(point&&(axis.zoom!=="hour"||!event.marker)){element.classList.add("cx-tl-bare");element.title=this.calEventName(event)}
|
|
55
|
+
if(width<40)element.classList.add("cx-tl-narrow");if(event.tlStart<axis.from)element.classList.add("cx-cal-cont-start");if(event.tlEnd>axis.to)element.classList.add("cx-cal-cont-end");(cell||lane).appendChild(element)}},tlUnitLabel(unit){const lower=this.tlHeader?.lower.find(cell=>cell.unit===unit);return lower?lower.label:this.calFmt.longDay(unit.first)},tlPaintShade(lane,id,left,right){const axis=this.tlAxis,add=(start,end,cls,label,tone)=>{const x1=axis.x(start),x2=axis.x(end);if(x2<=x1||x2<left||x1>right)return;const block=h("div","cx-tl-shade "+cls);block.setAttribute("aria-hidden","true");block.style.insetInlineStart=x1+"px";block.style.width=(x2-x1)+ "px";if(tone)block.style.setProperty("--cx-bg-tone","var(--cx-tone-"+tone+",var(--cx-tone-info))");if(label&&x2-x1>60){const text=h("span");setText(text,label);block.appendChild(text)}
|
|
56
|
+
lane.appendChild(block)};if(axis.zoom==="hour")for(let day=axis.units[0].first;day<=axis.units[axis.units.length-1].last;day++){const hours=this.calHoursFor(id,calDow(day))??(this.cal.working?(this.cal.working.days.has(calDow(day))?[this.cal.working]:[]):null);if(hours){let at=0;for(const span of hours.slice().sort((a,b)=>a.start-b.start)){add(this.calZone.instant(day,at),this.calZone.instant(day,span.start),"cx-tl-off");at=Math.max(at,span.end)}add(this.calZone.instant(day,at),this.calZone.instant(day,1440),"cx-tl-off")}}
|
|
57
|
+
for(const range of this.calRanges)if(range.resource===id)add(range.start,range.end,range.kind==="unavailable"?"cx-tl-unavailable":"cx-tl-bg",range.label,range.kind==="unavailable"?null:range.tone);for(const event of this.tlIndex.backgrounds.get(id)||[])add(event.tlStart,event.tlEnd,"cx-tl-bg",event.title,event.tone||"info")},tlPaintCanvas(left,right,total){const axis=this.tlAxis,layer=this.tlLayer||=h("div","cx-tl-layer");layer.setAttribute("aria-hidden","true");layer.style.height=total+"px";const blocks=[];for(const cell of this.tlHeader.lower)if(cell.weekend&&cell.x+cell.width>=left&&cell.x<=right){const block=h("div","cx-tl-weekend-col");block.style.insetInlineStart=cell.x+"px";block.style.width=cell.width+"px";blocks.push(block)}
|
|
58
|
+
const global=[...this.calRanges.filter(range=>range.resource==null),...(this.tlIndex.backgrounds.get("")||[]).map(event=>({start:event.tlStart,end:event.tlEnd,label:event.title,tone:event.tone||"info",kind:"background"}))];for(const range of global){const x1=axis.x(range.start),x2=axis.x(range.end);if(x2<=x1||x2<left||x1>right)continue;const block=h("div","cx-tl-range" +(range.kind==="unavailable"?" cx-tl-unavailable":""));block.style.insetInlineStart=x1+"px";block.style.width=(x2-x1)+ "px";if(range.kind!=="unavailable")block.style.setProperty("--cx-bg-tone","var(--cx-tone-"+range.tone+",var(--cx-tone-info))");block.title=range.label;blocks.push(block)}
|
|
59
|
+
const now=Date.now();if(this.cal.now&&now>=axis.from&&now<axis.to){const line=h("div","cx-tl-now");line.style.insetInlineStart=axis.x(now)+ "px";line.title=this.calLabels.calendarNow+" "+this.calFmt.time(now);blocks.push(line)}
|
|
60
|
+
layer.replaceChildren(...blocks);if(layer.parentNode!==this.tlCanvas)this.tlCanvas.prepend(layer);const labels=this.tlRangeLabels||=h("div","cx-tl-range-labels"),named=global.filter(range=>axis.x(range.end)- axis.x(range.start)>50);labels.replaceChildren(...named.map(range=>{const label=h("span","cx-tl-range-label");label.style.insetInlineStart=axis.x(range.start)+ "px";label.style.width=(axis.x(range.end)- axis.x(range.start))+ "px";setText(label,range.label);label.title=range.label;return label}));if(labels.parentNode!==this.tlHead)this.tlHead.appendChild(labels);if(this.tlHead.classList.contains("cx-tl-has-ranges")!==named.length>0){this.tlHead.classList.toggle("cx-tl-has-ranges",named.length>0);this.tlRoot.style.setProperty("--cx-tl-head-h",named.length?"78px":"57px");this.tlTree.scheduleRender()}},calTickTimeline(){if(this.calView==="timeline")this.tlPaintCanvas(this.tlScrollX()- TL_MARGIN,this.tlScrollX()+ this.tlMain.clientWidth+TL_MARGIN,this.tlTree.tops[this.tlTree.rows.length]||0)},tlPaintHeat(lane,id,left,right){const axis=this.tlAxis,heat=this.tlHeat(id),thresholds=this.cal.capacity?.thresholds||[],most=Math.max(1,...heat);heat.forEach((value,index)=>{const unit=axis.units[index];if(!value||unit.x+axis.width<left||unit.x>right)return;const block=h("div","cx-tl-heat"),tone=thresholds.reduce((found,item)=>value>=item.at?item.tone:found,null);block.style.insetInlineStart=unit.x+"px";block.style.width=axis.width+"px";block.style.setProperty("--cx-heat",String(Math.min(1,value / most)));
|
|
61
|
+
if(tone){block.dataset.cxTone=tone;block.style.setProperty("--cx-bg-tone","var(--cx-tone-"+tone+",var(--cx-accent))")}
|
|
62
|
+
block.setAttribute("aria-hidden","true");block.title=fill(this.calLabels.calendarCapacityAt,{count:numberFormat(this.lang).format(value)});if(axis.width>=28)setText(block,numberFormat(this.lang).format(value));lane.appendChild(block)});lane.setAttribute("aria-label",lane.getAttribute("aria-label")+ ", "+this.calLabels.calendarCapacity+" "+fill(this.calLabels.calendarCapacityAt,{count:numberFormat(this.lang).format(Math.max(0,...heat))}))},tlHeat(id){if(this.tl.heat.has(id))return this.tl.heat.get(id);const axis=this.tlAxis,units=axis.units,points=[],out=new Array(units.length).fill(0);for(const leaf of[id,...this.tlDescendants(id)])for(const event of this.tlIndex.byResource.get(leaf)||[]){if(event.tlEnd<=axis.from||event.tlStart>=axis.to)continue;points.push([Math.max(event.tlStart,axis.from),1],[Math.max(event.tlEnd,event.tlStart+1),-1])}
|
|
63
|
+
points.sort((a,b)=>a[0]- b[0]||a[1]- b[1]);let level=0,unit=0;for(let i=0;i<points.length;i++){level +=points[i][1];const from=points[i][0],to=i+1<points.length?points[i+1][0]:from;if(to<=from||level<=0)continue;while(unit<units.length-1&&units[unit].end<=from)unit++;for(let at=unit;at<units.length&&units[at].start<to;at++)out[at]=Math.max(out[at],level)}
|
|
64
|
+
this.tl.heat.set(id,out);return out},tlStats(id){const cache=this.tl.stats||=new Map();if(cache.has(id))return cache.get(id);const axis=this.tlAxis,stats={count:0,busy:0,overlaps:0};let end=-Infinity,lastEnd=-Infinity,lastIndex=-1;const overlapped=new Set(),list=(this.tlIndex.byResource.get(id)||[]).filter(event=>event.tlEnd>axis.from&&event.tlStart<axis.to);list.forEach((event,index)=>{const from=Math.max(event.tlStart,axis.from),to=Math.min(event.tlEnd,axis.to);if(to>end){stats.busy +=to-Math.max(from,end);end=to}
|
|
65
|
+
if(event.tlStart<lastEnd){overlapped.add(index);overlapped.add(lastIndex)}
|
|
66
|
+
if(event.tlEnd>lastEnd){lastEnd=event.tlEnd;lastIndex=index}});stats.count=list.length;stats.overlaps=overlapped.size;for(const child of this.tl.children.get(id)||[]){const inner=this.tlStats(child);stats.count +=inner.count;stats.busy +=inner.busy;stats.overlaps +=inner.overlaps}
|
|
67
|
+
cache.set(id,stats);return stats},tlAggregateText(id,kind){if(!this.tlIndex)return "";const stats=this.tlStats(id),format=numberFormat(this.lang);if(kind==="busy")return format.format(Math.round(stats.busy / CAL_HOUR * 10) / 10) + " h";
|
|
68
|
+
return format.format(kind==="overlap"?stats.overlaps:stats.count)}});Object.assign(DataGrid.prototype,{calKeyTimeline(event,target,eventElement){const key=event.key,tree=this.tlTree,axis=this.tlAxis;const cell=eventElement?eventElement.closest(".cx-tl-cell"):target.closest(".cx-tl-cell");if(!cell||!tree||!axis)return;const unit=Number(cell.dataset.cxUnit),resource=cell.dataset.cxResource,rowIndex=tree.rows.findIndex(row=>row.key===resource);if(eventElement){if(key==="Escape"){event.preventDefault();this.tlFocusCell(rowIndex,unit);return}
|
|
69
|
+
if(key==="ArrowLeft"||key==="ArrowRight"){event.preventDefault();const list=[...this.tlLanes.get(resource)?.querySelectorAll(".cx-cal-ev")||[]].sort((a,b)=>a._calEvent.start-b._calEvent.start);const next=list[list.indexOf(eventElement)+(key==="ArrowLeft"?-1:1)];if(next){eventElement.tabIndex=-1;next.tabIndex=0;next.focus()}}
|
|
70
|
+
return}
|
|
71
|
+
if(key==="ArrowLeft"||key==="ArrowRight"){event.preventDefault();const next=unit +(key==="ArrowLeft"?-1:1);if(next<0||next>=axis.units.length){this.calendarStep(next<0?-1:1).then(()=>this.tlFocusCell(rowIndex,next<0?this.tlAxis.units.length-1:0));return}
|
|
72
|
+
this.tlFocusCell(rowIndex,next)}else if(key==="ArrowUp"||key==="ArrowDown"){event.preventDefault();let next=rowIndex +(key==="ArrowUp"?-1:1);while(tree.rows[next]?.status)next +=key==="ArrowUp"?-1:1;if(next>=0&&next<tree.rows.length)this.tlFocusCell(next,unit)}else if(key==="Home"||key==="End"){event.preventDefault();this.tlFocusCell(rowIndex,key==="Home"?0:axis.units.length-1)}
|
|
73
|
+
else if(key==="PageUp"||key==="PageDown"){event.preventDefault();this.calendarStep(key==="PageUp"?-1:1).then(()=>this.tlFocusCell(rowIndex,unit))}
|
|
74
|
+
else if(key===" "||key==="Enter"){event.preventDefault();const inside=cell.querySelector(".cx-cal-ev");if(key==="Enter"&&inside){cell.tabIndex=-1;inside.tabIndex=0;inside.focus()}
|
|
75
|
+
else this.tlSelectUnit(axis.units[unit],resource)}},tlFocusCell(rowIndex,unitIndex){const tree=this.tlTree,axis=this.tlAxis,main=this.tlMain,row=tree.rows[rowIndex],unit=axis.units[unitIndex];if(!row||!unit)return;if(!this.calInValid({firstDay:unit.first,lastDay:unit.last}))return;const top=tree.tops[rowIndex],bottom=tree.tops[rowIndex+1]??top+tree.rowH,head=this.tlHead.offsetHeight;if(top<main.scrollTop)main.scrollTop=top;else if(bottom>main.scrollTop+main.clientHeight-head)main.scrollTop=bottom-main.clientHeight+head;const scrolled=this.tlScrollX();if(unit.x<scrolled)this.tlScrollTo(unit.x);else if(unit.x+axis.width>scrolled+main.clientWidth)this.tlScrollTo(unit.x+axis.width-main.clientWidth);tree.grid.scrollTop=main.scrollTop;this.calFocus={day:unit.first,minutes:null,event:null,resource:row.key,unit:unitIndex};this.tlPaintLanes();this.calRestoreFocus(true)},tlSelectUnit(unit,resource){if(this.tlSolo)resource=null;if(this.calZoom==="hour"){const minutes=this.calZone.parts(unit.start).minutes;this.calSelectSlots(unit.first,minutes,minutes+60,resource)}else this.calSelectDays(unit.first,unit.last,resource)},calTimelineClick(event){const lane=event.target.closest(".cx-tl-lane");if(!lane?.dataset.cxResource||!this.tlAxis)return false;const box=this.tlCanvas.getBoundingClientRect(),x=this.calRtl?box.right-event.clientX:event.clientX-box.left,axis=this.tlAxis;const index=Math.max(0,Math.min(axis.units.length-1,Math.floor(x / axis.width)));
|
|
76
|
+
const unit=axis.units[index];if(!this.calInValid({firstDay:unit.first,lastDay:unit.last}))return false;this.calFocus={day:axis.units[index].first,minutes:null,event:null,resource:lane.dataset.cxResource,unit:index};this.tlSelectUnit(axis.units[index],lane.dataset.cxResource);this.calRestoreFocus(true);return true},calTimelinePoint(x,y){const axis=this.tlAxis,tree=this.tlTree,box=this.tlCanvas.getBoundingClientRect();if(!axis||!tree)return null;const time=axis.time(Math.max(0,Math.min(axis.total,this.calRtl?box.right-x:x-box.left))),offset=y-box.top,tops=tree.tops;let low=0,high=tree.rows.length-1;while(low<high){const mid=(low+high+1)>>1;if(tops[mid]<=offset)low=mid;else high=mid-1}
|
|
77
|
+
const index=low;const row=tree.rows[index],resource=row&&!row.status&&!this.tlSolo&&!this.tl.children.has(row.key)?row.key:null;const parts=this.calZone.parts(time);return{day:parts.day,minutes:parts.minutes +(time%CAL_MINUTE)/ CAL_MINUTE, resource, time, row: row?.key ?? null };
|
|
78
|
+
},tlSnap(){const snap=this.cal.editable?.snap??this.cal.slotMinutes;return this.calZoom==="hour"?snap:this.calZoom==="day"?Math.max(60,snap):1440},calTimelineGhost(drag){const proposal=drag.proposal,axis=this.tlAxis,lane=this.tlLanes?.get(this.tlSolo?drag.event.tlRow??proposal.row:proposal.resource??drag.event.resource??drag.event.tlRow);const ghost=this.calGhost||=h("div","cx-cal-ghost");ghost.className="cx-cal-ghost cx-tl-ghost" +(drag.problem?" cx-cal-conflict":"");ghost.setAttribute("aria-hidden","true");const first=proposal.allDay?Math.floor(proposal.start / CAL_DAY) : this.calZone.day(proposal.start), last = Math.max(proposal.start, proposal.end - 1);
|
|
79
|
+
const label=(drag.drop?drag.event.title+" · ":"")+ this.calTimeText({...drag.event,start:proposal.start,end:proposal.end,sd:first,ed:proposal.allDay?Math.floor(last / CAL_DAY) : this.calZone.day(last) });
|
|
80
|
+
const text=ghost.querySelector(".cx-tl-ghost-label")||ghost.appendChild(h("span","cx-tl-ghost-label"));if(ghost.firstChild!==text)ghost.replaceChildren(text);setText(text,drag.problem?label+" · "+drag.problem:label);ghost.title=text.textContent;if(!lane){ghost.remove();return}
|
|
81
|
+
const span=this.calDisplaySpan(proposal),x1=axis.x(span.start),x2=Math.max(x1+3,axis.x(span.end));ghost.style.insetInlineStart=x1+"px";ghost.style.width=(x2-x1)+ "px";if(ghost.parentNode!==lane)lane.appendChild(ghost)}});const TL_PRINT_ROWS=400,TL_PRINT_LANE=760,TL_PRINT_CHAR=5.6;Object.assign(DataGrid.prototype,{tlPrint(on){this.tlPrintView?.remove();this.tlPrintView=null;if(!on||this.calView!=="timeline"||!this.tlTree||!this.tlAxis)return;const axis=this.tlAxis,tree=this.tlTree,view=this.tlPrintView=h("div","cx-tl-print"),share=time=>(axis.x(time)/ axis.total * 100) + "%";
|
|
82
|
+
view.setAttribute("aria-hidden","true");const head=h("div","cx-tl-print-row cx-tl-print-head"),corner=h("div","cx-tl-print-name"),scale=h("div","cx-tl-print-lane");setText(corner,this.tlSolo?"":this.cal.resources?.label||this.calLabels.calendarResources);for(const cell of this.tlHeader.lower){const mark=h("span","cx-tl-print-unit");mark.style.insetInlineStart=(cell.x / axis.total * 100) + "%"; mark.style.width = (cell.width / axis.total * 100) + "%";
|
|
83
|
+
setText(mark,cell.text);scale.appendChild(mark)}
|
|
84
|
+
head.append(corner,scale);view.appendChild(head);for(const row of tree.rows.filter(item=>!item.status).slice(0,TL_PRINT_ROWS)){const line=h("div","cx-tl-print-row"),name=h("div","cx-tl-print-name"),lane=h("div","cx-tl-print-lane"),group=this.tl.children.has(row.key);name.style.paddingInlineStart=(4 +(row.level-1)*12)+ "px";setText(name,this.tlSolo?"":this.calResourceName(row.key));if(group){line.classList.add("cx-tl-print-group");this.tlHeat(row.key).forEach((value,index)=>{if(!value)return;const unit=axis.units[index],mark=h("span","cx-tl-print-heat");mark.style.insetInlineStart=(unit.x / axis.total * 100) + "%"; mark.style.width = (axis.width / axis.total * 100) + "%"; setText(mark, String(value)); lane.appendChild(mark); });
|
|
85
|
+
}else for(const event of this.tlIndex.byResource.get(row.key)||[]){if(event.tlEnd<=axis.from||event.tlStart>=axis.to)continue;const bar=h("span","cx-tl-print-bar");const from=Math.max(event.tlStart,axis.from),to=Math.min(event.tlEnd,axis.to),pixels=(axis.x(to)- axis.x(from))/ axis.total * TL_PRINT_LANE;
|
|
86
|
+
bar.style.insetInlineStart=share(from);bar.style.width="max(6px, calc("+share(to)+ " - "+share(from)+ "))";if(event.tone)bar.style.setProperty("--cx-ev","var(--cx-tone-"+event.tone+",var(--cx-accent))");if(pixels<16)bar.classList.add("cx-tl-print-tiny");if(pixels>=event.title.length*TL_PRINT_CHAR+8)setText(bar,event.title);bar.title=this.calEventName(event);lane.appendChild(bar)}
|
|
87
|
+
line.append(name,lane);view.appendChild(line)}
|
|
88
|
+
this.tlRoot.appendChild(view)}});installed.add(context.DataGrid.prototype)}};(global.CanopyXParts||=[]).push(["timeline",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -0,0 +1,103 @@
|
|
|
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(--cx-line);border-radius:calc(var(--cx-radius) + var(--cx-size-2px));overflow:hidden;font:var(--cx-font-size)/1.4 var(--cx-font);}
|
|
3
|
+
.cx-page > .cx-tree-tools,.cx-page > .cx-main > .cx-tree-tools{padding:0;}
|
|
4
|
+
body .cx-host.cx-tree-tools{padding:0;}
|
|
5
|
+
.cx-tree-tools [hidden]{display:none!important;}
|
|
6
|
+
.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(--cx-line);}
|
|
8
|
+
.cx-tree-tools .cx-search{flex:1 1 var(--cx-size-240px);max-width:var(--cx-size-360px);height:var(--cx-control-h);display:flex;align-items:center;gap:var(--cx-size-8px);padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid var(--cx-control-border);border-radius:var(--cx-radius);color:var(--cx-muted);background:var(--cx-surface);min-width:0;}
|
|
9
|
+
.cx-tree-tools .cx-search::before,.cx-tree-tools .cx-search::after{display:none;}
|
|
10
|
+
.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
|
+
.cx-tree-tools .cx-search:focus-within{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-2px);}
|
|
12
|
+
.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(--cx-font-mono);border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-size-4px);padding:0 var(--cx-size-5px);}
|
|
14
|
+
.cx-tree-tools .cx-button,.cx-tree-tools .cx-btn{height:var(--cx-control-h);min-height:var(--cx-control-h);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(--cx-line-strong);border-radius:var(--cx-radius);background:var(--cx-surface);color:var(--cx-text);font:500 var(--cx-size-14px) var(--cx-font);cursor:pointer;white-space:nowrap;}
|
|
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(--cx-hover-bg);}
|
|
17
|
+
.cx-tree-tools .ghost{border-color:transparent;color:var(--cx-text-2);}
|
|
18
|
+
.cx-tree-tools .icon{width:var(--cx-control-h);padding:0;}
|
|
19
|
+
.cx-tree-tools .active{border-color:var(--cx-accent);color:var(--cx-accent-text);background:var(--cx-accent-soft);}
|
|
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(--cx-size-9px);background:var(--cx-accent);color:var(--cx-on-accent);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
|
+
.cx-spacer{flex:1;}
|
|
23
|
+
.cx-sep{width:var(--cx-size-1px);height:var(--cx-size-20px);background:var(--cx-line);}
|
|
24
|
+
.cx-tree-tools .cx-hrow{height:var(--cx-head-h);}
|
|
25
|
+
.cx-tree-tools .cx-hcell{padding:0 var(--cx-cell-px);font-size:var(--cx-size-13px);font-weight:700;color:var(--cx-text-2);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(--cx-line);}
|
|
27
|
+
.cx-tree-tools .cx-hcell:last-child::after{display:none;}
|
|
28
|
+
.cx-tree-tools .cx-hcell:last-child .cx-resize{right:0;}
|
|
29
|
+
.cx-tree-tools .cx-hcell .cx-sort{min-width:var(--cx-size-24px);overflow:hidden;}
|
|
30
|
+
.cx-tree-tools .cx-htext{overflow:hidden;text-overflow:ellipsis;}
|
|
31
|
+
.cx-tree-tools .cx-cell{padding:0 var(--cx-cell-px);font-variant-numeric:tabular-nums;}
|
|
32
|
+
.cx-tree-tools .cx-row > .cx-cell:first-child:not([data-cx-pin]){position:relative;}
|
|
33
|
+
.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(--cx-accent);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(--cx-line);border-radius:var(--cx-radius);box-shadow:var(--cx-panel-shadow);}
|
|
35
|
+
.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
|
+
.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(--cx-control-h);padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid var(--cx-control-border);border-radius:var(--cx-radius);background:var(--cx-surface);color:var(--cx-text);font:inherit;}
|
|
38
|
+
.cx-grid-control-error{color:var(--cx-tone-danger);margin:0;width:100%;overflow-wrap:anywhere;}
|
|
39
|
+
.cx-grid-delivery-status{margin:0;font-size:var(--cx-size-d875em);overflow-wrap:anywhere;}
|
|
40
|
+
.cx-grid-delivery-status:empty{display:none;}
|
|
41
|
+
.cx-grid-export progress{width:100%;max-width:100%;accent-color:var(--cx-accent);}
|
|
42
|
+
.cx-tree-tools .cx-grid-views .cx-grid-field{width:100%;}
|
|
43
|
+
.cx-tree-tools :is(button,summary,select,input,textarea):focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-2px);}
|
|
44
|
+
.cx-tree-tools .cx-grid-overflow .cx-grid-panel{right:0;left:auto;width:var(--cx-size-244px);}
|
|
45
|
+
.cx-tree-tools .cx-grid-overflow .cx-grid-panel > .cx-button{width:100%;justify-content:start;border:0;border-radius:var(--cx-radius-sm);}
|
|
46
|
+
.cx-tree-tools.cx-phone .cx-toolbar{gap:var(--cx-size-6px);}
|
|
47
|
+
.cx-tree-tools.cx-phone .cx-search{max-width:none;flex-basis:100%;height:var(--cx-size-44px);}
|
|
48
|
+
.cx-tree-tools.cx-phone .cx-spacer,.cx-tree-tools.cx-phone .cx-sep{display:none;}
|
|
49
|
+
.cx-tree-tools.cx-phone .cx-grid-columns > summary{width:var(--cx-size-44px);font-size:0;padding:0;}
|
|
50
|
+
.cx-tree-tools.cx-phone .cx-grid-columns > summary .cx-ico{width:var(--cx-size-16px);height:var(--cx-size-16px);}
|
|
51
|
+
.cx-tree-tools.cx-phone .cx-toolbar :is(.cx-btn,.cx-button){min-height:var(--cx-size-44px);}
|
|
52
|
+
.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(--cx-radius) var(--cx-radius) 0 0;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(--cx-radius);background:var(--cx-muted);margin:0 auto var(--cx-size-8px);flex-basis:var(--cx-size-32px);}
|
|
54
|
+
.cx-tree-tools.cx-phone .cx-grid-panel:has(> [open])::before{display:none;}
|
|
55
|
+
.cx-tree-tools.cx-phone .cx-hrow{height:var(--cx-size-44px);}
|
|
56
|
+
.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));}
|
|
57
|
+
.cx-grid-column-choice:hover{background:var(--cx-hover-bg);}
|
|
58
|
+
.cx-grid-column-handle{min-width:var(--cx-size-24px);}
|
|
59
|
+
.cx-grid-column-find{margin-bottom:var(--cx-size-4px);}
|
|
60
|
+
.cx-grid-column-choice{display:flex;align-items:center;border-radius:var(--cx-radius-sm);}
|
|
61
|
+
.cx-grid-column-choice label{flex:1;min-width:0;white-space:nowrap;}
|
|
62
|
+
.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(--cx-muted);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(--cx-accent);}
|
|
66
|
+
.cx-grid-column-choice.cx-drop-after{box-shadow:inset 0 var(--cx-size-neg-2px) var(--cx-accent);}
|
|
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(--cx-line);}
|
|
68
|
+
.cx-grid-column-actions .cx-button{border:0;color:var(--cx-accent-text);background:none;}
|
|
69
|
+
.cx-drawer{width:100%;max-width:var(--cx-size-440px);background:var(--cx-surface);border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);box-shadow:var(--cx-panel-shadow);font:var(--cx-size-14px)/1.45 var(--cx-font);color:var(--cx-text);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(--cx-line);}
|
|
71
|
+
.cx-drawer-h h4{margin:0;font-size:var(--cx-size-17px);width:fit-content;}
|
|
72
|
+
.cx-drawer-h p{color:var(--cx-muted);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(--cx-muted);font-size:var(--cx-size-13px);padding-top:var(--cx-size-1px);}
|
|
76
|
+
.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(--cx-muted);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;}
|
|
84
|
+
.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: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:color-mix(in srgb,var(--cx-shadow-ink) 35%,transparent);}
|
|
91
|
+
.cx-grid-overlay{color:var(--cx-text);font:var(--cx-font-size)/1.45 var(--cx-font);}
|
|
92
|
+
body .cx-host.cx-grid-overlay{height:auto;min-height:0;padding:0;}
|
|
93
|
+
.cx-grid-overlay [hidden]{display:none!important;}
|
|
94
|
+
.cx-tree-tools.cx-pin-tree .cx-row > .cx-cell.cx-tree:first-child{position:sticky;}
|
|
95
|
+
.cx-tree-tools .cx-row > [data-cx-pin]{position:sticky;z-index:1;background:inherit;}
|
|
96
|
+
.cx-tree-tools .cx-hcell[data-cx-pin]{position:sticky;z-index:2;background:var(--cx-head-bg);}
|
|
97
|
+
.cx-tree-tools .cx-results{position:fixed;}
|
|
98
|
+
.cx-tree-tools .cx-hcell[aria-sort="ascending"] .cx-sort::after{content:"↑";font-size:var(--cx-size-14px);color:var(--cx-accent);}
|
|
99
|
+
.cx-tree-tools .cx-hcell[aria-sort="descending"] .cx-sort::after{content:"↓";font-size:var(--cx-size-14px);color:var(--cx-accent);}
|
|
100
|
+
.cx-tree-tools .cx-switch{font-size:var(--cx-size-14px);color:var(--cx-text-2);white-space:nowrap;}
|
|
101
|
+
.cx-tree-tools .cx-hidden-fields{color:var(--cx-muted);font:var(--cx-size-12d5px) var(--cx-font);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-drawer :focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-2px);}
|
|
103
|
+
.cx-tree-tools.cx-drawer [data-cx-pointer-focus]:focus-visible{outline:none;}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"ce442e100494535d",install(context){if(installed.has(context.TreeGrid.prototype))return;const{TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,exportTimeout,exportFormatsOf,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField}=context;const EXPORT_IMPL={formatsOf:exportFormatsOf};const GRID_ICONS={search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',filter:'<path d="M4 5h16l-6 7.5V19l-4-2v-4.5z"/>',columns:'<rect x="3.5" y="4.5" width="17" height="15" rx="2"/><path d="M9.5 4.5v15M14.5 4.5v15"/>',views:'<path d="M6 4h12v16l-6-4-6 4z"/>',export:'<path d="M12 4v11M7.5 10.5 12 15l4.5-4.5M5 19h14"/>',more:'<circle cx="5" cy="12" r="1.2"/><circle cx="12" cy="12" r="1.2"/><circle cx="19" cy="12" r="1.2"/>',close:'<path d="M6 6l12 12M18 6 6 18"/>',check:'<path d="m5 12.5 4.5 4.5L19 7.5"/>',chart:'<path d="M4 19h16M7 16V10M12 16V6M17 16v-4"/>',copy:'<rect x="8" y="8" width="11" height="11" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/>',up:'<path d="M12 19V5M6 11l6-6 6 6"/>',down:'<path d="M12 5v14M6 13l6 6 6-6"/>',retry:'<path d="M4 12a8 8 0 1 0 2.4-5.7M4 4v4.5h4.5"/>',previous:'<path d="m14 7-5 5 5 5"/>',next:'<path d="m10 7 5 5-5 5"/>',first:'<path d="m13 7-5 5 5 5M17 7l-5 5 5 5"/>',last:'<path d="m11 7 5 5-5 5M7 7l5 5-5 5"/>'};function gridIcon(name,shapes){return svgIcon(shapes||GRID_ICONS[name]||GRID_ICONS.more)}
|
|
2
|
+
function gridDecorateButton(button,icon,ghost){button.classList.add("cx-btn");if(ghost)button.classList.add("ghost");if(icon)button.prepend(gridIcon(icon));return button}
|
|
3
|
+
function gridFilterCount(query){const count=group=>group?group.filters.length+group.groups.reduce((sum,child)=>sum+count(child),0):0;return(query?.filters?.length||0)+ count(query?.filterGroup)}
|
|
4
|
+
function gridPriority(value){return["essential","normal","optional"].includes(value)||Number.isInteger(value)&&value>=0&&value<=MAX_PROTOCOL_INTEGER}
|
|
5
|
+
function gridRank(column){const value=column.priority;return typeof value==="number"?value:value==="optional"?10000:value==="essential"||value===undefined&&column.identity?0:5000}
|
|
6
|
+
function gridLevel(column){const rank=gridRank(column);return rank<2?0:rank<10000?1:2}
|
|
7
|
+
function gridOptions(column){return column.presenter||{}}
|
|
8
|
+
const COLUMN_DIGITS=new Map(),COLUMN_NUMERIC_CHARS="0123456789 .,:;+-−/()[]\u00a0\u202f",COLUMN_HAS_NUMERIC=/[0-9\s.,:;+\-−/()\[\]]/;
|
|
9
|
+
function gridNumericVariant(grid){let sample=grid.querySelector(".cx-cell"),owned=!sample;if(owned){sample=document.createElement("span");sample.className="cx-cell";sample.style.display="none";grid.appendChild(sample)}
|
|
10
|
+
const variant=getComputedStyle(sample).fontVariantNumeric;if(owned)sample.remove();return variant}
|
|
11
|
+
function gridMeasureText(context,value,variant="normal"){const text=String(value).slice(0,512),measured=context.measureText(text).width;if(!variant.includes("tabular-nums")||!COLUMN_HAS_NUMERIC.test(text))return measured;const font=context.font;let variants=COLUMN_DIGITS.get(font);if(!variants){if(COLUMN_DIGITS.size===32)COLUMN_DIGITS.delete(COLUMN_DIGITS.keys().next().value);COLUMN_DIGITS.set(font,variants=new Map())}
|
|
12
|
+
if(!variants.has(variant)){const probe=document.createElement("span"),glyphs=[];probe.style.cssText="all:initial;position:absolute;visibility:hidden;display:flex;white-space:pre;padding:0;border:0;max-width:none;";probe.style.font=font;probe.style.fontVariantNumeric=variant;for(const character of COLUMN_NUMERIC_CHARS)for(const numeric of[true,false]){const glyph=document.createElement("span");glyph.textContent=(numeric?"00"+character+"00":character).repeat(10);glyph.style.cssText="flex:none;white-space:pre;";probe.appendChild(glyph);glyphs.push(glyph)}
|
|
13
|
+
document.body.appendChild(probe);const zero=glyphs[0].getBoundingClientRect().width / 50, numeric = new Map(), plain = new Map();
|
|
14
|
+
for(let index=0;index<COLUMN_NUMERIC_CHARS.length;index++){const character=COLUMN_NUMERIC_CHARS[index],canvas=context.measureText(character).width;for(let mode=0;mode<2;mode++){const delta=glyphs[index*2+mode].getBoundingClientRect().width / 10 - (mode ? 0 : 4 * zero) - canvas;
|
|
15
|
+
if(Math.abs(delta)>0.02)(mode?plain:numeric).set(character.charCodeAt(0),delta)}}
|
|
16
|
+
probe.remove();variants.set(variant,{numeric:numeric.size?numeric:null,plain:plain.size?plain:null})}
|
|
17
|
+
const advances=variants.get(variant),digits=/[0-9]/.test(text) ? advances.numeric : advances.plain;
|
|
18
|
+
if(!digits)return measured;let width=measured;for(let index=0;index<text.length;index++){width +=digits.get(text.charCodeAt(index))||0}
|
|
19
|
+
return width}
|
|
20
|
+
function gridTextual(column){return column.kind==="text"&&!["statusStrip","sparklineBars","sparklineLine","boolean","progress"].includes(gridOptions(column).kind)}
|
|
21
|
+
function gridFitColumn(column,identity){prepareWidth(column);column.identity=column===identity;column.pref=column.autoWidth?0:column.width;column.basePriority=column.priority;column.declared=column.width;column.flexWeight=typeof column.flex==="number"?column.flex:0;if(column.flexWeight)column.flex=true;else if(typeof column.flex==="number")delete column.flex}
|
|
22
|
+
const COLUMN_FIT={fitManual(column){column.width=column.renderWidth??column.width;column.sized=true},fitSize(column,level){const need=(column.need??column.width)+(column.reserve||0);if(level===0)return column.identity&&column.priority===undefined&&!column.fixed&&!column.sized?
|
|
23
|
+
Math.max(column.minW,column.headNeed||0):column.renderWidth;return Math.round(columnWidth(column,column.fixed||column.sized?column.width:!level?Math.max(need,column.pref):level>1||!gridLevel(column)?need:
|
|
24
|
+
Math.min(need,Math.max(column.headNeed||0,gridTextual(column)?this.fitCh||88:0))))},fitWidths(cols,width){let total=0,target;for(const column of cols)total +=column.renderWidth=this.fitSize(column);if(width&&total>width&&this.layoutMode&&this.layoutMode!=="fit")width=total;for(const level of[2,1,0])if(width&&total>width&&(level||cols.reduce((sum,column)=>sum+column.renderWidth-this.fitSize(column,0),0)>=total-width))
|
|
25
|
+
total=width+this.fitShrink(cols,total-width,level);if(width&&total<width)target=this.fitSpare(cols.filter(column=>!column.fixed&&!column.sized),width-total);total=0;for(const column of cols)total +=column.renderWidth=Math.floor(column.renderWidth);if(width>total&&!(target?.renderWidth<target?.maxW))for(const column of cols)
|
|
26
|
+
if(!column.fixed&&!column.sized&&column.renderWidth<column.maxW&&gridTextual(column))target=column;if(target)target.renderWidth +=Math.min(width-total,target.maxW-target.renderWidth);return cols.map(column=>column.renderWidth)},fitShrink(cols,excess,level){for(const group of[cols.filter(column=>column.flex),cols.filter(gridTextual),cols]){if(excess<=0.5)break;const floor=new Map(group.map(column=>[column,Math.min(column.renderWidth,this.fitSize(column,level))]));const cut=width=>group.reduce((sum,column)=>sum+Math.max(0,column.renderWidth-Math.max(width,floor.get(column))),0);let low=0,high=Math.max(0,...group.map(column=>column.renderWidth));for(let step=0;step<24;step++){const middle=(low+high)/ 2; if (cut(middle) >= excess) low = middle; else high = middle; }
|
|
27
|
+
excess -=cut(low);for(const column of group)column.renderWidth=Math.min(column.renderWidth,Math.max(low,floor.get(column)))}
|
|
28
|
+
return excess},fitSpare(columns,spare){let target,flex=columns.filter(column=>column.flex&&column.flexWeight);const grow=(column,limit)=>{const add=column?Math.min(spare,Math.min(limit,column.maxW)- column.renderWidth):0;if(add>0){column.renderWidth +=add;spare -=add;target=column}};for(let before=0;spare>0.5&&flex.length&&before!==spare;){const weight=flex.reduce((sum,column)=>sum+column.flexWeight,0);before=spare;for(const column of flex)grow(column,column.renderWidth+before*column.flexWeight / weight);
|
|
29
|
+
flex=flex.filter(column=>column.maxW-column.renderWidth>0.5)}
|
|
30
|
+
const identity=columns.find(column=>column.identity),widest=columns.filter(column=>!column.identity&&
|
|
31
|
+
gridTextual(column)&&gridLevel(column)===1).sort((a,b)=>b.need-a.need)[0];grow(identity,420);if(identity&&widest)grow(widest,widest.renderWidth+spare*widest.need / (widest.need + identity.need));
|
|
32
|
+
grow(identity,Infinity);grow(widest,Infinity);return target},fitHide(shown,width,phone){let total=0,remaining=shown.length;const order=(a,b)=>gridLevel(b)- gridLevel(a)||gridRank(b)- gridRank(a)||shown.indexOf(b)- shown.indexOf(a),identity=phone&&shown.find(column=>column.identity);const hide=(column,pinned)=>!column.sized&&!column.alwaysVisible&&(column.pin==="none")!==pinned&&!(phone&&column.identity)&&gridLevel(column)>!phone;for(const column of this.columns)column.fitHidden=false;if(this.layoutMode&&this.layoutMode!=="fit")return;for(const column of shown)total +=this.fitSize(column,1);for(const column of shown.filter(column=>hide(column,false)).sort(order))
|
|
33
|
+
if(total>width&&remaining>1){column.fitHidden=true;total -=this.fitSize(column,1);remaining--}
|
|
34
|
+
if(identity&&!identity.fixed&&!identity.sized)total +=Math.min(identity.need??identity.width,(identity.indentNeed||0)+ 2*(this.fitCh||88))+(identity.reserve||0)- this.fitSize(identity,1);if(identity)for(const column of shown.filter(column=>hide(column,true)).sort(order))
|
|
35
|
+
if(total>width){column.fitHidden=true;total -=this.fitSize(column,1)}}};function gridButton(text,run){const button=h("button","cx-button");button.type="button";setText(button,text);button.onclick=event=>{button.focus({preventScroll:true});run(event)};return button}
|
|
36
|
+
let keyboardInput=false;if(typeof document!=="undefined"){document.addEventListener("keydown",()=>{keyboardInput=true},true);document.addEventListener("pointerdown",()=>{keyboardInput=false},true)}
|
|
37
|
+
const focusDrawerTitle=title=>{if(keyboardInput&&title===document.activeElement&&!title.matches(":focus-visible"))title.blur();title.toggleAttribute("data-cx-pointer-focus",!keyboardInput);if(!keyboardInput)title.addEventListener("blur",()=>title.removeAttribute("data-cx-pointer-focus"),{once:true});title.focus({preventScroll:true,focusVisible:keyboardInput})};function gridInputLabel(text,input){const label=h("label","cx-grid-field");label.appendChild(document.createTextNode(text));label.appendChild(input);return label}
|
|
38
|
+
function gridOption(value,text){const option=h("option");option.value=value;setText(option,text);return option}
|
|
39
|
+
const MENU_EVENT="canopyx:closemenus",announceMenu=source=>document.dispatchEvent(new CustomEvent(MENU_EVENT,{detail:{source}}));const TOOLBAR_PANELS={startMenus(){this.controlFlyouts=[];this.disposeControls=()=>this.controlFlyouts.forEach(flyout=>flyout.dispose());let pressed=null;for(const type of["mouseup","click","keydown","pointercancel"])document.addEventListener(type,()=>{pressed=null},{capture:true,signal:this.lifetime.signal});for(const type of["pointerdown","focusin",MENU_EVENT])document.addEventListener(type,event=>{if(type==="pointerdown")pressed=event.target;const node=type==="focusin"&&pressed?.isConnected&&event.target.contains(pressed)?pressed:event.detail?.source||event.target;if(type!==MENU_EVENT||event.target.contains(this.host))this.closeMenusOutside(node)},{signal:this.lifetime.signal})},closeMenusOutside(node){for(const details of this.toolbar.querySelectorAll(".cx-columns[open]"))if(!details.contains(node))details.open=false;const popover=this.gridPopover;if(popover&&!popover.panel.contains(node)&&!popover.anchor?.contains(node))this.closeGridPopover(false)},closeMenus(){this.closeMenusOutside(document)},controlPanel(title,className,onOpen){const details=h("details","cx-columns "+className),summary=h("summary","cx-btn"),panel=h("div","cx-columns-list cx-grid-panel cx-pop");summary.setAttribute("role","button");if(className!=="cx-grid-filters")summary.classList.add("ghost");setText(summary,title);details.append(summary,panel);this.toolbar.appendChild(details);summary.prepend(gridIcon(className.slice(8).replace("rs","r")));panel.popover="manual";const flyout=watchFlyout(details,panel,()=>details.open);this.controlFlyouts.push(flyout);details.addEventListener("toggle",()=>{if(details.open){announceMenu(details);if(panel.isConnected)panel.showPopover?.();if(onOpen)onOpen(panel);flyout.position()}else{panel.hidePopover?.();for(const inner of panel.querySelectorAll("details[open]"))inner.open=false}});details.addEventListener("keydown",event=>{if(event.key==="Escape"&&details.open){details.open=false;summary.focus();event.preventDefault();event.stopPropagation()}});return{details,panel}},buildSavedViews(){const panel=this.controlPanel(this.labels.gridViews,"cx-grid-views").panel;const choice=this.savedChoice=h("select"),name=h("input");name.type="text";name.maxLength=100;choice.setAttribute("aria-label",this.labels.gridChooseView);panel.appendChild(choice);panel.appendChild(gridInputLabel(this.labels.gridViewName,name));const error=h("p","cx-grid-control-error");error.setAttribute("role","status");const run=action=>{try{Promise.resolve(action()).then(()=>setText(error,""),failure=>setText(error,failure.message))}
|
|
40
|
+
catch(failure){setText(error,failure.message)}};panel.appendChild(gridButton(this.labels.gridApply,()=>run(()=>this.applySavedView(choice.value))));panel.appendChild(gridButton(this.labels.gridSaveView,()=>run(()=>this.saveView(name.value))));panel.appendChild(gridButton(this.labels.gridRemoveView,()=>run(()=>this.removeSavedView(choice.value))));panel.appendChild(error);this.syncSavedViews()},syncSavedViews(){if(!this.savedChoice)return;const selected=this.savedChoice.value;this.savedChoice.textContent="";this.savedChoice.appendChild(gridOption("",this.labels.gridChooseView));this.getSavedViews().forEach(name=>this.savedChoice.appendChild(gridOption(name,name)));if(this.savedViews.has(selected))this.savedChoice.value=selected},placeMenus(phone){if(this.overflow)for(const selector of[".cx-grid-views",".cx-grid-export"]){const item=this.toolbar.querySelector(selector);if(!item)continue;item.open=false;if(phone)this.overflow.panel.appendChild(item);else this.toolbar.insertBefore(item,selector===".cx-grid-views"?this.slots?.afterViews||this.spacer:this.overflow.details)}}};const COLUMNS_MENU={moveColumnChoice(column,target,after){column.pin=target.pin;const ids=this.columns.map(item=>item.id).filter(id=>id!==column.id);ids.splice(ids.indexOf(target.id)+ after,0,column.id);this.setColumnOrder(ids)},renderGridColumns(panel){if(!this.columnList){const find=this.columnFind=h("input","cx-grid-column-find"),actions=h("div","cx-grid-column-actions");find.type="search";find.placeholder=this.labels.gridFindColumn;find.setAttribute("aria-label",find.placeholder);find.hidden=this.columns.length<9;find.oninput=()=>this.syncColumnControls();actions.append(gridButton(this.labels.gridShowAllColumns,()=>this.showAllColumns()),gridButton(this.labels.gridResetColumns,()=>this.resetColumns()));panel.replaceChildren(find,this.columnList=h("div"),actions)}
|
|
41
|
+
this.syncColumnControls()},syncColumnControls(){const list=this.columnList,active=document.activeElement,query=foldText(this.columnFind?.value.trim()||"");if(!list)return;const focus=list.contains(active)&&active.closest(".cx-grid-column-choice").dataset.cxColumn,held=focus&&active.matches(".cx-grid-column-handle"),last=this.columns.filter(item=>!item.hidden).length<2;list.textContent="";for(const column of this.columns){const row=h("div","cx-grid-column-choice"),label=h("label"),input=h("input"),name=h("span","cx-grid-column-name"),handle=h("button","cx-grid-column-handle"),note=column.fitHidden||column.responsiveHidden?this.labels.gridResponsiveHidden:column.pin==="left"?this.labels.gridPinnedLeft:column.pin==="right"?this.labels.gridPinnedRight:"";input.type="checkbox";input.checked=!column.hidden;input.disabled=!column.hidden&&last;input.onchange=()=>{input.focus({preventScroll:true});this.setColumnVisible(column.id,input.checked)};setText(name,name.title=column.title);handle.type="button";setText(handle,"⋮⋮");handle.setAttribute("aria-label",fill(this.labels.gridReorderColumn,{column:column.title}));label.append(input,name);row.append(handle,label);row.hidden=!!query&&!foldText(column.title).includes(query);if(note){const span=h("span","cx-grid-column-note");setText(span,note);row.append(span)}
|
|
42
|
+
row.onkeydown=event=>{const target=event.altKey&&this.columns[this.columns.indexOf(column)+(event.key==="ArrowUp"?-1:event.key==="ArrowDown"?1:NaN)];if(target){event.preventDefault();event.stopPropagation();this.moveColumnChoice(column,target,event.key==="ArrowDown")}};handle.onpointerdown=event=>{if(event.button)return;event.preventDefault();handle.focus();handle.setPointerCapture(event.pointerId);let target,after;const clear=()=>{for(const item of list.children)item.classList.remove("cx-drop-before","cx-drop-after")};handle.onpointermove=move=>{clear();const over=document.elementFromPoint(move.clientX,move.clientY)?.closest(".cx-grid-column-choice");target=over!==row&&list.contains(over)&&this.columns[[...list.children].indexOf(over)];if(target){const box=over.getBoundingClientRect();after=move.clientY>box.top+box.height / 2; over.classList.add(after ? "cx-drop-after" : "cx-drop-before"); }
|
|
43
|
+
};handle.onpointerup=handle.onpointercancel=up=>{handle.onpointermove=handle.onpointerup=handle.onpointercancel=null;clear();if(up.type==="pointerup"&&target)this.moveColumnChoice(column,target,after)}};row.dataset.cxColumn=column.id;list.appendChild(row);if(focus===column.id)(held?handle:input).focus({preventScroll:true})}}};function gridOperationActive(grid,signal){if(grid.destroyed||signal?.aborted)throw new DOMException("Grid cancelled.","AbortError")}
|
|
44
|
+
const exportPartReady=()=>typeof loadExportPart==="function"?loadExportPart():Promise.resolve();function exportAs(grid,format,options={}){const{onProgress,timeoutMs,download,...capture}=options;let provider,resolutionError;try{provider=EXPORT_IMPL.formatsOf(grid).find(item=>item.id===format)}
|
|
45
|
+
catch(error){resolutionError=error}
|
|
46
|
+
const prepared=grid.calIcsFormatWriter&&provider?.write===grid.calIcsFormatWriter?grid.calPrepareIcsExport(capture):grid.prepareExport(capture);return exportPartReady().then(()=>{if(resolutionError)throw resolutionError;return EXPORT_IMPL.run(grid,format,options,prepared,provider)})}
|
|
47
|
+
Object.assign(TreeGrid.prototype,TOOLBAR_PANELS,COLUMNS_MENU,{installTools(){this.checkTreeLayout();const bar=this.toolbar,tools=this.tools,labels=this.labels;this.host.classList.add("cx-chrome","cx-tree-tools");this.exportScopes=[["visible","gridVisibleRows"],["selected","gridSelectedRows"],["all","gridAllRows"]];this.toolbar.querySelector(".cx-search")?.prepend(gridIcon("search"));this.startMenus();this.lifetime.signal.addEventListener("abort",()=>{this.disposeControls();this.host.classList.remove("cx-chrome","cx-tree-tools","cx-phone")},{once:true});if(tools.columns!==false&&this.columns.length>1)this.controlPanel(labels.columns,"cx-grid-columns",panel=>this.renderGridColumns(panel));for(const item of pluginItems(this,"toolbarItems"))bar.appendChild(this.treeAction(item));this.prepareSavedViews();if(tools.views!==false&&this.stateKey()){this.buildSavedViews();bar.querySelector(".cx-grid-views .cx-grid-panel").appendChild(gridButton(labels.gridResetView,()=>this.resetView().catch(()=>{})))}
|
|
48
|
+
bar.appendChild(this.spacer=h("span","cx-spacer"));if(tools.export!==false)this.exportControl=this.controlPanel(labels.gridExport,"cx-grid-export",panel=>this.renderGridExport(panel));if(tools.more!==false)this.buildMoreMenu();if(bar.childElementCount===1)bar.replaceChildren();this.syncToolbar();this.startFit()},buildMoreMenu(){const overflow=this.overflow=this.controlPanel(this.labels.gridMore,"cx-grid-overflow"),summary=overflow.details.firstChild;summary.replaceChildren(gridIcon("more"));summary.classList.add("icon");summary.setAttribute("aria-label",this.labels.gridMore);for(const action of[...this.opts.actions||[],...pluginItems(this,"menuItems")])overflow.panel.appendChild(this.treeAction(action));if(this.columns.length>1)overflow.panel.appendChild(Object.assign(gridButton(this.labels.gridDetails,()=>
|
|
49
|
+
this.openDetails((this.focused||this.rows.find(w=>this.selected.has(w)))?.key).catch(error=>this.emit("error",{error}))),{className:"cx-button cx-grid-details"}));overflow.panel.appendChild(Object.assign(gridButton(this.labels.gridPrint,()=>global.print()),{className:"cx-button cx-grid-print"}))},treeSelection(){return Array.from(this.selected,w=>w.h)},treeAction(action){if(!action||typeof action.label!=="string"||typeof action.run!=="function")throw new Error("CanopyX: actions need a label and handler.");return gridButton(action.label,()=>Promise.resolve().then(()=>
|
|
50
|
+
action.run({nodes:this.treeSelection(),signal:this.dataLifetime.signal,api:this.host.canopyx})).catch(error=>this.emit("error",{error})))},closeMenusOutside(node){TOOLBAR_PANELS.closeMenusOutside.call(this,node);const panel=this.interactionPanel;if(panel?.getAttribute("role")==="menu"&&!panel.contains(node))this.closeInteractionPanel(false)},renderGridColumns(panel){COLUMNS_MENU.renderGridColumns.call(this,panel);this.columnList.setAttribute("role","group");this.columnList.setAttribute("aria-label",this.labels.visibleColumns)},syncColumnControls(){COLUMNS_MENU.syncColumnControls.call(this);const row=this.columnList?.firstChild;if(row){row.querySelector(".cx-grid-column-handle").hidden=true;row.querySelector("input").disabled=true}},syncPhone(){const phone=this.host.clientWidth<=640;if(phone===this.phone)return;if(this.hiddenFieldCount())this.version++;this.phone=phone;this.host.classList.toggle("cx-phone",phone);this.placeMenus(phone)}});const OPEN_PANEL=TreeGrid.prototype.openInteractionPanel;if(OPEN_PANEL)TreeGrid.prototype.openInteractionPanel=function(...args){const panel=OPEN_PANEL.apply(this,args);if(panel?.getAttribute("role")==="menu")announceMenu(panel);return panel};const TREE_ACTIVATION={activate:TreeGrid.prototype.activate,onDblClick:TreeGrid.prototype.onDblClick};Object.assign(TreeGrid.prototype,{rowActivated(w,keyboard){const callback=this.opts.onRowActivate;let go=this.host.dispatchEvent(new CustomEvent("canopyx:rowActivate",{detail:{id:w.key,node:w.h,keyboard},bubbles:true,cancelable:true}));if(typeof callback==="function"){try{go=callback(w.h,{keyboard})!==false&&go}catch(error){global.console?.error(error)}}
|
|
51
|
+
return go},activate(w,enter){if(!enter||w.status||this.rowActivated(w,true))TREE_ACTIVATION.activate.call(this,w,enter)},onDblClick(event){const w=this.rowFromEvent(event);if(!w||w.status||hostControl(event.target)||event.target.closest(".cx-exp")||this.rowActivated(w,false))TREE_ACTIVATION.onDblClick.call(this,event)}});const TREE_FIT={};for(const name of["applyWidths","visibleColumns","setColumnWidth","startResize","buildHeader","render","getState","readState","applyStatePresentation"])
|
|
52
|
+
TREE_FIT[name]=TreeGrid.prototype[name];const TREE_FIT_ROWS=2000;Object.assign(TreeGrid.prototype,COLUMN_FIT,{checkTreeLayout(){for(const[index,column]of this.view.columns.entries()){if(column.priority!==undefined&&!gridPriority(column.priority)||column.flex!==undefined&&!(typeof column.flex==="number"&&column.flex>=0&&column.flex<=100)||
|
|
53
|
+
[column.fixed,column.alwaysVisible,column.autoWidth].some(value=>value!==undefined&&typeof value!=="boolean")||
|
|
54
|
+
column.autoSize!==undefined&&!["content","header","none"].includes(column.autoSize)||
|
|
55
|
+
column.pinned!==undefined&&(index?!["left","right",null].includes(column.pinned):column.pinned!==null&&column.pinned!=="left"))throw new Error("CanopyX: invalid tree column layout.")}},startFit(){const identity=this.columns[0];for(const column of this.columns){const declared=this.view.columns.find(item=>item.id===column.id);column.autoWidth=!!(declared.autoWidth||declared.width===undefined);gridFitColumn(column,identity);column.declared=columnWidth(column,declared.width??160);if(this.restoredPin&&column.width!==column.declared)column.sized=true;column.pin=column===identity?"left":this.restoredPin&&column.pin||declared.pinned||"none"}
|
|
56
|
+
this.groupPins();if(identity.pinned!==null&&!this.restoredPin)this.host.classList.add("cx-pin-tree");this.fitReady=true;this.fitRows=null;this.observeFit();this.buildHeader()},observeFit(){let width=0;const observer=new ResizeObserver(()=>requestAnimationFrame(()=>{if(this.destroyed||!this.grid.clientWidth||this.grid.clientWidth===width)return;width=this.grid.clientWidth;this.syncPhone();this.applyWidths();this.heightTotal=undefined;this.scheduleRender()}));observer.observe(this.grid);this.lifetime.signal.addEventListener("abort",()=>observer.disconnect(),{once:true})},visibleColumns(){return TREE_FIT.visibleColumns.call(this).filter(column=>!column.fitHidden)},buildHeader(){if(this.fitReady)this.fitLayout();TREE_FIT.buildHeader.call(this);if(this.fitReady)this.headCells.forEach((cell,index)=>cell.querySelector(".cx-resize").addEventListener("keydown",event=>{if(["ArrowLeft","ArrowRight","Home"].includes(event.key))this.fitManual(this.cols[index])},true))},applyWidths(widths){if(widths||!this.fitReady||!this.cols)return TREE_FIT.applyWidths.call(this,widths);const width=this.grid.clientWidth;this.fitLayout();const visible=this.visibleColumns();if(visible.length!==this.cols.length||visible.some((column,index)=>column!==this.cols[index])){this.buildHeader();this.syncColumnControls();this.version++;this.scheduleRender();return}
|
|
57
|
+
TREE_FIT.applyWidths.call(this,this.fitWidths(this.cols,width))},startResize(event,column){if(!this.destroyed&&!event.button&&this.fitReady)this.fitManual(column);return TREE_FIT.startResize.call(this,event,column)},setColumnWidth(id,width){const column=this.columns.find(item=>item.id===id);if(column&&Number.isFinite(width))column.sized=true;return TREE_FIT.setColumnWidth.call(this,id,width)},fitLayout(){const width=this.grid.clientWidth;if(!width)return;const key=this.layout+":"+this.local+":" +(this.host.clientWidth<=640);if(this.fitRows!==this.rows||this.fitKey!==key){this.fitRows=this.rows;this.fitKey=key;this.measureTreeColumns()}
|
|
58
|
+
const shown=TREE_FIT.visibleColumns.call(this),phone=this.host.clientWidth<=640,identity=this.columns[0];identity.reserve=0;this.fitHide(shown,width,phone);const reserve=()=>{this.fitContext.font="700 12.5px"+this.fitFamily;identity.reserve=Math.max(24,Math.ceil(this.fitContext.measureText("+"+this.hiddenFieldCount()).width))+ 8};if(phone&&this.fitContext&&this.hiddenFieldCount()){reserve();this.fitHide(shown,width,phone);reserve()}},measureTreeColumns(){const context=this.fitContext||=document.createElement("canvas").getContext("2d");if(!context)return;const style=getComputedStyle(this.grid),family=this.fitFamily=" "+style.fontFamily,head=this.headCells?.[0]&&getComputedStyle(this.headCells[0]);const font=style.fontWeight+" "+style.fontSize+family,headFont=(head?head.fontWeight+" "+head.fontSize:"700 13px")+ family;const badgeFont="400 "+parseFloat(style.fontSize)*0.8+"px"+family,pad=parseFloat(getComputedStyle(this.host).getPropertyValue("--cx-cell-px"))||8;const numericVariant=gridNumericVariant(this.grid);const text=(value,using=font,numeric=true)=>{context.font=using;return gridMeasureText(context,value,numeric?numericVariant:"normal")};const badges=list=>(list||[]).reduce((sum,badge)=>sum+text(badge.text,badgeFont)+ 20,0);this.fitCh=Math.ceil(text("00000000000"));const rows=[];for(const w of this.rows){if(rows.length===TREE_FIT_ROWS)break;if(!w.status&&!w.h.detail)rows.push(w)}
|
|
59
|
+
const check=this.checkMode?28:0;this.columns.forEach((column,index)=>{const headNeed=Math.ceil(text(column.title,headFont,false)+ 2*pad +(column.sortable?22:8));let values=0,indent=0;if(column.autoSize!=="none"&&column.autoSize!=="header")for(const w of rows){const cell=this.cellOf(w.h,column,index),object=isCellObject(cell);let need=text(cellText(cell,column,this.fmt))+ badges(index===0?w.h.badges:null)+ badges(object?cell.badges:null);const lead=index?0:(w.level-1)*INDENT+22+check +(w.h.icon&&this.iconTemplates.has(w.h.icon)?22:0);if(lead>indent)indent=lead;if(need+lead>values)values=need+lead}
|
|
60
|
+
const cap=index===0?column.maxW:columnWidth(column,420);column.headNeed=Math.min(headNeed,cap);column.indentNeed=indent+2*pad;column.need=Math.max(column.minW,column.autoSize==="none"?column.pref||column.width:Math.min(cap,Math.max(headNeed,Math.ceil(values+2*pad+2))))})},render(){const measured=TREE_FIT.render.call(this);if(this.fitReady&&this.fitRows!==this.rows&&!this.fitPending){this.fitPending=true;requestAnimationFrame(()=>{this.fitPending=false;if(!this.destroyed&&this.fitRows!==this.rows)this.applyWidths()})}
|
|
61
|
+
this.watchHeight();return measured},getState(){const state=TREE_FIT.getState.call(this);state.columns.forEach((saved,index)=>{const column=this.columns[index];if(column.sized)saved.sized=true;if(index)saved.pin=column.pin});return state},readState(state){const result=TREE_FIT.readState.call(this,state);if(result&&result.columns)result.columns.forEach((column,index)=>{if(state.columns[index].sized===true)column.sized=true;if(["none","left","right"].includes(state.columns[index].pin))column.pin=state.columns[index].pin});return result},applyStatePresentation(state){if(state.version&&state.columns){const order=state.columns.map(column=>column.id),rank=column=>{const at=order.indexOf(column.id);return at<0?order.length:at};this.columns=[this.columns[0],...this.columns.slice(1).sort((a,b)=>rank(a)- rank(b))];for(const saved of state.columns){const column=this.columns.find(item=>item.id===saved.id);if(column){column.sized=!!saved.sized||column.declared!==undefined&&saved.width!==column.declared;if(column!==this.columns[0])column.pin=saved.pin??column.pin}}
|
|
62
|
+
this.groupPins();this.restoredPin=true}
|
|
63
|
+
return TREE_FIT.applyStatePresentation.call(this,state)}});const TREE_HEIGHT_DELAY=60;Object.assign(TreeGrid.prototype,{watchHeight(){if(!this.fitReady||this.view.autoHeight===false||this.total===this.heightTotal&&
|
|
64
|
+
(this.heightFitted||!this.rows.some(row=>!row.status)))return;const growing=this.total>this.heightTotal;this.heightTotal=this.total;clearTimeout(this.heightTimer);if(!this.heightFitted||growing){this.fitHeight();return}
|
|
65
|
+
this.heightTimer=setTimeout(()=>this.destroyed||this.fitHeight(),TREE_HEIGHT_DELAY)},fitHeight(){const grid=this.grid,style=this.host.style;if(!grid.clientWidth){this.heightTotal=undefined;return}
|
|
66
|
+
if(this.heightInline===undefined){this.heightInline=style.maxHeight;this.heightMax=parseFloat(getComputedStyle(this.host).maxHeight)||Infinity;this.lifetime.signal.addEventListener("abort",()=>{clearTimeout(this.heightTimer);style.maxHeight=this.heightInline},{once:true})}
|
|
67
|
+
const content=[...grid.children].reduce((sum,child)=>sum+child.offsetHeight,grid.offsetHeight-grid.clientHeight);const value=this.rows.length?Math.min(this.heightMax,Math.ceil(this.host.offsetHeight-grid.offsetHeight+content))+ "px":this.heightInline;if(style.maxHeight!==value){style.maxHeight=value;const anchor=this.interactionPanel&&this.rendered.get(this.panelNode);if(anchor?.isConnected)this.placeInteractionPanel(anchor)}
|
|
68
|
+
if(this.rows.some(row=>!row.status))this.heightFitted=true}});Object.assign(TreeGrid.prototype,{prepareSavedViews(){this.savedViews=new Map();if(this.stateKey())try{const stored=JSON.parse(sessionStorage.getItem(this.stateKey()+ ":views")||"[]");for(const entry of Array.isArray(stored)?stored.slice(0,20):[])if(this.readState(entry&&entry.state))this.savedViews.set(this.viewName(entry.name),entry.state)}catch(error){/* Unavailable storage or an invalid entry leaves the views that could be read. */ }
|
|
69
|
+
},writeSavedViews(){if(this.stateKey())try{sessionStorage.setItem(this.stateKey()+ ":views",JSON.stringify([...this.savedViews].map(([name,state])=>({name,state}))))}
|
|
70
|
+
catch(error){/* A disabled or full storage leaves the current session usable. */ }
|
|
71
|
+
},viewName(name){if(typeof name!=="string"||!name.trim()||name.trim().length>100)throw new Error("CanopyX: view names need 1 to 100 nonblank characters.");return name.trim()},getSavedViews(){return[...this.savedViews.keys()]},saveView(name){name=this.viewName(name);if(!this.savedViews.has(name)&&this.savedViews.size>=20)throw new Error("CanopyX: maximum 20 saved views.");this.savedViews.set(name,this.getState());this.writeSavedViews();this.syncSavedViews();if(this.savedChoice)this.savedChoice.value=name},async applySavedView(name){const state=this.savedViews.get(this.viewName(name));if(!state)throw new Error("CanopyX: the saved view does not exist.");return this.setState(state)},removeSavedView(name){this.savedViews.delete(this.viewName(name));this.writeSavedViews();this.syncSavedViews()},resetView(){return this.setState(this.declaredState())},declaredState(){const expanded=[],walk=parent=>this.modelChildren(parent).forEach(w=>{if(w.h.expanded&&this.expandable(w)){expanded.push(this.pathOf(w));walk(w)}});walk(this.root);return{version:1,expanded,selection:[],columns:this.declaredColumns(),sort:null,filters:[],timeZone:this.view.timeZone==="local"?"local":"utc",pinTreeColumn:!!this.view.pinTreeColumn||this.columns[0].pinned!==null,focus:null,anchor:null,...this.layoutOptions&&{layout:{mode:this.layoutOptions.mode,density:this.layoutOptions.density}},...this.highlightOptions&&{highlight:this.highlightOptions.enabled}}},declaredColumns(){return this.view.columns.map((declared,index)=>({id:declared.id,width:columnWidth(this.columns.find(column=>column.id===declared.id),declared.width??160),hidden:index>0&&!!declared.hidden,pin:index&&declared.pinned||"none"}))},setColumnOrder(ids){if(!Array.isArray(ids)||ids.length!==this.columns.length||new Set(ids).size!==ids.length||ids.some(id=>!this.columns.some(column=>column.id===id)))
|
|
72
|
+
throw new Error("CanopyX: name each column once.");if(this.cancelResize)this.cancelResize();const identity=this.columns[0];this.columns=[identity,...ids.filter(id=>id!==identity.id).map(id=>this.columns.find(column=>column.id===id))];this.groupPins();this.columnsChanged()},showAllColumns(){for(const column of this.columns)column.hidden=false;this.columnsChanged()},resetColumns(){const declared=this.declaredColumns();this.columns=declared.map((saved,index)=>Object.assign(this.columns.find(column=>column.id===saved.id),{width:saved.width,hidden:saved.hidden,sized:false,...index&&{pin:saved.pin}}));this.groupPins();this.columnsChanged()},columnsChanged(){this.buildHeader();this.syncColumnControls();this.relayout();this.stateChanged()}});const TREE_PINS={};for(const name of["applyWidths","render","setTreeColumnPinned"])TREE_PINS[name]=TreeGrid.prototype[name];Object.assign(TreeGrid.prototype,{groupPins(){const[tree,...rest]=this.columns;this.columns=[tree,...["left","none","right"].flatMap(side=>rest.filter(column=>(column.pin||"none")===side))]},setColumnPinned(id,pin){const column=this.columns.find(item=>item.id===id);if(!column||column===this.columns[0]||!["none","left","right"].includes(pin))throw new Error("CanopyX: invalid column pin.");column.pin=pin;this.groupPins();this.columnsChanged();this.emit("columnPin",{column:id,pin})},applyWidths(widths){TREE_PINS.applyWidths.call(this,widths);if(this.fitReady&&this.cols)this.pinRows(true)},setTreeColumnPinned(pinned){TREE_PINS.setTreeColumnPinned.call(this,pinned);if(this.fitReady&&this.cols)this.pinRows(true)},render(){const result=TREE_PINS.render.call(this);this.pinRows();return result},pinRows(measure){const cols=this.cols,width=column=>column.renderWidth??column.width;if(measure){let start=this.host.classList.contains("cx-pin-tree")?width(cols[0]):0,end=0;let stop=false;const room=column=>!(stop||=start+end+width(column)>this.grid.clientWidth-128);for(const column of cols)column.pinAt=null;for(const column of cols.slice(1))if(column.pin==="left"&&room(column)){column.pinAt=start;start +=width(column)}
|
|
73
|
+
stop=false;for(const column of cols.slice(1).reverse())if(column.pin==="right"&&room(column)){column.pinAt=end;end +=width(column)}
|
|
74
|
+
this.pinned=cols.some(column=>column.pinAt!=null)}
|
|
75
|
+
const place=(cell,column)=>{const side=column?.pinAt!=null&&column.pin,key=side&&side+column.pinAt;if(cell._pin===key)return;cell._pin=key;cell.style.left=cell.style.right="";if(side){cell.dataset.cxPin=side;cell.style[side]=column.pinAt+"px"}else delete cell.dataset.cxPin};if(!(this.pinsPlaced||=this.pinned))return;this.headCells.forEach((cell,index)=>place(cell,cols[index]));for(const row of this.rendered.values())if(row._kind==="node")row._cells.forEach((slot,index)=>place(slot.cell,cols[index]))}});const TREE_EXPORT={prepareExport(options={}){const{scope="visible",values="display",signal}=options;if(this.destroyed||!["visible","selected","all"].includes(scope)||!["raw","display"].includes(values)||signal!==undefined&&!(signal instanceof AbortSignal))
|
|
76
|
+
throw new Error("CanopyX: invalid tree export.");const ids=options.columns??this.columns.filter(column=>!column.hidden).map(column=>column.id);const columns=Array.isArray(ids)?ids.map(id=>this.columns.find(column=>column.id===id)):[];if(!columns.length||columns.some(column=>!column)||new Set(ids).size!==ids.length)throw new Error("CanopyX: invalid export columns.");const rows=[],add=(node,level,path)=>{if(!node.detail)rows.push({id:node.id,level,path,node:{...node}})};const sort=this.sortState,column=sort&&this.columns.find(item=>item.id===sort.column),index=this.columns.indexOf(column);const key=node=>sortKey(this.cellOf(node,column,index),column);const raw=(nodes,level,path)=>(column&&!this.queryAware?nodes.map((node,at)=>[key(node),at,node])
|
|
77
|
+
.sort((a,b)=>compareKeys(a[0],b[0],sort.direction==="desc"?-1:1)||a[1]- b[1]).map(entry=>entry[2]):nodes)
|
|
78
|
+
.forEach(node=>{const at=[...path,node.id];add(node,level,at);if(node.children)raw(node.children,level+1,at)});const walk=parent=>this.modelChildren(parent).forEach(w=>{if(scope==="all"||this.selected.has(w))add(w.h,w.level,this.pathOf(w));walk(w)});if(scope==="visible")this.rows.forEach(w=>{if(!w.status)add(w.h,w.level,this.pathOf(w))});else if(scope==="all"&&this.root.inlineItems)raw(this.root.inlineItems,1,[]);else walk(this.root);const request=Object.freeze({kind:"tree",scope,presentation:"text",values,revision:this.datasetRevision,recordCount:rows.length,columns:Object.freeze(columns.map(({id,title,kind})=>Object.freeze({id,title,kind}))),locale:this.lang,timeZone:this.local?"local":"utc"}),grid=this;return Object.freeze({request,rows:async function*(more){const linked=AbortSignal.any([grid.lifetime.signal,signal,more?.signal].filter(Boolean));await exportPartReady();yield*EXPORT_IMPL.treeRows(grid,request,rows,linked)}})},exportAs(format,options){return exportAs(this,format,options)}};Object.assign(TreeGrid.prototype,{outlineTable(){const cols=this.visibleColumns(),table=h("table","cx-outline-table"),head=h("tr"),body=h("tbody");cols.forEach((column)=>setText(head.appendChild(h("th")),column.title));table.appendChild(h("thead")).appendChild(head);table.appendChild(body);this.rows.forEach((w)=>{if(w.status){return}
|
|
79
|
+
const tr=body.appendChild(h("tr")),indent=(td)=>{td.style.paddingLeft=((w.level-1)*14+4)+ "px";return td};if(w.h.detail){const td=indent(tr.appendChild(h("td")));td.colSpan=cols.length;this.renderDetail(w.h,td,true);return}
|
|
80
|
+
cols.forEach((column,i)=>{const index=this.columns.indexOf(column);const value=this.cellOf(w.h,column,index);const text=cellText(value,column,this.fmt);const td=tr.appendChild(h("td")),content=h("span");if(i===0)indent(td);const slot={};try{if(!column.render||column.render(w.h,content,new HostCellContext(slot,column.id,w.level,w.expanded,index))!==true){const badges=(i===0?w.h.badges||[]:[]).concat(isCellObject(value)?value.badges||[]:[]);content.appendChild(detailCell("span",Object.assign({},isCellObject(value)?value:{},{text,badges}),this.fmt))}
|
|
81
|
+
td.appendChild(content.cloneNode(true))}finally{disposeHostSlot(slot)}})});return table}});const TREE_DETAILS={paintNodeRow:TreeGrid.prototype.paintNodeRow,active:null};Object.assign(TreeGrid.prototype,{focusRing:focusDrawerTitle,hiddenFieldCount(){return this.columns.filter(column=>column.hidden||column.fitHidden).length},paintNodeRow(rowEl,w){TREE_DETAILS.paintNodeRow.call(this,rowEl,w);const slot=rowEl._cells[0],count=this.phone&&this.fitReady&&this.hiddenFieldCount();let button=slot.hiddenFields;if(!count){button?.remove();slot.hiddenFields=null;return}
|
|
82
|
+
if(!button){button=slot.hiddenFields=gridButton("",()=>this.openDetails(button.dataset.cxRecord).catch(error=>this.emit("error",{error})));button.classList.add("cx-hidden-fields");button.tabIndex=-1;button.addEventListener("click",event=>event.stopPropagation())}
|
|
83
|
+
if(button.parentNode!==slot.cell)slot.cell.appendChild(button);button.dataset.cxRecord=w.h.id;button.setAttribute("aria-label",this.labels.gridDetails);setText(button,"+"+count)},async openDetails(id,options){const node=this.keyMap.get(id)?.h;if(node&&this.recordNeeded(node))await this.requirePart("record-panel");return this.showDetails(id,options)},showDetails(id,options={}){const rows=this.rows.filter(w=>!w.status&&!w.h.detail),returnFocus=options.returnFocus||document.activeElement,labels=this.labels,owner=this.dataLifetime;let index=rows.findIndex(w=>w.key===id);const loose=index<0?options.node||this.keyMap.get(id)?.h:null;if(index<0&&!loose||this.destroyed)throw new Error("CanopyX: open the details of a loaded node.");if(typeof this.opts.onDetails==="function"){const node=JSON.parse(JSON.stringify(loose||rows[index].h)),controller=new AbortController();owner.signal.addEventListener("abort",()=>controller.abort(),{once:true});return Promise.resolve(this.opts.onDetails({node,signal:controller.signal,returnFocus}))}
|
|
84
|
+
if(TREE_DETAILS.active){TREE_DETAILS.active._replaced=true;TREE_DETAILS.active.close();TREE_DETAILS.active.remove()}
|
|
85
|
+
const dialog=TREE_DETAILS.active=this.recordDrawer=h("dialog","cx-host cx-tree-tools cx-drawer"),head=h("div","cx-drawer-h"),title=h("h4"),body=h("div","cx-drawer-body");dialog._returnFocus=returnFocus;dialog.setAttribute("data-cx-theme",this.host.getAttribute("data-cx-theme"));const theme=getComputedStyle(this.host);dialog.style.colorScheme=theme.colorScheme;for(const name of theme)if(name.startsWith("--cx-"))dialog.style.setProperty(name,theme.getPropertyValue(name));title.id=this.id+"-record-title";title.tabIndex=-1;title.setAttribute("aria-level","2");dialog.setAttribute("aria-labelledby",title.id);const button=(icon,label,run)=>{const item=gridDecorateButton(gridButton("",run),icon,true);item.classList.add("icon");item.setAttribute("aria-label",labels[label]);return item};const step=position=>{paint(position);focusDrawerTitle(title)};const previous=button("up","gridPreviousRecord",()=>step(index-1)),next=button("down","gridNextRecord",()=>step(index+1));head.append(h("div"),previous,next,button("close","gridCloseRecord",()=>dialog.close()));head.firstChild.appendChild(title);dialog.append(head,body);let shown=loose,paints=null;const paint=position=>{if(!loose&&(position<0||position>=rows.length))return;if(!loose){index=position;shown=rows[index].h}
|
|
86
|
+
const node=shown;paints?.abort();paints=new AbortController();setText(title,node.label);dialog._cxRecord=node;dialog.setAttribute("data-cx-record",node.id);dialog.setAttribute("data-cx-view",this.view.id);previous.disabled=!!loose||!index;next.disabled=!!loose||index===rows.length-1;this.paintDrawerBody(node,body,dialog,{index:loose?null:index,signal:paints.signal});dialog.dispatchEvent(new CustomEvent("cx-drawer-paint",{detail:{id:node.id,index:loose?null:index}}))};dialog._cxPaint=node=>{shown=node;paint(index)};dialog.addEventListener("keydown",event=>{if(event.defaultPrevented)return;if(event.key==="Escape"){event.preventDefault();dialog.close()}
|
|
87
|
+
else if((event.key==="ArrowUp"||event.key==="ArrowDown")&&!event.target.matches("input,textarea,select,[role=tab]")&&!event.target.closest(".cx-data-grid,.cx-record-nested")){event.preventDefault();step(index +(event.key==="ArrowUp"?-1:1))}});const close=()=>dialog.close();owner.signal.addEventListener("abort",close,{once:true});dialog.addEventListener("close",()=>{owner.signal.removeEventListener("abort",close);paints?.abort();dialog.remove();if(TREE_DETAILS.active===dialog)TREE_DETAILS.active=null;if(this.recordDrawer!==dialog||this.destroyed)return;this.recordDrawer=null;if(TREE_DETAILS.active||dialog._replaced)return;const key=shown.id,row=this.rows.find(w=>w.key===key);if(returnFocus?.isConnected&&(!returnFocus.dataset.cxRecord||returnFocus.dataset.cxRecord===id))returnFocus.focus({preventScroll:true});else if(row)this.setFocus(row,true);else this.grid.focus({preventScroll:true})},{once:true});RECORD_IMPL.decorate?.(this,dialog,{head,identity:head.firstChild,title,body,options});document.body.appendChild(dialog);const phone=this.host.clientWidth<=640;dialog.classList.toggle("cx-phone",phone);if(phone)dialog.showModal();else dialog.show();paint(index);focusDrawerTitle(title);return dialog},paintDrawerBody(node,body,dialog,context){if(RECORD_IMPL.paint&&this.recordNeeded(node))return RECORD_IMPL.paint(this,node,body,dialog,context);const sections=new Map();body.replaceChildren();this.columns.forEach((column,position)=>{if(!position||column.drawer===false)return;const name=column.section||this.labels.gridDetailsSection;if(!sections.has(name)){const heading=h("div","cx-drawer-s"),list=h("dl","cx-dl");setText(heading,name);sections.set(name,list);body.append(heading,list)}
|
|
88
|
+
const term=h("dt"),value=h("dd");setText(term,column.title);term.setAttribute("data-cx-field",column.id);value.setAttribute("data-cx-field",column.id);this.paintDrawerValue(column,node,value,position,context);sections.get(name).append(term,value)})},paintDrawerValue(column,node,value,position,context){const cell=this.cellOf(node,column,position),object=isCellObject(cell);if(typeof column.render==="function"){try{if(column.render(node,value,{column:column.id,level:1,expanded:false,index:position,signal:context.signal,onDispose:cleanup=>{if(context.signal.aborted)cleanup();else context.signal.addEventListener("abort",cleanup,{once:true})}})===true)return}
|
|
89
|
+
catch(error){this.emit("error",{error})}}
|
|
90
|
+
const text=cellText(cell,column,this.fmt),span=h("span");applyTone(span,"cx-drawer-text" +(text?"":" p-missing"),toneOf(object?cell.tone:null));setText(span,text||"—");if(object&&cell.title)span.title=cell.title;value.appendChild(span);if(object)for(const badge of cell.badges||[])value.appendChild(badgeElement(badge))}});const TREE_EXPORT_PART=definePart(TreeGrid,"export","export part",()=>({DataGrid:TreeGrid,EXPORT_IMPL,h,setText,gridButton,gridOption,fill,numberFormat,gridExportField,gridOperationActive,formatting,cellValue,cellText,isCellObject,exportTimeout,exportFormat,EXPORT_FORMATS}));function loadExportPart(){return loadPart(TREE_EXPORT_PART)}
|
|
91
|
+
Object.assign(TreeGrid.prototype,TREE_EXPORT,{async renderGridExport(panel){if(panel.firstChild)return;setText(panel,this.labels.loading);try{await loadExportPart();if(!this.destroyed&&panel.isConnected){setText(panel,"");this.renderGridExport(panel);this.controlFlyouts.forEach(item=>item.position())}}
|
|
92
|
+
catch(error){if(this.destroyed||!panel.isConnected)return;panel.replaceChildren(gridButton(fill(this.labels.loadError,{error:error.message}),()=>{panel.replaceChildren();this.renderGridExport(panel)}));this.emit("error",{error})}},exportText(...args){return loadExportPart().then(()=>EXPORT_IMPL.exportText.apply(this,args))}});installed.add(context.TreeGrid.prototype)}};(global.CanopyXParts||=[]).push(["tree-tools",part])})(typeof window!=="undefined"?window:globalThis);
|