@evotecit/canopyx 0.3.11 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CanopyX.Html/Assets/canopyx-calendar-edit.js +36 -18
- package/CanopyX.Html/Assets/canopyx-calendar-ics.js +7 -5
- package/CanopyX.Html/Assets/canopyx-calendar.css +124 -116
- package/CanopyX.Html/Assets/canopyx-calendar.js +74 -54
- package/CanopyX.Html/Assets/canopyx-cell-range.css +8 -8
- package/CanopyX.Html/Assets/canopyx-cell-range.js +1 -1
- package/CanopyX.Html/Assets/canopyx-changes.css +113 -113
- package/CanopyX.Html/Assets/canopyx-changes.js +7 -10
- package/CanopyX.Html/Assets/canopyx-column-groups.css +5 -5
- package/CanopyX.Html/Assets/canopyx-column-groups.js +1 -1
- package/CanopyX.Html/Assets/canopyx-data.js +2 -2
- package/CanopyX.Html/Assets/canopyx-detail-rows.css +9 -9
- package/CanopyX.Html/Assets/canopyx-detail-rows.js +2 -2
- package/CanopyX.Html/Assets/canopyx-editing.css +18 -18
- package/CanopyX.Html/Assets/canopyx-editing.js +1 -1
- package/CanopyX.Html/Assets/canopyx-enhance.js +2 -2
- package/CanopyX.Html/Assets/canopyx-export.js +8 -4
- package/CanopyX.Html/Assets/canopyx-facets.css +33 -33
- package/CanopyX.Html/Assets/canopyx-facets.js +10 -11
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +57 -57
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +15 -11
- package/CanopyX.Html/Assets/canopyx-flow-checks.css +11 -11
- package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-command.css +7 -7
- package/CanopyX.Html/Assets/canopyx-flow-command.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-dialog.css +7 -7
- package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-drafts.css +7 -7
- package/CanopyX.Html/Assets/canopyx-flow-drafts.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-entry.css +17 -76
- package/CanopyX.Html/Assets/canopyx-flow-entry.js +9 -3
- package/CanopyX.Html/Assets/canopyx-flow-host.css +4 -4
- package/CanopyX.Html/Assets/canopyx-flow-host.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-module.mjs +9 -3
- package/CanopyX.Html/Assets/canopyx-flow-pick.css +4 -4
- package/CanopyX.Html/Assets/canopyx-flow-pick.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-preview.css +6 -6
- package/CanopyX.Html/Assets/canopyx-flow-preview.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-records.css +3 -3
- package/CanopyX.Html/Assets/canopyx-flow-records.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-tasks.css +17 -17
- package/CanopyX.Html/Assets/canopyx-flow-tasks.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow.css +79 -79
- package/CanopyX.Html/Assets/canopyx-flow.js +1 -1
- package/CanopyX.Html/Assets/canopyx-format-editor.css +23 -23
- package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -3
- package/CanopyX.Html/Assets/canopyx-formatting.css +17 -17
- package/CanopyX.Html/Assets/canopyx-formatting.js +5 -5
- package/CanopyX.Html/Assets/canopyx-forms.css +5 -5
- package/CanopyX.Html/Assets/canopyx-forms.js +1 -1
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +134 -77
- package/CanopyX.Html/Assets/canopyx-grid-options.css +10 -0
- package/CanopyX.Html/Assets/canopyx-grid-options.js +47 -0
- package/CanopyX.Html/Assets/canopyx-grid.css +199 -261
- package/CanopyX.Html/Assets/canopyx-grid.js +134 -77
- package/CanopyX.Html/Assets/canopyx-grouping.css +17 -17
- package/CanopyX.Html/Assets/canopyx-grouping.js +12 -9
- package/CanopyX.Html/Assets/canopyx-highlight.css +14 -14
- package/CanopyX.Html/Assets/canopyx-highlight.js +2 -2
- package/CanopyX.Html/Assets/canopyx-interactive.css +94 -155
- package/CanopyX.Html/Assets/canopyx-interactive.js +58 -24
- package/CanopyX.Html/Assets/canopyx-labels-de.js +5 -0
- package/CanopyX.Html/Assets/canopyx-labels-es.js +5 -0
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +5 -0
- package/CanopyX.Html/Assets/canopyx-labels-it.js +5 -0
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +5 -0
- package/CanopyX.Html/Assets/canopyx-layouts.css +17 -17
- package/CanopyX.Html/Assets/canopyx-layouts.js +4 -12
- package/CanopyX.Html/Assets/canopyx-link.css +7 -7
- package/CanopyX.Html/Assets/canopyx-link.js +1 -1
- package/CanopyX.Html/Assets/canopyx-live.css +9 -9
- package/CanopyX.Html/Assets/canopyx-live.js +2 -2
- package/CanopyX.Html/Assets/canopyx-matrix.css +74 -74
- package/CanopyX.Html/Assets/canopyx-matrix.js +3 -4
- package/CanopyX.Html/Assets/canopyx-module.mjs +58 -24
- package/CanopyX.Html/Assets/canopyx-pager.css +2 -2
- package/CanopyX.Html/Assets/canopyx-pager.js +1 -1
- package/CanopyX.Html/Assets/canopyx-presenters.js +11 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.css +49 -49
- package/CanopyX.Html/Assets/canopyx-record-panel.js +13 -11
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +142 -84
- package/CanopyX.Html/Assets/canopyx-reporting.css +214 -276
- package/CanopyX.Html/Assets/canopyx-reporting.js +142 -84
- package/CanopyX.Html/Assets/canopyx-timeline.css +28 -28
- package/CanopyX.Html/Assets/canopyx-timeline.js +11 -10
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +47 -46
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +5 -4
- package/CanopyX.Html/Assets/canopyx.css +81 -142
- package/CanopyX.Html/Assets/canopyx.js +58 -24
- package/JavaScript/calendar.d.ts +15 -0
- package/JavaScript/grid.d.ts +29 -4
- package/JavaScript/hosts.d.ts +11 -0
- package/JavaScript/locales/de.mjs +5 -0
- package/JavaScript/locales/es.mjs +5 -0
- package/JavaScript/locales/fr.mjs +5 -0
- package/JavaScript/locales/it.mjs +5 -0
- package/JavaScript/locales/pl.mjs +5 -0
- package/JavaScript/plugins.d.ts +4 -0
- package/JavaScript/protocol.d.ts +14 -1
- package/JavaScript/records.d.ts +2 -0
- package/README.md +6 -2
- package/package.json +7 -1
|
@@ -24,14 +24,15 @@ function checkPage(doc,node){checkDocument(doc,"page");if(!Array.isArray(doc.ite
|
|
|
24
24
|
if(!Object.hasOwn(doc,"next"))throw new Error("CanopyX: page continuation is required.");if(doc.next!==null)requireIdentifier(doc.next,"page continuation");const parent=node?node.id:null;if(doc.parent!==parent)throw new Error("CanopyX: page parent does not match the requested node.");return doc}
|
|
25
25
|
function isCellObject(cell){return cell!==null&&typeof cell==="object"}
|
|
26
26
|
function cellValue(cell){return isCellObject(cell)?(cell.value===undefined?null:cell.value):(cell===undefined?null:cell)}
|
|
27
|
-
const NO_TONE={cls:"",host:null};const tones=new Map();function
|
|
27
|
+
const NO_TONE={cls:"",host:null};const tones=new Map();function toneVariable(name,background=false,fallback){const role={success:"good",warning:"warn",danger:"bad"}[name]||name;const key="--hfx-color-status-"+role +(background?"-bg":"-fg");return "var("+key +(STATUS_FALLBACKS[key]||fallback?"," +(STATUS_FALLBACKS[key]||fallback):"")+ ")"}
|
|
28
|
+
function toneOf(name){let tone=typeof name==="string"?tones.get(name):NO_TONE;if(!tone){if(!/^[a-z][a-z0-9-]{0,31}$/.test(name) || name.endsWith("-bg")) {
|
|
28
29
|
return NO_TONE}
|
|
29
30
|
const host=!/^(neutral|info|success|warning|danger|muted)$/.test(name);
|
|
30
31
|
tone={cls:" cx-tone-"+name +(host?" cx-toned":""),host:host?name:null};if(tones.size<256)tones.set(name,tone)}
|
|
31
32
|
return tone}
|
|
32
33
|
function applyTone(element,base,tone){element.className=base+tone.cls;toneColors(element,tone)}
|
|
33
34
|
function toneColors(element,tone){if((element._tone||null)===tone.host){return}
|
|
34
|
-
element._tone=tone.host;if(tone.host){element.style.setProperty("--cx-t",
|
|
35
|
+
element._tone=tone.host;if(tone.host){element.style.setProperty("--cx-t",toneVariable(tone.host));element.style.setProperty("--cx-t-bg",toneVariable(tone.host,true))}else{element.style.removeProperty("--cx-t");element.style.removeProperty("--cx-t-bg")}}
|
|
35
36
|
function pad2(value){return value<10?"0"+value:String(value)}
|
|
36
37
|
const dateTexts=new Map();function dateText(value){let texts=dateTexts.get(value);if(texts===undefined){const time=Date.parse(value);const d=new Date(time);texts=isNaN(time)?null:[String(d.getUTCFullYear()).padStart(4,"0")+ "-"+pad2(d.getUTCMonth()+ 1)+ "-"+pad2(d.getUTCDate())+ " "+pad2(d.getUTCHours())+ ":"+pad2(d.getUTCMinutes()),String(d.getFullYear()).padStart(4,"0")+ "-"+pad2(d.getMonth()+ 1)+ "-"+pad2(d.getDate())+ " "+pad2(d.getHours())+ ":"+pad2(d.getMinutes())];if(dateTexts.size>=DATE_CACHE)dateTexts.clear();dateTexts.set(value,texts)}
|
|
37
38
|
return texts}
|
|
@@ -44,9 +45,10 @@ if(typeof value==="boolean"){return value?fmt.labels.yes:fmt.labels.no}
|
|
|
44
45
|
if(typeof value==="number"&&kind==="number"){return numberText(value,fmt.lang,format)}
|
|
45
46
|
if(typeof value==="string"&&kind==="datetime"){return formatDate(value,fmt)}
|
|
46
47
|
return String(value)}
|
|
47
|
-
function cellText(cell,column,fmt){if(isCellObject(cell)&&typeof cell.text==="string"){return cell.text}
|
|
48
|
+
function cellText(cell,column,fmt){const raw=cellValue(cell);if(typeof raw==="string"&&Object.hasOwn(column.valueLabels||{},raw))return column.valueLabels[raw];if(isCellObject(cell)&&typeof cell.text==="string"){return cell.text}
|
|
48
49
|
return formatValue(cellValue(cell),column.kind,fmt,column.format)}
|
|
49
|
-
const collator=new Intl.Collator(undefined,{numeric:true,sensitivity:"base"});const safeGridNumber=value=>Number.isFinite(value)&&Math.abs(value)<=Number.MAX_SAFE_INTEGER;function sortKey(cell,column){
|
|
50
|
+
const collator=new Intl.Collator(undefined,{numeric:true,sensitivity:"base"});const safeGridNumber=value=>Number.isFinite(value)&&Math.abs(value)<=Number.MAX_SAFE_INTEGER;function sortKey(cell,column){if(column.valueOrder?.length){const raw=cellValue(cell);if(raw==null)return{rank:2,value:0};const at=typeof raw==="string"?column.valueOrder.indexOf(raw):-1;return{rank:1,category:at<0?column.valueOrder.length:at,type:typeof raw,value:raw}}
|
|
51
|
+
let value=isCellObject(cell)&&(typeof cell.sort==="string"||safeGridNumber(cell.sort))?cell.sort:cellValue(cell);if((value===null||value==="")&&isCellObject(cell)&&typeof cell.text==="string"&&cell.text!==""){value=cell.text}
|
|
50
52
|
if(value===null||value===""){return{rank:2,value:0}}
|
|
51
53
|
if(typeof value==="boolean"){return{rank:0,value:value?1:0}}
|
|
52
54
|
if(typeof value==="number"){return{rank:0,value}}
|
|
@@ -54,7 +56,20 @@ if(column.kind==="datetime"){const time=Date.parse(value);if(!isNaN(time)){retur
|
|
|
54
56
|
return{rank:1,value:String(value)}}
|
|
55
57
|
function compareKeys(a,b,direction){if(a.rank!==b.rank){return a.rank-b.rank}
|
|
56
58
|
if(a.rank===2){return 0}
|
|
57
|
-
const order=a.
|
|
59
|
+
const order=a.category!==undefined?a.category-b.category||
|
|
60
|
+
(a.type<b.type?-1:a.type>b.type?1:a.value<b.value?-1:a.value>b.value?1:0):
|
|
61
|
+
a.rank===0?(a.value<b.value?-1:a.value>b.value?1:0):collator.compare(a.value,b.value);return order*direction}
|
|
62
|
+
function columnNumericTone(column,raw){return typeof raw==="number"&&Number.isFinite(raw)?column.numericTones?.find(rule=>
|
|
63
|
+
rule.operator==="atMost"?raw<=rule.value:rule.operator==="atLeast"?raw>=rule.value:
|
|
64
|
+
rule.operator==="below"?raw<rule.value:raw>rule.value):undefined}
|
|
65
|
+
function columnValueTone(column,cell){const raw=cellValue(cell);return columnNumericTone(column,raw)?.tone||(typeof raw==="string"&&Object.hasOwn(column.valueTones||{},raw)?column.valueTones[raw]:undefined)}
|
|
66
|
+
function validateColumnValues(column){const fail=()=>{throw new Error("CanopyX: invalid column value labels, order, tones or line limit.")};const tone=value=>typeof value==="string"&&/^[a-z][a-z0-9-]{0,31}$/.test(value) && !value.endsWith("-bg");
|
|
67
|
+
if(column.maxLines!==undefined&&(!Number.isInteger(column.maxLines)||column.maxLines<1||column.maxLines>12))fail();for(const name of["valueLabels","valueTones"])if(column[name]!==undefined){const map=column[name];if(column.kind!=="text"||!map||typeof map!=="object"||Array.isArray(map)||Object.keys(map).length>512||
|
|
68
|
+
Object.entries(map).some(([key,value])=>key.length>4096||(name==="valueTones"?!tone(value):typeof value!=="string"||value.length>4096)))fail()}
|
|
69
|
+
if(column.valueOrder!==undefined&&(column.kind!=="text"||!Array.isArray(column.valueOrder)||column.valueOrder.length>512||
|
|
70
|
+
new Set(column.valueOrder).size!==column.valueOrder.length||column.valueOrder.some(value=>typeof value!=="string"||value.length>4096)))fail();if(column.numericTones!==undefined&&(column.kind!=="number"||!Array.isArray(column.numericTones)||column.numericTones.length>32||
|
|
71
|
+
column.numericTones.some(rule=>!rule||!["atMost","atLeast","below","above"].includes(rule.operator)||!Number.isFinite(rule.value)||
|
|
72
|
+
!tone(rule.tone)||typeof rule.label!=="string"||!rule.label.trim()||rule.label.length>4096)))fail()}
|
|
58
73
|
function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, name) => (values && Object.hasOwn(values, name) ? String(values[name]) : match));
|
|
59
74
|
}
|
|
60
75
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
@@ -74,6 +89,12 @@ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.
|
|
|
74
89
|
catch(_){trustPolicy=null}}
|
|
75
90
|
return trustPolicy?trustPolicy["create"+kind](value):value}
|
|
76
91
|
function hostHtml(element,html,sanitize,kind){const text=String(html??""),value=sanitize?sanitize(text,{kind}):text;if(value?.nodeType)element.replaceChildren(value);else if(typeof value==="string")element.innerHTML=trusted("HTML",value);else if(global.trustedTypes?.isHTML?.(value))element.innerHTML=value;else throw new Error("CanopyX: invalid sanitizeHtml result.")}
|
|
92
|
+
const STATUS_FALLBACKS={"--hfx-color-status-bad-bg":"light-dark(#f9e4e4,#3c272a)","--hfx-color-status-bad-fg":"light-dark(#b8292a,#f47171)","--hfx-color-status-good-bg":"light-dark(#e2f0e9,#1f362f)","--hfx-color-status-good-fg":"light-dark(#177345,#4cc78a)","--hfx-color-status-info-bg":"light-dark(#e4ecfa,#262f41)","--hfx-color-status-info-fg":"light-dark(#2b5fc0,#74a2f7)","--hfx-color-status-neutral-bg":"light-dark(#eeeff0,#2a2c31)","--hfx-color-status-neutral-fg":"light-dark(#5b6069,#a0a5ae)","--hfx-color-status-warn-bg":"light-dark(#f8efde,#3b3322)","--hfx-color-status-warn-fg":"light-dark(#8c5c05,#eeb640)"};const MODE_ATTRIBUTES=["data-theme","data-cx-theme","data-hfx-mode","data-bs-theme","data-hfx-theme","data-hfx-tokens"];const THEME_ATTRIBUTES=[...MODE_ATTRIBUTES,"data-hfx-style","data-hfx-density","data-cx-fallback-mode","style","class"];function watchTheme(host,signal){const attributes=THEME_ATTRIBUTES;const previous=host.getAttribute("data-cx-fallback-mode");const refresh=()=>{const parent=host.parentElement&&getComputedStyle(host.parentElement);const inherited=parent?.colorScheme;let mode=null;if(!parent?.getPropertyValue("--hfx-color-surface").trim()){outer:for(let owner=host;owner;owner=owner.parentElement)for(const attribute of MODE_ATTRIBUTES){const value=owner.getAttribute(attribute);if(value==="light"||value==="dark"){mode=value;break outer}}}
|
|
93
|
+
if(parent?.getPropertyValue("--hfx-color-surface").trim()||!mode&&inherited&&inherited!=="normal"){if(host.hasAttribute("data-cx-fallback-mode"))host.removeAttribute("data-cx-fallback-mode")}else if(host.getAttribute("data-cx-fallback-mode")!==(mode||"auto"))host.setAttribute("data-cx-fallback-mode",mode||"auto")};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:attributes});refresh();const dispose=()=>{observer.disconnect();if(previous===null)host.removeAttribute("data-cx-fallback-mode");else host.setAttribute("data-cx-fallback-mode",previous)};signal?.addEventListener("abort",dispose,{once:true});return dispose}
|
|
94
|
+
function overlayTheme(host,element,inherit=false){for(const name of["data-hfx-style","data-hfx-mode","data-hfx-density"]){const owner=host.closest("["+name+"]");if(owner&&!inherit)element.setAttribute(name,owner.getAttribute(name));else element.removeAttribute(name)}
|
|
95
|
+
const theme=getComputedStyle(host),parent=inherit&&host.parentElement&&getComputedStyle(host.parentElement);element.style.colorScheme=theme.colorScheme;const copied=[];for(const name of theme)if((name.startsWith("--cx-")||name.startsWith("--hfx-"))&&(!parent||theme.getPropertyValue(name)!==parent.getPropertyValue(name))){element.style.setProperty(name,theme.getPropertyValue(name));copied.push(name)}
|
|
96
|
+
return copied}
|
|
97
|
+
function watchOverlayTheme(host,element,signal){if(signal?.aborted)return()=>{};let copied=[];const refresh=()=>{for(const name of copied)element.style.removeProperty(name);copied=overlayTheme(host,element,element.parentElement===host.parentElement)};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:THEME_ATTRIBUTES});const media=["(prefers-color-scheme:dark)","(prefers-contrast:more)","(forced-colors:active)"].map(query=>matchMedia(query));for(const query of media)query.addEventListener("change",refresh);const dispose=()=>{observer.disconnect();for(const query of media)query.removeEventListener("change",refresh);signal?.removeEventListener("abort",dispose)};signal?.addEventListener("abort",dispose,{once:true});dispose.refresh=refresh;refresh();return dispose}
|
|
77
98
|
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{gridViews:"Views",gridViewName:"View name",gridSaveView:"Save view",gridRemoveView:"Remove view",gridResetView:"Reset view",gridChooseView:"Choose a saved view",gridApply:"Apply",gridFindColumn:"Find a column…",gridShowAllColumns:"Show all",gridResetColumns:"Reset columns",gridReorderColumn:"{column}: drag, or press Alt+Up or Alt+Down to move",gridPinnedLeft:"Pinned left",gridPinnedRight:"Pinned right",gridResponsiveHidden:"Hidden at this width",gridExport:"Export",gridVisibleRows:"Visible rows",gridSelectedRows:"Selected rows",gridAllRows:"All rows",gridDownloadCsv:"Download CSV",gridCopy:"Copy",gridExportProgress:"{completed} of {total} records",gridExportReading:"{completed} records",gridExportCancelled:"Export cancelled",gridCancelExport:"Cancel export",gridMore:"More",gridPrint:"Print",gridDetails:"Record details",gridDetailsSection:"Details",gridPreviousRecord:"Previous record",gridNextRecord:"Next record",gridCloseRecord:"Close"}));DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{recordBack:"Back",recordBackTo:"Back to {record}",recordTrail:"Record trail",recordShowing:"Showing {record}",recordTabs:"Record views",recordSections:"Jump to a section",recordOtherFields:"Other fields",recordShowEmpty:"Show empty fields ({count})",recordHideEmpty:"Hide empty fields",recordActions:"Record actions",recordCopyValues:"Copy values",recordCopyJson:"Copy as JSON",recordCopyLink:"Copy link",recordCopied:"Copied to the clipboard",recordPrint:"Print record",recordExportCsv:"Export CSV",recordExportJson:"Export JSON",recordOpenAll:"Open all in grid",recordLoadMore:"Load more",recordCount:"{shown} of {total}",recordItems:"{count} items",recordMore:"+{count}",recordShowAll:"Show all {count}",recordRetry:"Retry",recordLoadFailed:"Could not load the record details: {error}",recordUnavailable:"Record {id} is not available here.",recordField:"Field",recordValue:"Value",recordSection:"Section",recordBefore:"Before",recordAfter:"After",recordAdded:"Added",recordRemoved:"Removed",recordChanged:"{count} changed fields"}));function boundedPattern(source,exact=true,whole=false){const bad=()=>{throw new Error("CanopyX: pattern requires literals, character classes and at most one variable repetition anchored at the start; groups, alternatives and backreferences are unsupported.")};if(typeof source!=="string"||source.length>256)bad();let width=0,variable=0;for(let i=0;i<source.length;){const unit=source[i++];if(unit==="^"&&i===1||unit==="$"&&i===source.length)continue;if(unit==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbBnrtfv\\.^$*+?{}\[\]()|/]$/.test(escape)) bad();
|
|
78
99
|
}else if(unit==="["){let closed=false;while(i<source.length){const c=source[i++];if(c==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbnrtfv\\.^$*+?{}\[\]()|/-]$/.test(escape)) bad(); }
|
|
79
100
|
else if(c==="]"){closed=true;break}}
|
|
@@ -117,7 +138,8 @@ if(column.kind==="datetime"){const date=typeof value==="string"&&/^\d{4}-\d\d-\d
|
|
|
117
138
|
if(!Number.isFinite(date))
|
|
118
139
|
throw new Error("CanopyX: date grid cells need ISO dates with an explicit time zone.");return date}
|
|
119
140
|
if(typeof value!=="string"&&typeof value!=="boolean")throw new Error("CanopyX: text grid cells need strings or booleans.");return value}
|
|
120
|
-
function
|
|
141
|
+
function gridExactTokens(column){return column.kind==="text"&&(column.valueOrder?.length||Object.keys(column.valueLabels||{}).length)}
|
|
142
|
+
function cellMatches(cell,predicate,column){const scalar=gridScalar(cell,column),op=predicate.operator;if(op==="isNull")return scalar===null;if(op==="isNotNull")return scalar!==null;if(scalar===null)return false;const normalize=value=>column.kind==="text"&&!gridExactTokens(column)&&typeof value==="string"?foldText(value):value;const value=normalize(scalar),values=predicate.values.map(operand=>normalize(gridScalar(operand,column))),operand=values[0];switch(op){case "eq":return value===operand;case "ne":return value!==operand;case "in":return values.includes(value);case "contains":return String(value).includes(String(operand));case "startsWith":return String(value).startsWith(String(operand));case "gt":return value>operand;case "ge":return value>=operand;case "lt":return value<operand;case "le":return value<=operand}
|
|
121
143
|
return false}
|
|
122
144
|
function validateGridRows(rows,columns,ids=new Set()){if(!Array.isArray(rows))throw new Error("CanopyX: grid rows must be an array.");const declared=new Map(columns.map(column=>[column.id,column]));for(const row of rows){requireIdentifier(row&&row.id,"grid row ID");if(ids.has(row.id))throw new Error("CanopyX: duplicate grid row ID "+row.id);ids.add(row.id);if(!row.cells||typeof row.cells!=="object"||Array.isArray(row.cells))
|
|
123
145
|
throw new Error("CanopyX: invalid flat row fields.");gridDecoration(row.tone,row.className);for(const id of Object.keys(row.cells)){if(!declared.has(id))throw new Error("CanopyX: undeclared grid column "+id);const cell=row.cells[id];if(isCellObject(cell)){if(Array.isArray(cell)||
|
|
@@ -189,9 +211,9 @@ throw new Error("CanopyX: unknown source kind '"+kind+"'.")}
|
|
|
189
211
|
async function remoteJson(url,type,timeoutMs,lifetime,signal){const controller=new AbortController();const signals=Array.from(new Set([lifetime,signal].filter(Boolean)));const abort=()=>controller.abort();signals.forEach((item)=>{if(item.aborted)abort();else item.addEventListener("abort",abort,{once:true})});let timedOut=false;const timer=setTimeout(()=>{timedOut=true;abort()},timeoutMs);try{const response=await fetch(url,{headers:{Accept:"application/json"},signal:controller.signal});if(!response.ok){if(response.body)await response.body.cancel().catch(()=>{});throw new Error(response.status+" "+response.statusText)}
|
|
190
212
|
return checkDocument(await response.json(),type)}catch(error){if(timedOut)throw new Error("CanopyX: remote request timed out after "+timeoutMs+" milliseconds.");throw error}finally{abort();clearTimeout(timer);signals.forEach((item)=>item.removeEventListener("abort",abort))}}
|
|
191
213
|
class TreeGrid{constructor(host,options){const view=checkDocument(options.view,"view");requireIdentifier(view.id,"view ID");if(view.columns.some(column=>column.format!==undefined))throw new Error("CanopyX: number formats apply to flat grids only.");this.host=host;this.view=view;this.opts=options;for(const name of["isSelectable","beforeSelect","sanitizeHtml"]){if(options[name]!==undefined&&typeof options[name]!=="function")throw new Error("CanopyX: "+name+" must be a function.")}
|
|
192
|
-
this.id="cx" + ++instanceSeq;this.lifetime=new AbortController();this.source=options.source||sourceFor(view,{signal:this.lifetime.signal,timeoutMs:options.requestTimeoutMs});this.queryAware=this.source.queryAware===true;this.dataLifetime=new AbortController();this.acceptedQuery=Object.freeze({version:1,sort:null,filters:Object.freeze([])});this.datasetRevision=null;this.rowH=view.rowHeight||
|
|
214
|
+
this.id="cx" + ++instanceSeq;this.lifetime=new AbortController();this.source=options.source||sourceFor(view,{signal:this.lifetime.signal,timeoutMs:options.requestTimeoutMs});this.queryAware=this.source.queryAware===true;this.dataLifetime=new AbortController();this.acceptedQuery=Object.freeze({version:1,sort:null,filters:Object.freeze([])});this.datasetRevision=null;this.rowH=view.rowHeight||40;this.pageSize=view.pageSize||100;this.retainedNodeLimit=options.retainedNodeLimit===undefined?1024:options.retainedNodeLimit;if(!validStructuralCount(this.retainedNodeLimit))throw new Error("CanopyX: retainedNodeLimit must be a nonnegative 32-bit integer.");this.inactiveNodeLimit=options.inactiveNodeLimit===undefined?4096:options.inactiveNodeLimit;if(!validStructuralCount(this.inactiveNodeLimit))throw new Error("CanopyX: inactiveNodeLimit must be a nonnegative 32-bit integer.");this.multi=view.selection==="multiple";this.lang=document.documentElement.lang||undefined;this.labels=labelsFor(view.labels,options.labels);this.tools=Object.assign({},view.toolbar,options.toolbar);if(Object.entries(this.tools).some(([name,value])=>!/^(search|filters|columns|views|export|more|matches|layout)$/.test(name) || typeof value !== "boolean"))
|
|
193
215
|
throw new Error("CanopyX: toolbar options are booleans by control name.");this.local=view.timeZone==="local";this.fmt=formatting(this.lang,this.local,this.labels);this.kind="tree";this.plugins=viewPlugins(options,this.kind);const renderers=hostRenderers(options.renderers||{},view.columns,this.plugins);if(!options.formatLink!==!options.parseLink){throw new Error("CanopyX: formatLink and parseLink define one link scheme and are given together.")}
|
|
194
|
-
this.columns=view.columns.map((column,index)=>({...column,hidden:index>0&&!!column.hidden,render:Object.hasOwn(renderers,column.id)?renderers[column.id]:null}));this.columns.forEach(prepareWidth);this.keyMap=new Map();this.root={key:null,h:null,parent:null,level:0,idx:0,expanded:true,children:null,total:null,next:null,loading:false,error:null};if(!options.source&&(!view.source||view.source.kind==="inline")){this.root.inlineItems=view.roots||[]}
|
|
216
|
+
this.columns=view.columns.map((column,index)=>({...column,hidden:index>0&&!!column.hidden,render:Object.hasOwn(renderers,column.id)?renderers[column.id]:null}));this.columns.forEach(prepareWidth);this.columns.forEach(validateColumnValues);this.keyMap=new Map();this.root={key:null,h:null,parent:null,level:0,idx:0,expanded:true,children:null,total:null,next:null,loading:false,error:null};if(!options.source&&(!view.source||view.source.kind==="inline")){this.root.inlineItems=view.roots||[]}
|
|
195
217
|
this.rows=[];this.tops=[0];this.total=0;this.version=1;this.rendered=new Map();this.pool=[];this.focused=null;this.selected=new Set();this.anchor=null;this.filter=null;this.declaredFilter=null;this.filterExpand=false;this.activeFilters=new Set();this.sortState=null;this.typeBuf="";this.typeAt=0;this.rafId=0;this.iconTemplates=this.buildIcons(view.icons||{});this.initializing=true;this.prepareViewModes();this.build();this.buildToolbar();if(view.deepLink)loadPart(LINKS).catch(()=>{});this.ready=this.modesReady?Promise.all([this.init(),this.modesReady]).then(([result])=>result):this.init()}
|
|
196
218
|
async search(query,limit){if(this.destroyed)throw new DOMException("Grid was destroyed.","AbortError");const navigation=navigationScope(this,this.dataLifetime.signal);try{const result=await navigation.wait(this.source.search(query,limit,this.sourceRequest(this.dataLifetime.signal)));if(navigation.cancelled())throw new DOMException("Search snapshot was retired.","AbortError");if(this.queryAware)snapshotRevision(result,this.datasetRevision);return validateSearchResult(result)}finally{navigation.dispose()}}
|
|
197
219
|
buildIcons(icons){const templates=new Map();Object.keys(icons).forEach((key)=>{const holder=h("span","cx-icon");holder.setAttribute("aria-hidden","true");hostHtml(holder,icons[key],this.opts.sanitizeHtml,"icon");// trusted host SVG, declared once per view
|
|
@@ -256,10 +278,9 @@ value.sort===undefined||typeof value!=="object")throw new Error("CanopyX: query
|
|
|
256
278
|
const named=new Set(value.filters);if(named.size!==value.filters.length||value.filters.some(id=>!(grid.view.filters||[]).some(f=>f.id===id)))
|
|
257
279
|
throw new Error("CanopyX: query filters must be unique declared IDs.");const filters=Object.freeze((grid.view.filters||[]).filter(f=>named.has(f.id)).map(f=>f.id));return Object.freeze({version:1,sort,filters})}
|
|
258
280
|
function snapshotRevision(value,expected){requireIdentifier(value&&value.revision,"dataset revision");if(expected!=null&&value.revision!==expected)throw new Error("CanopyX: dataset revision changed; reload the roots before continuing.");return value.revision}
|
|
259
|
-
Object.assign(TreeGrid.prototype,{getQuery(){return{version:1,sort:this.sortState&&Object.assign({},this.sortState),filters:Array.from(this.activeFilters)}},sourceRequest(signal){return this.queryAware?{signal:signal||this.dataLifetime.signal,query:this.acceptedQuery,revision:this.datasetRevision}:{signal}},syncQueryControls(){this.toolbar.querySelectorAll("[data-cx-filter]").forEach(input=>{input.checked=this.activeFilters.has(input.getAttribute("data-cx-filter"))})},querySortHeader(id){const query=this.pendingQuery||this.acceptedQuery,state=query.sort&&query.sort.column===id?query.sort.direction:null;this.sort(id,state==="asc"?"desc":state==="desc"?null:"asc").catch(()=>{})}});Object.assign(TreeGrid.prototype,{retireWrapper(w){w._invalidated=true;this.retirePage(w);if(this.inlineRetained&&this.inlineRetained.get(w.key)===w)this.inlineRetained.delete(w.key);if(this.inactiveCache)this.inactiveCache.delete(w);if(this.keyMap.get(w.key)===w)this.keyMap.delete(w.key);w.children=null;w.inlineCache=null;w.inlineOrder=null;const selected=this.selected.delete(w);if(this.anchor===w)this.anchor=null;return selected?w:null}});Object.assign(TreeGrid.prototype,{build(){const host=this.host;host.classList.add("cx-host");
|
|
260
|
-
host.style.setProperty("--cx-row-h",this.rowH+"px");this.setTreeColumnPinned(this.view.pinTreeColumn);this.toolbar=h("div","cx-toolbar");this.toolbar.hidden=true;const grid=this.grid=h("div","cx-grid");grid.id=this.id;grid.setAttribute("role","treegrid");grid.setAttribute("aria-label",this.view.label);if(this.multi){grid.setAttribute("aria-multiselectable","true")}
|
|
281
|
+
Object.assign(TreeGrid.prototype,{getQuery(){return{version:1,sort:this.sortState&&Object.assign({},this.sortState),filters:Array.from(this.activeFilters)}},sourceRequest(signal){return this.queryAware?{signal:signal||this.dataLifetime.signal,query:this.acceptedQuery,revision:this.datasetRevision}:{signal}},syncQueryControls(){this.toolbar.querySelectorAll("[data-cx-filter]").forEach(input=>{input.checked=this.activeFilters.has(input.getAttribute("data-cx-filter"))})},querySortHeader(id){const query=this.pendingQuery||this.acceptedQuery,state=query.sort&&query.sort.column===id?query.sort.direction:null;this.sort(id,state==="asc"?"desc":state==="desc"?null:"asc").catch(()=>{})}});Object.assign(TreeGrid.prototype,{retireWrapper(w){w._invalidated=true;this.retirePage(w);if(this.inlineRetained&&this.inlineRetained.get(w.key)===w)this.inlineRetained.delete(w.key);if(this.inactiveCache)this.inactiveCache.delete(w);if(this.keyMap.get(w.key)===w)this.keyMap.delete(w.key);w.children=null;w.inlineCache=null;w.inlineOrder=null;const selected=this.selected.delete(w);if(this.anchor===w)this.anchor=null;return selected?w:null}});Object.assign(TreeGrid.prototype,{build(){const host=this.host;host.classList.add("cx-host");watchTheme(host,this.lifetime.signal);host.style.setProperty("--cx-row-h",this.rowH+"px");this.setTreeColumnPinned(this.view.pinTreeColumn);this.toolbar=h("div","cx-toolbar");this.toolbar.hidden=true;const grid=this.grid=h("div","cx-grid");grid.id=this.id;grid.setAttribute("role","treegrid");grid.setAttribute("aria-label",this.view.label);if(this.multi){grid.setAttribute("aria-multiselectable","true")}
|
|
261
282
|
this.head=h("div","cx-head");this.head.setAttribute("role","rowgroup");this.headRow=h("div","cx-hrow");this.headRow.setAttribute("role","row");this.headRow.setAttribute("aria-rowindex","1");this.head.appendChild(this.headRow);this.canvas=h("div","cx-canvas");this.canvas.setAttribute("role","rowgroup");grid.appendChild(this.head);grid.appendChild(this.canvas);this.live=h("div","cx-live cx-sr-only");this.live.setAttribute("aria-live","polite");this.outline=h("div","cx-outline");host.appendChild(this.toolbar);host.appendChild(grid);host.appendChild(this.live);host.appendChild(this.outline);this.buildHeader();this.onScroll=()=>{this.scheduleRender();this.stateChanged()};this.onPrint=()=>{const table=this.outlineElement();this.outline.replaceChildren(...table?[table]:[])};grid.addEventListener("scroll",this.onScroll,{passive:true});grid.addEventListener("click",(e)=>this.onClick(e));grid.addEventListener("dblclick",(e)=>this.onDblClick(e));grid.addEventListener("pointerover",(e)=>this.cellTip(e));grid.addEventListener("keydown",(e)=>this.onKey(e));this.canvas.addEventListener("focusin",(e)=>{const rowEl=e.target.closest(".cx-row");if(rowEl&&rowEl._w&&this.focused!==rowEl._w){this.focusRevision=(this.focusRevision||0)+ 1;this.focused=rowEl._w;this.scheduleRender()}});this.canvas.addEventListener("focusout",(e)=>this.settleCell(e.relatedTarget));global.addEventListener("beforeprint",this.onPrint);this.onHash=(e)=>{const href=global.location.href;const last=this.locationEvent;this.locationEvent=last&&last.href===href&&last.type!==e.type?null:{href,type:e.type};if(this.locationEvent)this.readLocation()};global.addEventListener("hashchange",this.onHash);global.addEventListener("popstate",this.onHash);const viewWidth=()=>{if(grid.clientWidth)host.style.setProperty("--cx-view-w",grid.clientWidth+"px")};viewWidth();this.resizeObserver=new ResizeObserver(()=>{viewWidth();this.scheduleRender()});this.resizeObserver.observe(grid)},visibleColumns(){return this.columns.filter((column)=>!column.hidden)},buildHeader(){const active=document.activeElement;const focusedColumn=active&&this.headRow.contains(active)?active.closest(".cx-hcell").getAttribute("data-cx-column"):null;const focusedResize=active&&active.classList.contains("cx-resize");const nextCols=this.visibleColumns();const layoutChanged=!this.cols||this.cols.length!==nextCols.length||nextCols.some((column,i)=>column!==this.cols[i]);this.cols=nextCols;this.columnIndex=this.cols.map((column)=>this.columns.indexOf(column));if(layoutChanged){this.layout=(this.layout||0)+ 1;this.version++}
|
|
262
|
-
this.grid.setAttribute("aria-colcount",String(this.cols.length));this.headRow.textContent="";this.headCells=this.cols.map((column,i)=>{const cell=h("div","cx-hcell cx-kind-" +(column.kind||"text"));cell.setAttribute("role","columnheader");cell.setAttribute("aria-label",column.title);cell.setAttribute("data-cx-column",column.id);cell.setAttribute("aria-colindex",String(i+1));if(column.sortable){const sorted=this.sortState&&this.sortState.column===column.id?this.sortState.direction:null;cell.setAttribute("aria-sort",sorted==="asc"?"ascending":sorted==="desc"?"descending":"none");const button=h("button","cx-sort");button.type="button";setText(button,column.title);button.addEventListener("click",(event)=>this.queryAware?this.querySortHeader(column.id,event):this.sort(column.id,sorted==="asc"?"desc":sorted==="desc"?null:"asc"));cell.appendChild(button)}else{const title=h("span","cx-htext");setText(title,column.title);cell.appendChild(title)}
|
|
283
|
+
this.grid.setAttribute("aria-colcount",String(this.cols.length));this.headRow.textContent="";this.headCells=this.cols.map((column,i)=>{const cell=h("div","cx-hcell cx-kind-" +(column.kind||"text"));cell.setAttribute("role","columnheader");cell.setAttribute("aria-label",column.title);if(column.headerDescription)cell.setAttribute("aria-description",column.headerDescription);cell.title=column.headerDescription??column.title;cell.setAttribute("data-cx-column",column.id);cell.setAttribute("aria-colindex",String(i+1));if(column.sortable){const sorted=this.sortState&&this.sortState.column===column.id?this.sortState.direction:null;cell.setAttribute("aria-sort",sorted==="asc"?"ascending":sorted==="desc"?"descending":"none");const button=h("button","cx-sort");button.type="button";button.title=column.headerDescription??column.title;setText(button,column.title);button.addEventListener("click",(event)=>this.queryAware?this.querySortHeader(column.id,event):this.sort(column.id,sorted==="asc"?"desc":sorted==="desc"?null:"asc"));cell.appendChild(button)}else{const title=h("span","cx-htext");title.title=column.headerDescription??column.title;setText(title,column.title);cell.appendChild(title)}
|
|
263
284
|
const grip=h("span","cx-resize");grip.setAttribute("aria-label",fill(this.labels.resizeColumn,{column:column.title}));grip.tabIndex=0;grip.setAttribute("role","separator");grip.setAttribute("aria-orientation","vertical");grip.setAttribute("aria-valuemin",column.minW);grip.setAttribute("aria-valuemax",column.maxW);grip.addEventListener("keydown",(e)=>{if(!["ArrowLeft","ArrowRight","Home"].includes(e.key))return;e.preventDefault();e.stopPropagation();column.width=columnWidth(column,e.key==="Home"?40:column.width +(e.key==="ArrowLeft"?-1:1)*(e.shiftKey?50:10));this.applyWidths();this.stateChanged()});grip.addEventListener("pointerdown",(e)=>this.startResize(e,column));cell.appendChild(grip);this.headRow.appendChild(cell);return cell});this.applyWidths();if(focusedColumn){const index=this.cols.findIndex((c)=>c.id===focusedColumn);const button=index>=0?this.headCells[index].querySelector(focusedResize?".cx-resize":".cx-sort"):null;if(button){button.focus()}}},rowCount(){return this.rows.length},rowItem(index){return this.rows[index]},rowTop(index){return this.tops[index]},rowAt(y){const tops=this.tops;let lo=0;let hi=this.rows.length-1;while(lo<hi){const mid=(lo+hi+1)>>1;if(tops[mid]<=y){lo=mid}else{hi=mid-1}}
|
|
264
285
|
return Math.max(0,lo)},indexOf(w){const i=w?w._ri:undefined;return i!==undefined&&this.rows[i]===w?i:-1},render(){let measured=false;for(let pass=0;!this.destroyed;pass++){this.renderPass();if(!this.measureDetails())break;measured=true;if(pass===3){this.scheduleRender();break}}
|
|
265
286
|
return measured}});function columnWidth(column,width){return Math.min(column.maxW,Math.max(column.minW,width))}
|
|
@@ -309,13 +330,13 @@ this.paintSlot(slot,node,this.cols[i],this.columnIndex[i],w)}},paintRowState(row
|
|
|
309
330
|
const expander=this.expandable(w)?"cx-exp":"cx-exp cx-leaf";if(slot.expCls!==expander){slot.exp.className=expander;slot.expCls=expander}
|
|
310
331
|
const key=w.h.icon&&this.iconTemplates.has(w.h.icon)?w.h.icon:null;if(slot.iconKey!==key){if(slot.iconEl){slot.iconEl.remove()}
|
|
311
332
|
slot.iconEl=key?this.iconTemplates.get(key).cloneNode(true):null;if(slot.iconEl){slot.cell.insertBefore(slot.iconEl,slot.content)}
|
|
312
|
-
slot.iconKey=key}},cellTip(event){const cell=event.target.closest?.(".cx-cell"),row=cell?.parentNode._kind==="node"&&cell.parentNode._w;const column=row&&!row.status&&this.cols[[...cell.parentNode.children].indexOf(cell)],tip=column?.tooltip;const source=tip==="auto"?column:this.columns.find(item=>item.id===tip);if(!source||cell.title&&!cell._cxTip)return;cell._cxTip=true;cell.title=tip!=="auto"||[cell,...cell.querySelectorAll("*")].some(item=>item.scrollWidth>item.clientWidth)?
|
|
333
|
+
slot.iconKey=key}},cellTip(event){const cell=event.target.closest?.(".cx-cell"),row=cell?.parentNode._kind==="node"&&cell.parentNode._w;const column=row&&!row.status&&this.cols[[...cell.parentNode.children].indexOf(cell)],tip=column?.tooltip;const source=tip==="auto"?column:this.columns.find(item=>item.id===tip);if(!source||cell.title&&!cell._cxTip)return;cell._cxTip=true;cell.title=tip!=="auto"||[cell,...cell.querySelectorAll("*")].some(item=>item.scrollWidth>item.clientWidth||item.scrollHeight>item.clientHeight)?
|
|
313
334
|
cellText(this.cellOf(row.h,source,this.columns.indexOf(source)),source,this.fmt):""},paintSlot(slot,node,column,index,w){const value=this.cellOf(node,column,index);if(slot.cell._cxTip){slot.cell._cxTip=false;slot.cell.removeAttribute("title");slot.title=null}
|
|
314
335
|
const hosted=column.render?this.paintHostSlot(slot,node,column,index,w):null;if(hosted==="host"){return}
|
|
315
336
|
const decorated=hosted==="decorated";const text=cellText(value,column,this.fmt);if(slot.text.data!==text){slot.text.data=text}
|
|
316
|
-
const object=isCellObject(value);const tone=
|
|
337
|
+
const object=isCellObject(value);const rule=columnNumericTone(column,cellValue(value));const tone=toneOf(columnValueTone(column,value)||(object?value.tone:null));const cls=slot.base+tone.cls;if(slot.cls!==cls){if(decorated){if(tone.cls)slot.cell.className +=tone.cls}else{slot.cell.className=cls}
|
|
317
338
|
slot.cls=cls}
|
|
318
|
-
toneColors(slot.cell,tone);const title=object&&value.title?value.title:decorated?null:otherZone(value,column,this.fmt);if(slot.title!==title){if(title){slot.cell.title=title}else{slot.cell.removeAttribute("title")}
|
|
339
|
+
toneColors(slot.cell,tone);const title=object&&value.title?value.title:decorated?null:rule?.label||otherZone(value,column,this.fmt);setAttr(slot.cell,"aria-description",rule?.label||null);if(slot.title!==title){if(title){slot.cell.title=title}else{slot.cell.removeAttribute("title")}
|
|
319
340
|
slot.title=title}
|
|
320
341
|
this.paintBadges(slot,(index===0&&node.badges)||null,object&&value.badges?value.badges:null)},paintBadges(slot,first,second){const count=(first?first.length:0)+(second?second.length:0);for(let k=0;k<count;k++){const badge=first&&k<first.length?first[k]:second[k -(first?first.length:0)];let span=slot.badges[k];if(!span){span=slot.content.appendChild(h("span"));span._text=span.appendChild(document.createTextNode(""));slot.badges.push(span)}
|
|
321
342
|
const tone=toneOf(badge.tone||"neutral");if(span._cls!==tone.cls){applyTone(span,"cx-badge",tone);span._cls=tone.cls}
|
|
@@ -504,7 +525,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
|
|
|
504
525
|
active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
|
|
505
526
|
close()}else{return}
|
|
506
527
|
e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
|
|
507
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["
|
|
528
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"record-panel":["94adeb844689e329","canopyx-record-panel.d0d71d38743e3476.js","canopyx-record-panel.66edd824ab6111c1.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
508
529
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
509
530
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
510
531
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -514,7 +535,7 @@ const load=(element,attribute,file,kind)=>new Promise((resolve,reject)=>{const u
|
|
|
514
535
|
.catch(error=>{part.styleReady=null;throw error}));const code=PART_CODE.get(part.name)?.version===part.version||(part.scriptReady||=load(script,"src",hashed?scriptFile:"canopyx-"+part.name+".js","script")
|
|
515
536
|
.finally(()=>script.remove()).catch(error=>{part.scriptReady=null;throw error}));await Promise.all([style,code])}}
|
|
516
537
|
const code=PART_CODE.get(part.name);if(code?.version!==part.version)throw new Error("CanopyX: "+part.label+" and runtime must come from the same build.");for(const name of code.requires||[])await loadPart(part.parts[name]);code.install(part.context())}).catch(error=>{part.ready=null;throw error})}
|
|
517
|
-
const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};const TREE_TOOLS=definePart(TreeGrid,"tree-tools","tree tools",()=>({TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,exportTimeout,exportFormatsOf:EXPORT_IMPL.formatsOf,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField}));const SEARCH_IMPL={},SEARCH_PART=definePart(TreeGrid,"search","sidecar search",()=>({SEARCH_IMPL,checkDocument,badIndex,isCount,isIdentifier,recentCache,packBytes,shardKey,foldText,trimSeparators,rankHits,validateSearchHit,PACK_CACHE,PACK_CACHE_BYTES,SHARD_CACHE,ENTRY_CACHE,ENTRY_BATCH,SEARCH_CANDIDATES}));async function requirePart(name){await this.toolsReady;const part=Object.hasOwn(this.parts,name)?this.parts[name]:null;if(!part)throw new Error("CanopyX: unknown part '"+name+"'.");return loadPart(part)}
|
|
538
|
+
const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};const TREE_TOOLS=definePart(TreeGrid,"tree-tools","tree tools",()=>({TreeGrid,h,setText,fill,numberFormat,watchFlyout,columnWidth,prepareWidth,cellText,cellValue,isCellObject,foldText,formatting,sortKey,compareKeys,EXPORT_FORMATS,exportFormat,exportTimeout,exportFormatsOf:EXPORT_IMPL.formatsOf,INDENT,MAX_PROTOCOL_INTEGER,hostControl,detailCell,HostCellContext,disposeHostSlot,loadPart,definePart,pluginItems,applyTone,toneOf,badgeElement,RECORD_IMPL,svgIcon,gridExportField,columnNumericTone,columnValueTone,overlayTheme}));const SEARCH_IMPL={},SEARCH_PART=definePart(TreeGrid,"search","sidecar search",()=>({SEARCH_IMPL,checkDocument,badIndex,isCount,isIdentifier,recentCache,packBytes,shardKey,foldText,trimSeparators,rankHits,validateSearchHit,PACK_CACHE,PACK_CACHE_BYTES,SHARD_CACHE,ENTRY_CACHE,ENTRY_BATCH,SEARCH_CANDIDATES}));async function requirePart(name){await this.toolsReady;const part=Object.hasOwn(this.parts,name)?this.parts[name]:null;if(!part)throw new Error("CanopyX: unknown part '"+name+"'.");return loadPart(part)}
|
|
518
539
|
TreeGrid.prototype.requirePart=requirePart;function readStateColumn(c,seen){requireIdentifier(c&&c.id,"state column ID");if(seen.has(c.id)||!Number.isFinite(c.width)||c.width<40||c.width>MAX_COLUMN_WIDTH||typeof c.hidden!=="boolean")
|
|
519
540
|
throw new Error("CanopyX: invalid state column.");seen.add(c.id);return{id:c.id,width:c.width,hidden:c.hidden}}
|
|
520
541
|
function statePaths(value){if(!Array.isArray(value))throw new Error("CanopyX: state paths must be arrays.");return value.map(path=>{if(!Array.isArray(path)||!path.length)throw new Error("CanopyX: state paths cannot be empty.");return path.map(id=>{requireIdentifier(id,"state path ID");return id})})}
|
|
@@ -528,9 +549,9 @@ catch(error){/* Nodes removed since the snapshot are skipped. */ }
|
|
|
528
549
|
}},applyStatePosition(state,current){if(!state.version)return;const valid=path=>{const w=path&&this.keyMap.get(path[path.length-1]);return w&&JSON.stringify(this.pathOf(w))===JSON.stringify(path)?w:null};this.setSelection(state.selection.map(valid).filter(Boolean).map(w=>w.key));if(this.destroyed||current.signal.aborted)return;const focused=valid(state.focus);if(focused&&this.indexOf(focused)>=0)this.setFocus(focused,false);const anchor=state.anchor&&valid(state.anchor.path);if(anchor)this.restoreScrollAnchor({id:anchor.key,offset:state.anchor.offset})}});const PLUGINS=new Map();function plugin(value){const item=Object.freeze({...value}),fn=handler=>typeof handler==="function";const entry=menu=>action=>action&&typeof action.label==="string"&&
|
|
529
550
|
(fn(action.run)&&action.render===undefined||menu&&fn(action.render)&&action.run===undefined);if(!value||!partName(item.name)||Object.hasOwn(PARTS,item.name)||[item.init,item.destroy].some(hook=>hook!==undefined&&!fn(hook))||
|
|
530
551
|
["requires","views","toolbarItems","menuItems","exportFormats","recordActions"].some(key=>item[key]!==undefined&&!Array.isArray(item[key]))||
|
|
531
|
-
["cellRenderers","columnTypes","editors","events","aggregates","detailRenderers","drawerSections"].some(key=>item[key]!==undefined&&Object(item[key])!==item[key])||
|
|
552
|
+
["cellRenderers","columnTypes","editors","events","aggregates","detailRenderers","drawerSections","filterOperators","sortComparators"].some(key=>item[key]!==undefined&&Object(item[key])!==item[key])||
|
|
532
553
|
!(item.requires||[]).every(partName)||!(item.views||[]).every(kind=>kind==="tree"||kind==="grid")||
|
|
533
|
-
![...Object.values(item.cellRenderers||{}),...Object.values(item.events||{}),...Object.values(item.detailRenderers||{}),...Object.values(item.drawerSections||{})].every(fn)||
|
|
554
|
+
![...Object.values(item.cellRenderers||{}),...Object.values(item.events||{}),...Object.values(item.detailRenderers||{}),...Object.values(item.drawerSections||{}),...Object.values(item.filterOperators||{}),...Object.values(item.sortComparators||{})].every(fn)||
|
|
534
555
|
!(item.toolbarItems||[]).every(entry())||!(item.recordActions||[]).every(entry())||!(item.menuItems||[]).every(entry(true)))
|
|
535
556
|
throw new Error("CanopyX: invalid plugin '"+item.name+"'.");item.exportFormats?.forEach(exportFormat);return item}
|
|
536
557
|
function use(value){const item=plugin(value);if(PLUGINS.has(item.name))throw new Error("CanopyX: plugin '"+item.name+"' is already registered.");PLUGINS.set(item.name,item);const formats=item.exportFormats?.map(registerExportFormat)||[];return()=>{if(PLUGINS.get(item.name)===item){PLUGINS.delete(item.name);formats.forEach(dispose=>dispose())}}}
|
|
@@ -568,14 +589,27 @@ finally{navigation.dispose()}
|
|
|
568
589
|
if(navigation.cancelled())return null;if(this.queryAware)snapshotRevision(doc,this.datasetRevision);checkDocument(doc,"counts");this.applyCounts(Object.assign({},doc,{items:doc.items.filter(item=>{const captured=mine.get(item.id);return captured&&this.keyMap.get(item.id)===captured.w&&captured.w.countRevision===captured.revision})}),true);return doc}});const LINKS=definePart(TreeGrid,"links","deep links",()=>({TreeGrid,navigationScope}));for(const name of["openDeepLink","writeDeepLink"])TreeGrid.prototype[name]=function(...args){return this.view.deepLink?loadPart(LINKS).then(()=>this[name](...args),error=>this.emit("error",{error})):Promise.resolve()};TreeGrid.prototype.readLocation=function(){if(this.destroyed)return Promise.resolve();if(this.initializing){if(this.linkOpening&&this.currentLink()!==this.link){this.linkOpening.abort();this.link=null;// Deferred reopening must not reuse the canceled link if the address changes back.
|
|
569
590
|
}
|
|
570
591
|
this.linkChanged=this.dataLifetime.signal;return this.ready.then(()=>undefined,()=>undefined)}
|
|
571
|
-
return this.openDeepLink()};
|
|
592
|
+
return this.openDeepLink()};function sharedDensity(host){const value=host.closest("[data-hfx-density]")?.getAttribute("data-hfx-density");return value==="compact"||value==="comfortable"?value:null}
|
|
593
|
+
function watchSharedDensity(view){let previous=sharedDensity(view.host);const metrics=()=>{if(previous)view.host.style.setProperty("--cx-compact",previous==="compact"?"1":"0");else view.host.style.removeProperty("--cx-compact")};metrics();const observer=new MutationObserver(()=>{const current=sharedDensity(view.host);if(current===previous||view.destroyed)return;previous=current;metrics();refreshSharedDensity(view)});for(let owner=view.host;owner;owner=owner.parentElement){observer.observe(owner,{attributes:true,attributeFilter:["data-hfx-density"]})}
|
|
594
|
+
view.lifetime.signal.addEventListener("abort",()=>observer.disconnect(),{once:true})}
|
|
595
|
+
function layoutAnchor(view){const rows=view.rowProjection||view,top=view.logicalTop(),count=rows.rowCount();if(!count)return null;const index=rows.rowAt(top),height=(view.autoRows?null:view.rowH)||1;const offset=Math.max(0,top-rows.rowTop(index));return{index,offset,share:Math.max(0,Math.min(1,offset / height)) };
|
|
596
|
+
}
|
|
597
|
+
function layoutRows(view,anchor){const rows=view.rowProjection||view;for(const row of[...view.rowCache.values(),...view.placeholders.values()])row.hpx=view.rowH;if(view.autoRows){for(const[index,height]of view.rowHeights)if(height<view.rowH)view.rowHeights.set(index,view.rowH);view.rowOffsets=null;view.measureNeeded=true;view.render()}
|
|
598
|
+
else{const bounds=view.rowBounds(),count=view.rowProjection?rows.rowCount():Math.max(0,bounds.last-bounds.first+1);view.total=count*view.rowH;view.syncScrollRange(anchor?rows.rowTop(anchor.index)+ anchor.share*view.rowH:0)}
|
|
599
|
+
if(anchor&&view.autoRows){const top=rows.rowTop(anchor.index),height=rows.rowTop(anchor.index+1)- top;view.setLogicalTop(top+Math.min(anchor.offset,Math.max(0,height-1)))}
|
|
600
|
+
view.render()}
|
|
601
|
+
function layoutApplyTree(view){const before=view.rowH,after=densityRowHeight(view,view.density);if(before!==after){const anchor=view.captureScrollAnchor();view.rowH=after;const status=row=>{if(row&&row.hpx===before)row.hpx=after};status(view.root._status);for(const row of view.keyMap.values()){if(!row.h?.detail&&row.hpx===before)row.hpx=after;status(row._status)}
|
|
602
|
+
for(const row of view.rows)if(row.status)status(row);view.retop();if(anchor)view.restoreScrollAnchor(anchor)}
|
|
603
|
+
view.fitKey=null;view.version++;if(view.fitReady)view.applyWidths();view.render()}
|
|
604
|
+
function refreshSharedDensity(view){if(!view.grid)return;if(view.kind==="grid"){view.fitKey=null;view.fitFont=null;if(view.layoutMode==="cards"&&VIEW_MODES.refreshCardDensity)VIEW_MODES.refreshCardDensity(view);else{const anchor=layoutAnchor(view);view.rowH=densityRowHeight(view,view.density);view.version++;layoutRows(view,anchor);view.applyWidths()}}else layoutApplyTree(view);view.host.style.setProperty("--cx-row-h",view.rowH+"px");view.fitHeight?.()}
|
|
605
|
+
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{linkFilteredBy:"Filtered by {source}: {values}",linkRemoveFilter:"Remove the filter from {source}: {values}",linkFiltered:"Filtered by {source}: {count} rows",linkHighlighted:"{count} rows highlighted from {source}",linkHighlightedRows:"{count} rows highlighted",linkCleared:"Linked filters removed"}));const LINK_IMPL={TreeGrid,queryOwn:Symbol("own conditions")},LINK_PART=definePart(TreeGrid,"link","linked views",()=>({LINK_IMPL,h,setText,filterChipContent,fill,numberFormat,cellValue,setAttr,cellMatches}));const LINK_METHODS=["setExternalFilter","clearExternalFilters","setHighlight","clearHighlight","startLinkEvents"];function linkMethods(View){for(const name of LINK_METHODS)(View.prototype[name]=function(...args){return this.destroyed?Promise.resolve(/Highlight/.test(name) ? 0 : name === "startLinkEvents" ? undefined : false) : loadPart(LINK_PART).then(() => this[name](...args));
|
|
572
606
|
}).linkStub=true;View.prototype.getExternalFilters=function(){return(this.linkCommitted||[]).map(item=>JSON.parse(JSON.stringify(item)))};View.prototype.getHighlight=function(){return Array.from(this.linkHighlight||[])};View.prototype.linkStart=function(){if(this.opts.linkEvents===true)return loadPart(LINK_PART).then(()=>this.linkWatch()).catch(error=>{this.emit("error",{error});throw error})}}
|
|
573
607
|
linkMethods(TreeGrid);function linkGridPart(View){(Object.hasOwn(View.prototype,"parts")?View.prototype.parts:View.prototype.parts={}).link=LINK_PART}
|
|
574
608
|
function linkReady(grid,ready){return Promise.all([ready,grid.linkStart()]).then(([result])=>result)}
|
|
575
609
|
function linkApi(grid){const api={};for(const name of LINK_METHODS.concat("getExternalFilters","getHighlight"))api[name]=(...args)=>grid[name](...args);return api}
|
|
576
|
-
const RECORD_IMPL={},RECORD_PART=definePart(TreeGrid,"record-panel","record panel",()=>({RECORD_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,badgeElement,loadSidecar,requireIdentifier,validateGridRows,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField}));function loadRecordPanel(){return loadPart(RECORD_PART)}
|
|
610
|
+
const RECORD_IMPL={},RECORD_PART=definePart(TreeGrid,"record-panel","record panel",()=>({RECORD_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,badgeElement,loadSidecar,requireIdentifier,validateGridRows,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField,columnNumericTone,columnValueTone,validateColumnValues}));function loadRecordPanel(){return loadPart(RECORD_PART)}
|
|
577
611
|
const RECORD_STRUCTURE=["items","fields","records","events","changes","ref"];TreeGrid.prototype.recordNeeded=function(node){return!!this.view.record||!!node&&(!!node.fields||Object.values(node.cells||{}).some(cell=>isCellObject(cell)&&RECORD_STRUCTURE.some(name=>cell[name]!==undefined)))};TreeGrid.prototype.openRecord=function(id,options){return loadRecordPanel().then(()=>RECORD_IMPL.open(this,id,options))};function recordStart(grid){if(grid.view.record?.deepLink)loadRecordPanel().then(()=>RECORD_IMPL.start(grid),error=>grid.emit("error",{error}))}
|
|
578
|
-
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{matchesHighlight:"Highlight matches",matchesCount:"[one]{count} match[other]{count} matches",matchesPosition:"{current} of {count}",matchesNone:"No matches",matchesLoaded:"[one]{count} match in loaded rows[other]{count} matches in loaded rows",matchesPrevious:"Previous match",matchesNext:"Next match",matchesAnnounce:"Match {current} of {count}, {column}",layoutMenu:"Layout",layoutFit:"Fit to width",layoutScroll:"All columns, scroll sideways",layoutCards:"Cards",layoutDensity:"Density",layoutCompact:"Compact",layoutNormal:"Normal",layoutComfortable:"Comfortable",layoutChanged:"Layout: {mode}, {density}",layoutSort:"Sort by"}));const LAYOUT_MODES=["fit","scroll","cards"],LAYOUT_DENSITIES=["compact","default","comfortable"];const DENSITY_STEP={tree:{compact:-
|
|
612
|
+
DEFAULT_LABELS=Object.freeze(Object.assign({},DEFAULT_LABELS,{matchesHighlight:"Highlight matches",matchesCount:"[one]{count} match[other]{count} matches",matchesPosition:"{current} of {count}",matchesNone:"No matches",matchesLoaded:"[one]{count} match in loaded rows[other]{count} matches in loaded rows",matchesPrevious:"Previous match",matchesNext:"Next match",matchesAnnounce:"Match {current} of {count}, {column}",layoutMenu:"Layout",layoutFit:"Fit to width",layoutScroll:"All columns, scroll sideways",layoutCards:"Cards",layoutDensity:"Density",layoutCompact:"Compact",layoutNormal:"Normal",layoutComfortable:"Comfortable",layoutChanged:"Layout: {mode}, {density}",layoutSort:"Sort by"}));const LAYOUT_MODES=["fit","scroll","cards"],LAYOUT_DENSITIES=["compact","default","comfortable"];const DENSITY_STEP={tree:{compact:-8,default:0,comfortable:0},grid:{compact:-8,default:0,comfortable:0}};const VIEW_MODES={};const HIGHLIGHT_KEYS=["enabled","search","filters","matchCase","ignoreAccents","minLength","filterTones"];function readSearchHighlight(value,columns){if(value===undefined||value===false)return null;const options=value===true?{}:value,tone=name=>typeof name==="string"&&/^[a-z][a-z0-9-]{0,31}$/.test(name) && !name.endsWith("-bg");
|
|
579
613
|
if(!options||typeof options!=="object"||Array.isArray(options)||Object.keys(options).some(key=>!HIGHLIGHT_KEYS.includes(key))||
|
|
580
614
|
HIGHLIGHT_KEYS.slice(0,5).some(key=>options[key]!==undefined&&typeof options[key]!=="boolean")||
|
|
581
615
|
options.minLength!==undefined&&(!Number.isInteger(options.minLength)||options.minLength<1||options.minLength>32)||
|
|
@@ -591,12 +625,12 @@ function readModeState(view,state){const result={};if(state.layout!==undefined){
|
|
|
591
625
|
throw new Error("CanopyX: invalid saved layout.");if(options)result.layout={mode:options.modes.includes(layout.mode)?layout.mode:options.mode,density:layout.density}}
|
|
592
626
|
if(state.highlight!==undefined){if(typeof state.highlight!=="boolean")throw new Error("CanopyX: invalid saved highlight choice.");if(view.highlightOptions)result.highlight=state.highlight}
|
|
593
627
|
return result}
|
|
594
|
-
function densityRowHeight(view,density){const steps=DENSITY_STEP[view.kind];return Math.max(20,Math.min(64,view.baseRowH+steps[density]- steps[view.declaredDensity]))}
|
|
595
|
-
const VIEW_MODE_METHODS={prepareViewModes(){const view=this.view,columns=this.columns||view.columns;this.highlightOptions=readSearchHighlight(view.searchHighlight,columns);this.declaredDensity=this.kind==="grid"?view.density||"default":"default";this.layoutOptions=readLayout(view.layout,this.kind,this.declaredDensity);this.baseRowH=this.rowH;this.adoptModes({layout:this.layoutOptions||{mode:"fit",density:this.declaredDensity},highlight:!!this.highlightOptions?.enabled})},adoptModes(choice){if(choice.layout){this.layoutMode=choice.layout.mode;this.density=choice.layout.density}
|
|
628
|
+
function densityRowHeight(view,density){const shared=sharedDensity(view.host);if(shared)return shared==="compact"?32:40;const steps=DENSITY_STEP[view.kind];return Math.max(20,Math.min(64,view.baseRowH+steps[density]- steps[view.declaredDensity]))}
|
|
629
|
+
const VIEW_MODE_METHODS={prepareViewModes(){const view=this.view,columns=this.columns||view.columns;this.highlightOptions=readSearchHighlight(view.searchHighlight,columns);this.declaredDensity=this.kind==="grid"?view.density||"default":"default";this.layoutOptions=readLayout(view.layout,this.kind,this.declaredDensity);this.baseRowH=this.rowH;this.adoptModes({layout:this.layoutOptions||{mode:"fit",density:this.declaredDensity},highlight:!!this.highlightOptions?.enabled});watchSharedDensity(this)},adoptModes(choice){if(choice.layout){this.layoutMode=choice.layout.mode;this.density=choice.layout.density}
|
|
596
630
|
if(choice.highlight!==undefined)this.highlightOn=choice.highlight;this.rowH=densityRowHeight(this,this.density);if(this.layoutMode==="fit")this.host.removeAttribute("data-cx-layout");else this.host.setAttribute("data-cx-layout",this.layoutMode)},modeState(state){if(this.layoutOptions)state.layout={mode:this.layoutMode,density:this.density};if(this.highlightOptions)state.highlight=!!this.highlightOn;return state},applyModeState(state){if(state.layout&&(state.layout.mode!==this.layoutMode||state.layout.density!==this.density))
|
|
597
631
|
this.setLayout(state.layout).catch(error=>this.emit("error",{error}));if(state.highlight!==undefined&&state.highlight!==!!this.highlightOn)
|
|
598
632
|
this.setSearchHighlight(state.highlight).catch(error=>this.emit("error",{error}))},startViewModes(){const parts=[this.highlightOptions&&"highlight",this.layoutOptions&&"layouts"].filter(Boolean);return Promise.all(parts.map(name=>this.requirePart(name).then(()=>this.destroyed||VIEW_MODES[name+"Start"](this))
|
|
599
|
-
.catch(error=>this.emit("error",{error}))))},getLayout(){return Object.freeze({mode:this.layoutMode,density:this.density,modes:this.layoutOptions?this.layoutOptions.modes:Object.freeze(["fit"])})},setLayout(change){if(!this.layoutOptions)return Promise.reject(new Error("CanopyX: this view declares no layout modes."));return this.requirePart("layouts").then(()=>VIEW_MODES.setLayout(this,change))},getMatches(){return VIEW_MODES.matches?VIEW_MODES.matches(this):Object.freeze({enabled:!!this.highlightOn,total:0,current:0,complete:true})},setSearchHighlight(enabled){if(typeof enabled!=="boolean")return Promise.reject(new Error("CanopyX: the highlight switch is a boolean."));if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.setHighlight(this,enabled))},nextMatch(options){return this.stepMatch(1,options)},previousMatch(options){return this.stepMatch(-1,options)},stepMatch(direction,options){if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.step(this,direction,options?.focus!==false))}};Object.assign(TreeGrid.prototype,VIEW_MODE_METHODS);const viewModeContext=()=>({VIEW_MODES,TreeGrid,h,setText,fill,numberFormat,foldText,cellText,cellValue,isCellObject,setAttr,toneOf,watchFlyout,densityRowHeight,MAX_PROTOCOL_INTEGER,LAYOUT_DENSITIES,plural,svgIcon});definePart(TreeGrid,"highlight","search highlighting",viewModeContext);definePart(TreeGrid,"layouts","layout modes",viewModeContext);const MODES_TOOLBAR=TreeGrid.prototype.buildToolbar;TreeGrid.prototype.buildToolbar=function(){MODES_TOOLBAR.call(this);if(this.highlightOptions||this.layoutOptions)this.modesReady=Promise.resolve(this.toolsReady).then(()=>this.destroyed||this.startViewModes());this.lifetime.signal.addEventListener("abort",()=>this.host.removeAttribute("data-cx-layout"),{once:true})};Object.assign(TreeGrid.prototype,{destroy(){if(this.destroyed)return;this.destroyed=true;for(const row of[...this.rendered.values(),...this.pool])disposeRowHostCells(row);this.lifetime.abort();this.dataLifetime.abort();if(this.queryController)this.queryController.abort();if(this.restoreController)this.restoreController.abort();if(this.cancelResize)this.cancelResize();clearTimeout(this.saveTimer);clearTimeout(this.layoutTimer);if(this.cancelSearch)this.cancelSearch();if(this.disposeSearchFlyout)this.disposeSearchFlyout();cancelAnimationFrame(this.rafId);this.resizeObserver.disconnect();if(this.detailObserver)this.detailObserver.disconnect();this.grid.removeEventListener("scroll",this.onScroll);this.grid.removeEventListener("wheel",this.onScaledWheel);this.grid.removeEventListener("touchstart",this.onScaledTouchStart);this.grid.removeEventListener("touchmove",this.onScaledTouchMove);this.grid.removeEventListener("touchend",this.onScaledTouchEnd);this.grid.removeEventListener("touchcancel",this.onScaledTouchEnd);global.removeEventListener("beforeprint",this.onPrint);global.removeEventListener("hashchange",this.onHash);global.removeEventListener("popstate",this.onHash);if(this.linkOpening)this.linkOpening.abort();[this.toolbar,this.grid,this.live,this.outline].forEach(element=>element.remove());this.host.classList.remove("cx-pin-tree");this.host.removeAttribute("data-cx-ready");this.host.removeAttribute("data-canopyx-mounted");this.keyMap.clear();this.selected.clear();this.rendered.clear();this.pool.length=0;if(this.inactiveCache)this.inactiveCache.clear();if(this.inlineRetained)this.inlineRetained.clear();this.rows=[];this.tops=[0];this.total=0;this.root.children=null;this.root.inlineCache=null;this.root.inlineOrder=null;this.focused=null;this.anchor=null;this.source=null;this.touchScroll=null;this.opts={};for(const column of this.columns)column.render=null;this.filter=null;this.declaredFilter=null;this.pendingRestorationToggles=null;this.scrolledCell=null;this.focusHandoff=null;this.cancelResize=null;this.cancelSearch=null;this.disposeSearchFlyout=null;this.canvas.replaceChildren();this.outline.replaceChildren()}});function checkIntentPath(path){if(!Array.isArray(path)||!path.length)throw new Error("CanopyX: checking needs a complete node-ID path.");const seen=new Set();return path.map(id=>{requireIdentifier(id,"checking path ID");if(seen.has(id))throw new Error("CanopyX: a checking path cannot repeat an ID.");seen.add(id);return id})}
|
|
633
|
+
.catch(error=>this.emit("error",{error}))))},getLayout(){return Object.freeze({mode:this.layoutMode,density:this.density,modes:this.layoutOptions?this.layoutOptions.modes:Object.freeze(["fit"])})},setLayout(change){if(!this.layoutOptions)return Promise.reject(new Error("CanopyX: this view declares no layout modes."));return this.requirePart("layouts").then(()=>VIEW_MODES.setLayout(this,change))},getMatches(){return VIEW_MODES.matches?VIEW_MODES.matches(this):Object.freeze({enabled:!!this.highlightOn,total:0,current:0,complete:true})},setSearchHighlight(enabled){if(typeof enabled!=="boolean")return Promise.reject(new Error("CanopyX: the highlight switch is a boolean."));if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.setHighlight(this,enabled))},nextMatch(options){return this.stepMatch(1,options)},previousMatch(options){return this.stepMatch(-1,options)},stepMatch(direction,options){if(!this.highlightOptions)return Promise.reject(new Error("CanopyX: this view declares no search highlighting."));return this.requirePart("highlight").then(()=>VIEW_MODES.step(this,direction,options?.focus!==false))}};Object.assign(TreeGrid.prototype,VIEW_MODE_METHODS);const viewModeContext=()=>({VIEW_MODES,TreeGrid,h,setText,fill,numberFormat,foldText,cellText,cellValue,isCellObject,setAttr,toneOf,toneVariable,watchFlyout,densityRowHeight,layoutAnchor,layoutRows,layoutApplyTree,MAX_PROTOCOL_INTEGER,LAYOUT_DENSITIES,plural,svgIcon});definePart(TreeGrid,"highlight","search highlighting",viewModeContext);definePart(TreeGrid,"layouts","layout modes",viewModeContext);const MODES_TOOLBAR=TreeGrid.prototype.buildToolbar;TreeGrid.prototype.buildToolbar=function(){MODES_TOOLBAR.call(this);if(this.highlightOptions||this.layoutOptions)this.modesReady=Promise.resolve(this.toolsReady).then(()=>this.destroyed||this.startViewModes());this.lifetime.signal.addEventListener("abort",()=>this.host.removeAttribute("data-cx-layout"),{once:true})};Object.assign(TreeGrid.prototype,{destroy(){if(this.destroyed)return;this.destroyed=true;for(const row of[...this.rendered.values(),...this.pool])disposeRowHostCells(row);this.lifetime.abort();this.dataLifetime.abort();if(this.queryController)this.queryController.abort();if(this.restoreController)this.restoreController.abort();if(this.cancelResize)this.cancelResize();clearTimeout(this.saveTimer);clearTimeout(this.layoutTimer);if(this.cancelSearch)this.cancelSearch();if(this.disposeSearchFlyout)this.disposeSearchFlyout();cancelAnimationFrame(this.rafId);this.resizeObserver.disconnect();if(this.detailObserver)this.detailObserver.disconnect();this.grid.removeEventListener("scroll",this.onScroll);this.grid.removeEventListener("wheel",this.onScaledWheel);this.grid.removeEventListener("touchstart",this.onScaledTouchStart);this.grid.removeEventListener("touchmove",this.onScaledTouchMove);this.grid.removeEventListener("touchend",this.onScaledTouchEnd);this.grid.removeEventListener("touchcancel",this.onScaledTouchEnd);global.removeEventListener("beforeprint",this.onPrint);global.removeEventListener("hashchange",this.onHash);global.removeEventListener("popstate",this.onHash);if(this.linkOpening)this.linkOpening.abort();[this.toolbar,this.grid,this.live,this.outline].forEach(element=>element.remove());this.host.classList.remove("cx-pin-tree");this.host.removeAttribute("data-cx-ready");this.host.removeAttribute("data-canopyx-mounted");this.keyMap.clear();this.selected.clear();this.rendered.clear();this.pool.length=0;if(this.inactiveCache)this.inactiveCache.clear();if(this.inlineRetained)this.inlineRetained.clear();this.rows=[];this.tops=[0];this.total=0;this.root.children=null;this.root.inlineCache=null;this.root.inlineOrder=null;this.focused=null;this.anchor=null;this.source=null;this.touchScroll=null;this.opts={};for(const column of this.columns)column.render=null;this.filter=null;this.declaredFilter=null;this.pendingRestorationToggles=null;this.scrolledCell=null;this.focusHandoff=null;this.cancelResize=null;this.cancelSearch=null;this.disposeSearchFlyout=null;this.canvas.replaceChildren();this.outline.replaceChildren()}});function checkIntentPath(path){if(!Array.isArray(path)||!path.length)throw new Error("CanopyX: checking needs a complete node-ID path.");const seen=new Set();return path.map(id=>{requireIdentifier(id,"checking path ID");if(seen.has(id))throw new Error("CanopyX: a checking path cannot repeat an ID.");seen.add(id);return id})}
|
|
600
634
|
function checkBranch(){return{value:null,mask:0,children:new Map()}}
|
|
601
635
|
class CheckIntents{constructor(items,mode){if(!Array.isArray(items))throw new Error("CanopyX: checkIntents must be an array.");this.mode=mode;this.root=checkBranch();for(const item of items){if(!item||typeof item.checked!=="boolean")throw new Error("CanopyX: a checking intent needs a boolean checked value.");const path=checkIntentPath(item.path);let branch=this.root;for(const id of path){if(!branch.children.has(id))branch.children.set(id,checkBranch());branch=branch.children.get(id)}
|
|
602
636
|
if(branch.value!==null)throw new Error("CanopyX: a checking path cannot have duplicate intents.");branch.value=item.checked}
|
|
@@ -507,6 +507,11 @@ const labels = Object.freeze({
|
|
|
507
507
|
calendarOccurrenceTitle: "Wiederkehrenden Termin ändern",
|
|
508
508
|
calendarOccurrenceReadOnly: "Dieser Teil der Serie kann nicht gespeichert werden, weil einige Werte schreibgeschützt sind.",
|
|
509
509
|
calendarThisEvent: "Nur dieser Termin",
|
|
510
|
+
calendarEditOccurrence: "Dieses Vorkommen bearbeiten",
|
|
511
|
+
calendarRemoveOccurrence: "Dieses Vorkommen entfernen",
|
|
512
|
+
calendarOccurrenceScope: "Nur {date} ändert sich; andere Termine von {title} bleiben unverändert.",
|
|
513
|
+
calendarSharedResources: "{count} {resources}",
|
|
514
|
+
calendarResourceWindow: "{resources} {start}–{end} von {total}",
|
|
510
515
|
calendarThisAndFollowing: "Dieser und alle folgenden Termine",
|
|
511
516
|
calendarAllEvents: "Alle Termine",
|
|
512
517
|
calendarSources: "Kalender",
|
|
@@ -507,6 +507,11 @@ const labels = Object.freeze({
|
|
|
507
507
|
calendarOccurrenceTitle: "Cambiar un evento periódico",
|
|
508
508
|
calendarOccurrenceReadOnly: "No se puede guardar esta parte de la serie porque algunos valores son de solo lectura.",
|
|
509
509
|
calendarThisEvent: "Este evento",
|
|
510
|
+
calendarEditOccurrence: "Editar esta ocurrencia",
|
|
511
|
+
calendarRemoveOccurrence: "Eliminar esta ocurrencia",
|
|
512
|
+
calendarOccurrenceScope: "Solo cambia {date}; las otras fechas de {title} se mantienen.",
|
|
513
|
+
calendarSharedResources: "{count} {resources}",
|
|
514
|
+
calendarResourceWindow: "{resources} {start}–{end} de {total}",
|
|
510
515
|
calendarThisAndFollowing: "Este evento y los siguientes",
|
|
511
516
|
calendarAllEvents: "Todos los eventos",
|
|
512
517
|
calendarSources: "Calendarios",
|
|
@@ -507,6 +507,11 @@ const labels = Object.freeze({
|
|
|
507
507
|
calendarOccurrenceTitle: "Modifier un événement récurrent",
|
|
508
508
|
calendarOccurrenceReadOnly: "Cette partie de la série ne peut pas être enregistrée, car certaines valeurs sont en lecture seule.",
|
|
509
509
|
calendarThisEvent: "Cet événement",
|
|
510
|
+
calendarEditOccurrence: "Modifier cette occurrence",
|
|
511
|
+
calendarRemoveOccurrence: "Supprimer cette occurrence",
|
|
512
|
+
calendarOccurrenceScope: "Seul le {date} change ; les autres dates de {title} restent inchangées.",
|
|
513
|
+
calendarSharedResources: "{count} {resources}",
|
|
514
|
+
calendarResourceWindow: "{resources} {start}–{end} sur {total}",
|
|
510
515
|
calendarThisAndFollowing: "Cet événement et les suivants",
|
|
511
516
|
calendarAllEvents: "Tous les événements",
|
|
512
517
|
calendarSources: "Calendriers",
|
|
@@ -507,6 +507,11 @@ const labels = Object.freeze({
|
|
|
507
507
|
calendarOccurrenceTitle: "Modifica un evento ricorrente",
|
|
508
508
|
calendarOccurrenceReadOnly: "Questa parte della serie non può essere salvata perché alcuni valori sono di sola lettura.",
|
|
509
509
|
calendarThisEvent: "Questo evento",
|
|
510
|
+
calendarEditOccurrence: "Modifica questa occorrenza",
|
|
511
|
+
calendarRemoveOccurrence: "Rimuovi questa occorrenza",
|
|
512
|
+
calendarOccurrenceScope: "Cambia solo {date}; le altre date di {title} restano invariate.",
|
|
513
|
+
calendarSharedResources: "{count} {resources}",
|
|
514
|
+
calendarResourceWindow: "{resources} {start}–{end} di {total}",
|
|
510
515
|
calendarThisAndFollowing: "Questo evento e i successivi",
|
|
511
516
|
calendarAllEvents: "Tutti gli eventi",
|
|
512
517
|
calendarSources: "Calendari",
|
|
@@ -507,6 +507,11 @@ const labels = Object.freeze({
|
|
|
507
507
|
calendarOccurrenceTitle: "Zmień wydarzenie cykliczne",
|
|
508
508
|
calendarOccurrenceReadOnly: "Nie można zapisać tej części serii, ponieważ niektóre wartości są tylko do odczytu.",
|
|
509
509
|
calendarThisEvent: "To wydarzenie",
|
|
510
|
+
calendarEditOccurrence: "Edytuj to wystąpienie",
|
|
511
|
+
calendarRemoveOccurrence: "Usuń to wystąpienie",
|
|
512
|
+
calendarOccurrenceScope: "Zmienia się tylko {date}; pozostałe daty wydarzenia {title} pozostają bez zmian.",
|
|
513
|
+
calendarSharedResources: "{count} {resources}",
|
|
514
|
+
calendarResourceWindow: "{resources} {start}–{end} z {total}",
|
|
510
515
|
calendarThisAndFollowing: "To i następne wydarzenia",
|
|
511
516
|
calendarAllEvents: "Wszystkie wydarzenia",
|
|
512
517
|
calendarSources: "Kalendarze",
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
/* The Layout menu: radio groups for the mode and the density. */
|
|
2
2
|
.cx-chrome .cx-grid-layout > .cx-grid-panel{display:block;width:var(--cx-size-244px);padding:var(--cx-size-6px) var(--cx-size-8px);}
|
|
3
3
|
.cx-layout-group{padding:var(--cx-size-4px) 0;}
|
|
4
|
-
.cx-layout-group + .cx-layout-group{border-top:var(--cx-size-1px) solid var(--
|
|
5
|
-
.cx-layout-title{padding:0 var(--cx-size-6px) var(--cx-size-4px);font-size:var(--cx-size-12px);font-weight:700;color:var(--
|
|
6
|
-
.cx-layout-choice{display:flex;align-items:center;gap:var(--cx-size-8px);min-height:var(--cx-size-32px);padding:0 var(--cx-size-6px);border-radius:var(--
|
|
7
|
-
.cx-layout-choice:hover{background:var(--
|
|
8
|
-
.cx-layout-choice input{flex:none;width:var(--cx-size-16px);height:var(--cx-size-16px);margin:0;accent-color:var(--
|
|
9
|
-
.cx-layout-choice:has(input:focus-visible){outline:var(--
|
|
4
|
+
.cx-layout-group + .cx-layout-group{border-top:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));margin-top:var(--cx-size-4px);padding-top:var(--cx-size-8px);}
|
|
5
|
+
.cx-layout-title{padding:0 var(--cx-size-6px) var(--cx-size-4px);font-size:var(--cx-size-12px);font-weight:700;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
6
|
+
.cx-layout-choice{display:flex;align-items:center;gap:var(--cx-size-8px);min-height:var(--cx-size-32px);padding:0 var(--cx-size-6px);border-radius:var(--hfx-radius-sm,4px);cursor:pointer;}
|
|
7
|
+
.cx-layout-choice:hover{background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));}
|
|
8
|
+
.cx-layout-choice input{flex:none;width:var(--cx-size-16px);height:var(--cx-size-16px);margin:0;accent-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
|
|
9
|
+
.cx-layout-choice:has(input:focus-visible){outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:calc(-1 * var(--cx-size-2px));}
|
|
10
10
|
.cx-chrome.cx-phone .cx-grid-layout > summary{width:var(--cx-size-44px);font-size:0;padding:0;}
|
|
11
11
|
.cx-chrome.cx-phone .cx-layout-choice{min-height:var(--cx-size-44px);}
|
|
12
|
-
.cx-layouts:not(.cx-data-grid)[data-cx-density="compact"]{
|
|
13
|
-
.cx-layouts:not(.cx-data-grid)[data-cx-density="comfortable"]{
|
|
12
|
+
.cx-layouts:not(.cx-data-grid)[data-cx-density="compact"]{}
|
|
13
|
+
.cx-layouts:not(.cx-data-grid)[data-cx-density="comfortable"]{}
|
|
14
14
|
.cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-hcell:first-child,.cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-row > .cx-tree{position:sticky;left:0;z-index:1;}
|
|
15
|
-
.cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-hcell:first-child{z-index:2;background:var(--
|
|
15
|
+
.cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-hcell:first-child{z-index:2;background:var(--hfx-table-header-background,var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317)));}
|
|
16
16
|
.cx-layouts:not(.cx-data-grid)[data-cx-layout="scroll"] .cx-row > .cx-tree{background:inherit;}
|
|
17
17
|
.cx-data-grid[data-cx-layout="cards"] .cx-grid{overflow-x:hidden;}
|
|
18
18
|
.cx-data-grid[data-cx-layout="cards"] :is(.cx-canvas,.cx-head){width:100% !important;min-width:0;}
|
|
19
19
|
.cx-data-grid[data-cx-layout="cards"] .cx-head{display:none;}
|
|
20
20
|
.cx-chrome .cx-grid-sort > .cx-grid-panel{display:block;width:var(--cx-size-280px);padding:var(--cx-size-6px) var(--cx-size-8px);}
|
|
21
21
|
.cx-sort-list{display:flex;flex-direction:column;gap:var(--cx-size-2px);}
|
|
22
|
-
.cx-grid-sort .cx-grid-selection-controls{padding:var(--cx-size-4px) var(--cx-size-6px) var(--cx-size-8px);margin-bottom:var(--cx-size-6px);border-bottom:var(--cx-size-1px) solid var(--
|
|
22
|
+
.cx-grid-sort .cx-grid-selection-controls{padding:var(--cx-size-4px) var(--cx-size-6px) var(--cx-size-8px);margin-bottom:var(--cx-size-6px);border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
|
|
23
23
|
.cx-sort-choice{display:flex;align-items:center;gap:var(--cx-size-4px);min-height:var(--cx-size-32px);}
|
|
24
|
-
.cx-chrome .cx-sort-choice .cx-sort-column{flex:1;min-width:0;justify-content:start;border:0;border-radius:var(--
|
|
25
|
-
.cx-chrome .cx-sort-choice span.cx-sort-column{padding:0 var(--cx-size-11px);color:var(--
|
|
26
|
-
.cx-chrome .cx-sort-choice .cx-sort-column[aria-pressed="true"]{color:var(--
|
|
27
|
-
.cx-chrome .cx-sort-choice .cx-sort-menu{flex:none;border:0;background:transparent;color:var(--
|
|
24
|
+
.cx-chrome .cx-sort-choice .cx-sort-column{flex:1;min-width:0;justify-content:start;border:0;border-radius:var(--hfx-radius-sm,4px);background:transparent;overflow:hidden;text-overflow:ellipsis;}
|
|
25
|
+
.cx-chrome .cx-sort-choice span.cx-sort-column{padding:0 var(--cx-size-11px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
26
|
+
.cx-chrome .cx-sort-choice .cx-sort-column[aria-pressed="true"]{color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));font-weight:600;}
|
|
27
|
+
.cx-chrome .cx-sort-choice .cx-sort-menu{flex:none;border:0;background:transparent;color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
|
|
28
28
|
.cx-chrome.cx-phone .cx-grid-sort > summary{width:var(--cx-size-44px);font-size:0;padding:0;}
|
|
29
29
|
.cx-chrome.cx-phone .cx-sort-choice{min-height:var(--cx-size-44px);}
|
|
30
30
|
.cx-chrome.cx-phone .cx-sort-choice .cx-button{min-height:var(--cx-size-44px);}
|
|
@@ -37,12 +37,12 @@ grid-auto-flow:row dense;align-content:start;column-gap:var(--cx-size-16px);row-
|
|
|
37
37
|
width:auto !important;height:auto;min-width:0;padding:0;position:relative !important;left:auto !important;right:auto !important;box-shadow:none;background:transparent;
|
|
38
38
|
flex-direction:column;align-items:flex-start;justify-content:center;gap:var(--cx-size-1px);text-align:left;
|
|
39
39
|
}
|
|
40
|
-
.cx-data-grid[data-cx-layout="cards"] .cx-row:not(.cx-status):not(.cx-grid-group) > .cx-cell:first-child{grid-column:1/-1;height:var(--cx-card-title);flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--cx-size-6px);font-weight:600;font-size:calc(var(--
|
|
40
|
+
.cx-data-grid[data-cx-layout="cards"] .cx-row:not(.cx-status):not(.cx-grid-group) > .cx-cell:first-child{grid-column:1/-1;height:var(--cx-card-title);flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--cx-size-6px);font-weight:600;font-size:calc(var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem)) + 1px);}
|
|
41
41
|
.cx-data-grid[data-cx-layout="cards"] .cx-row:not(.cx-status):not(.cx-grid-group) > .cx-cell[data-cx-card="wide"]{grid-column:span var(--cx-card-span,1);}
|
|
42
|
-
.cx-data-grid[data-cx-layout="cards"] .cx-cell[data-cx-label]::before{content:attr(data-cx-label) / "";display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--cx-size-11d5px);font-weight:600;line-height:1.35;color:var(--
|
|
42
|
+
.cx-data-grid[data-cx-layout="cards"] .cx-cell[data-cx-label]::before{content:attr(data-cx-label) / "";display:block;flex:none;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--cx-size-11d5px);font-weight:600;line-height:1.35;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
43
43
|
.cx-data-grid[data-cx-layout="cards"] .cx-cell > :is(.cx-text,.cx-presenter-text){max-width:100%;}
|
|
44
44
|
.cx-data-grid[data-cx-layout="cards"] .cx-row:not(.cx-status):not(.cx-grid-group) > .cx-cell:first-child::before{content:none;}
|
|
45
|
-
.cx-data-grid[data-cx-layout="cards"] .cx-row[aria-selected="true"]{box-shadow:inset var(--cx-size-3px) 0 0 var(--
|
|
45
|
+
.cx-data-grid[data-cx-layout="cards"] .cx-row[aria-selected="true"]{box-shadow:inset var(--cx-size-3px) 0 0 var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
|
|
46
46
|
@media (forced-colors:active){
|
|
47
47
|
.cx-data-grid[data-cx-layout="cards"] .cx-row[aria-selected="true"]{forced-color-adjust:none;box-shadow:inset var(--cx-size-3px) 0 0 Highlight;}
|
|
48
48
|
}
|
|
@@ -1,22 +1,14 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
2
|
-
function cardGeometry(view){const metrics=CARD_METRICS[view.density],width=Math.max(0,(view.grid.clientWidth||view.host.clientWidth)- 2*CARD_GUTTER);const fields=(view.cols||[]).slice(1),most=Math.max(1,Math.floor((width+CARD_COLUMN_GAP)/ (CARD_FIELD + CARD_COLUMN_GAP)));
|
|
3
|
-
const slots=fields.reduce((sum,field)=>sum +(cardWide(field)&&most>1?2:1),0)||1;const columns=Math.min(most,Math.ceil(slots / Math.ceil(slots / most))), span = Math.min(2, columns), rows = [];
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"606fcf6dcd00d420",install(context){if(installed.has(context.VIEW_MODES))return;const{VIEW_MODES,TreeGrid,h,setText,fill,numberFormat,foldText,cellText,cellValue,isCellObject,setAttr,toneOf,watchFlyout,densityRowHeight,layoutAnchor,layoutRows,layoutApplyTree,MAX_PROTOCOL_INTEGER,LAYOUT_DENSITIES,plural,svgIcon}=context;const CARD_METRICS={compact:{pad:8,field:36,gap:4,title:24},default:{pad:12,field:40,gap:6,title:26},comfortable:{pad:16,field:44,gap:8,title:28}};const CARD_FIELD=140,CARD_GUTTER=16,CARD_COLUMN_GAP=16,CARD_WIDE=["longText","tags","list"];function cardWide(column){return!!column.wrap||!!column.flex||CARD_WIDE.includes(column.presenter?.kind)}
|
|
2
|
+
function cardGeometry(view){const metrics={...CARD_METRICS[view.density]},width=Math.max(0,(view.grid.clientWidth||view.host.clientWidth)- 2*CARD_GUTTER);const fields=(view.cols||[]).slice(1),most=Math.max(1,Math.floor((width+CARD_COLUMN_GAP)/ (CARD_FIELD + CARD_COLUMN_GAP)));
|
|
3
|
+
const font=parseFloat(getComputedStyle(view.grid).fontSize),clampLines=column=>Math.min(column.maxLines??2,2);if(fields.some(column=>column.wrap))metrics.field=Math.max(metrics.field,Math.ceil(11.5*1.35+1+font*1.4*Math.max(...fields.filter(column=>column.wrap).map(clampLines))));if(view.cols?.[0]?.wrap)metrics.title=Math.max(metrics.title,Math.ceil((font+1)*1.4*clampLines(view.cols[0])));const slots=fields.reduce((sum,field)=>sum +(cardWide(field)&&most>1?2:1),0)||1;const columns=Math.min(most,Math.ceil(slots / Math.ceil(slots / most))), span = Math.min(2, columns), rows = [];
|
|
4
4
|
for(const field of fields){const size=cardWide(field)?span:1;for(let row=0,placed=false;!placed;row++){const cells=rows[row]||=new Array(columns).fill(false);for(let at=0;at+size<=columns&&!placed;at++)if(cells.slice(at,at+size).every(used=>!used)){cells.fill(true,at,at+size);placed=true}}}
|
|
5
5
|
const lines=rows.length;return{columns,span,metrics,height:2*metrics.pad+metrics.title +(lines?metrics.gap+lines*metrics.field +(lines-1)*metrics.gap:0)+ 1}}
|
|
6
6
|
function cardStyle(view,geometry){const style=view.host.style,{metrics}=geometry;style.setProperty("--cx-card-cols",String(geometry.columns));style.setProperty("--cx-card-span",String(geometry.span));style.setProperty("--cx-card-pad",metrics.pad+"px");style.setProperty("--cx-card-field",metrics.field+"px");style.setProperty("--cx-card-gap",metrics.gap+"px");style.setProperty("--cx-card-title",metrics.title+"px")}
|
|
7
|
-
function layoutAnchor(view){const rows=view.rowProjection||view,top=view.logicalTop(),count=rows.rowCount();if(!count)return null;const index=rows.rowAt(top),height=(view.autoRows?null:view.rowH)||1;return{index,share:Math.max(0,Math.min(1,(top-rows.rowTop(index))/ height)) };
|
|
8
|
-
}
|
|
9
|
-
function layoutRows(view,anchor){const rows=view.rowProjection||view;for(const row of[...view.rowCache.values(),...view.placeholders.values()])row.hpx=view.rowH;if(view.autoRows){view.rowOffsets=null;view.rowHeights?.clear();view.measureNeeded=true;view.render()}
|
|
10
|
-
else{const bounds=view.rowBounds(),count=view.rowProjection?rows.rowCount():Math.max(0,bounds.last-bounds.first+1);view.total=count*view.rowH;view.syncScrollRange(anchor?rows.rowTop(anchor.index)+ anchor.share*view.rowH:0)}
|
|
11
|
-
if(anchor&&view.autoRows)view.setLogicalTop(rows.rowTop(anchor.index));view.render()}
|
|
12
7
|
function layoutApplyGrid(view,mode){const anchor=layoutAnchor(view);if(mode==="cards"){if(view.cardAutoRows===undefined){view.cardAutoRows=view.autoRows;view.autoRows=false}}
|
|
13
8
|
else if(view.cardAutoRows!==undefined){view.autoRows=view.cardAutoRows;view.cardAutoRows=undefined;view.rowOffsets=null}
|
|
14
9
|
view.fitFont=null;view.fitKey=null;view.layout=(view.layout||0)+ 1;view.version++;view.layoutApplying=true;try{view.buildHeader();view.syncColumnControls()}finally{view.layoutApplying=false}
|
|
15
10
|
if(mode==="cards"){const geometry=cardGeometry(view);cardStyle(view,geometry);view.rowH=geometry.height}
|
|
16
11
|
else view.rowH=densityRowHeight(view,view.density);layoutRows(view,anchor);view.syncPinnedShadows?.()}
|
|
17
|
-
function layoutApplyTree(view){const before=view.rowH,after=densityRowHeight(view,view.density);if(before!==after){const anchor=view.captureScrollAnchor();view.rowH=after;const status=row=>{if(row&&row.hpx===before)row.hpx=after};status(view.root._status);for(const row of view.keyMap.values()){if(!row.h?.detail&&row.hpx===before)row.hpx=after;status(row._status)}
|
|
18
|
-
for(const row of view.rows)if(row.status)status(row);view.retop();if(anchor)view.restoreScrollAnchor(anchor)}
|
|
19
|
-
view.fitKey=null;view.version++;if(view.fitReady)view.applyWidths();view.render()}
|
|
20
12
|
function layoutApply(view,mode,density){const active=document.activeElement,held=view.canvas.contains(active)?active:null;const cell=held?.closest(".cx-cell"),row=view.focused,column=cell&&view.cols[view.rowCells(cell.parentNode).indexOf(cell)]?.id;view.layoutMode=mode;view.density=density;view.host.setAttribute("data-cx-density",density);if(mode==="fit")view.host.removeAttribute("data-cx-layout");else view.host.setAttribute("data-cx-layout",mode);view.host.style.setProperty("--cx-row-h",densityRowHeight(view,density)+ "px");if(view.kind==="grid")layoutApplyGrid(view,mode);else layoutApplyTree(view);if(held&&row&&view.rendered.get(row)){const at=column?view.cols.findIndex(item=>item.id===column):-1;if(at>=0)view.focusCell(row,at,null);else view.rendered.get(row).focus({preventScroll:true})}}
|
|
21
13
|
const LAYOUT_ICON='<rect x="4" y="4" width="16" height="7" rx="1.5"/><rect x="4" y="13" width="16" height="7" rx="1.5"/>';let layoutSeq=0;function layoutGroup(view,legend,name,choices,current,choose){const group=h("div","cx-layout-group"),title=h("div","cx-layout-title");title.id=name+"-title";group.setAttribute("role","radiogroup");group.setAttribute("aria-labelledby",title.id);setText(title,legend);group.appendChild(title);for(const[value,text]of choices){const label=h("label","cx-layout-choice"),input=h("input");input.type="radio";input.name=name;input.value=value;input.checked=value===current;input.addEventListener("change",()=>{if(input.checked)choose(value)});label.append(input,document.createTextNode(text));group.appendChild(label)}
|
|
22
14
|
return group}
|
|
@@ -24,7 +16,7 @@ function layoutModeText(view,mode){return view.labels[mode==="fit"?"layoutFit":m
|
|
|
24
16
|
function layoutDensityText(view,density){return view.labels[density==="compact"?"layoutCompact":density==="comfortable"?"layoutComfortable":"layoutNormal"]}
|
|
25
17
|
function layoutMenu(view){if(view.tools.layout===false||typeof view.controlPanel!=="function")return;const{details,panel}=view.controlPanel(view.labels.layoutMenu,"cx-grid-layout"),id=view.id+"-layout-" + ++layoutSeq;const icon=details.firstChild.querySelector("svg");if(icon)icon.replaceWith(svgIcon(LAYOUT_ICON));const choose=change=>Promise.resolve().then(()=>VIEW_MODES.setLayout(view,change)).catch(error=>view.emit("error",{error}));const render=()=>{const options=view.layoutOptions;if(panel.firstChild){for(const input of panel.querySelectorAll("input"))input.checked=input.value===view.layoutMode||input.value===view.density;return}
|
|
26
18
|
panel.replaceChildren(...[options.modes.length>1&&layoutGroup(view,view.labels.layoutMenu,id+"-mode",options.modes.map(mode=>[mode,layoutModeText(view,mode)]),view.layoutMode,mode=>choose({mode})),layoutGroup(view,view.labels.layoutDensity,id+"-density",LAYOUT_DENSITIES.map(density=>[density,layoutDensityText(view,density)]),view.density,density=>choose({density}))].filter(Boolean))};render();view.layoutMenu={details,render};const anchor=view.toolbar.querySelector(".cx-grid-views")||view.spacer;if(anchor&&anchor.parentNode===view.toolbar)view.toolbar.insertBefore(details,anchor)}
|
|
27
|
-
VIEW_MODES.layoutsStart=view=>{if(!view.layoutMenu)layoutMenu(view);if(!view.sortMenu)sortMenu(view);if(view.layoutStarted)return;view.layoutStarted=true;view.host.classList.add("cx-layouts");view.lifetime.signal.addEventListener("abort",()=>{view.host.classList.remove("cx-layouts");for(const name of["cols","span","pad","field","gap","title"])view.host.style.removeProperty("--cx-card-"+name)},{once:true});view.host.setAttribute("data-cx-density",view.density);if(view.layoutMode!=="fit"||view.kind==="grid"&&view.density!==view.declaredDensity)layoutApply(view,view.layoutMode,view.density)};VIEW_MODES.setLayout=(view,change)=>{if(!change||typeof change!=="object"||Array.isArray(change)||Object.keys(change).some(key=>!["mode","density"].includes(key))||
|
|
19
|
+
VIEW_MODES.layoutsStart=view=>{if(!view.layoutMenu)layoutMenu(view);if(!view.sortMenu)sortMenu(view);if(view.layoutStarted)return;view.layoutStarted=true;view.host.classList.add("cx-layouts");view.lifetime.signal.addEventListener("abort",()=>{view.host.classList.remove("cx-layouts");for(const name of["cols","span","pad","field","gap","title"])view.host.style.removeProperty("--cx-card-"+name)},{once:true});view.host.setAttribute("data-cx-density",view.density);if(view.layoutMode!=="fit"||view.kind==="grid"&&view.density!==view.declaredDensity)layoutApply(view,view.layoutMode,view.density)};VIEW_MODES.refreshCardDensity=view=>{const anchor=layoutAnchor(view),geometry=cardGeometry(view);cardStyle(view,geometry);view.rowH=geometry.height;view.version++;layoutRows(view,anchor)};VIEW_MODES.setLayout=(view,change)=>{if(!change||typeof change!=="object"||Array.isArray(change)||Object.keys(change).some(key=>!["mode","density"].includes(key))||
|
|
28
20
|
change.mode!==undefined&&!view.layoutOptions.modes.includes(change.mode)||change.density!==undefined&&!LAYOUT_DENSITIES.includes(change.density))
|
|
29
21
|
throw new Error("CanopyX: setLayout takes a mode the view allows and a density.");if(!view.layoutStarted)VIEW_MODES.layoutsStart(view);const mode=change.mode??view.layoutMode,density=change.density??view.density;if(mode!==view.layoutMode||density!==view.density){layoutApply(view,mode,density);view.layoutMenu?.render();view.sortMenu?.sync();if(view.live){setText(view.live,"");setText(view.live,fill(view.labels.layoutChanged,{mode:layoutModeText(view,mode),density:layoutDensityText(view,density)}))}
|
|
30
22
|
view.stateChanged();view.emit("layout",{mode,density})}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/* Linked views: external filter chips and highlighted rows. The info tone keeps both apart from the reader's own chips and selection. */
|
|
2
|
-
.cx-has-linked,.cx-link-bar,.cx-link-chip{--cx-linked-bg:color-mix(in srgb,var(--
|
|
2
|
+
.cx-has-linked,.cx-link-bar,.cx-link-chip{--cx-linked-bg:color-mix(in srgb,var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7)) 14%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));}
|
|
3
3
|
.cx-has-linked .cx-row[data-cx-linked="true"]{background:var(--cx-linked-bg);}
|
|
4
|
-
.cx-has-linked .cx-row[data-cx-linked="true"][aria-selected="true"]{background:color-mix(in srgb,var(--
|
|
4
|
+
.cx-has-linked .cx-row[data-cx-linked="true"][aria-selected="true"]{background:color-mix(in srgb,var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7)) 14%,var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435)));}
|
|
5
5
|
.cx-has-linked .cx-row[data-cx-linked="true"] [data-cx-pin]{background:var(--cx-linked-bg);}
|
|
6
|
-
.cx-has-linked .cx-row[data-cx-linked="true"] > :first-child{box-shadow:inset var(--cx-size-3px) 0 0 var(--
|
|
6
|
+
.cx-has-linked .cx-row[data-cx-linked="true"] > :first-child{box-shadow:inset var(--cx-size-3px) 0 0 var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7));}
|
|
7
7
|
.cx-link-bar{flex:none;display:flex;flex-wrap:wrap;gap:var(--cx-size-6px);padding:0 0 var(--cx-size-8px);min-width:0;}
|
|
8
|
-
.cx-link-chip{max-width:100%;height:var(--cx-size-24px);min-height:var(--cx-size-24px);padding:0 var(--cx-size-9px);border:0;border-radius:var(--
|
|
8
|
+
.cx-link-chip{max-width:100%;height:var(--cx-size-24px);min-height:var(--cx-size-24px);padding:0 var(--cx-size-9px);border:0;border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--cx-linked-bg);color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font:inherit;font-size:var(--cx-size-13px);white-space:nowrap;overflow:hidden;cursor:pointer;}
|
|
9
9
|
.cx-data-grid .cx-link-chip.cx-grid-chip{background:var(--cx-linked-bg);}
|
|
10
|
-
.cx-link-chip:hover{background:color-mix(in srgb,var(--
|
|
11
|
-
.cx-link-chip:focus-visible{outline:var(--
|
|
10
|
+
.cx-link-chip:hover{background:color-mix(in srgb,var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7)) 22%,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));}
|
|
11
|
+
.cx-link-chip:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
|
|
12
12
|
@media (forced-colors:active){
|
|
13
|
-
.cx-has-linked .cx-row[data-cx-linked="true"]{outline:var(--cx-size-2px) dashed Highlight;outline-offset:var(--
|
|
13
|
+
.cx-has-linked .cx-row[data-cx-linked="true"]{outline:var(--cx-size-2px) dashed Highlight;outline-offset:calc(-1 * var(--hfx-focus-width,2px));}
|
|
14
14
|
.cx-link-chip{border:var(--cx-size-1px) solid ButtonText;}
|
|
15
15
|
}
|
|
16
16
|
@media print{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"e7268bbe59e2dfa8",install(context){if(installed.has(context.LINK_IMPL))return;const{LINK_IMPL,h,setText,filterChipContent,fill,numberFormat,cellValue,setAttr,cellMatches}=context;const{TreeGrid,DataGrid}=LINK_IMPL;const LINK_SOURCE=/^[A-Za-z0-9][\w.:-]{0,127}$/, LINK_MAX_KEYS = 10000, LINK_MAX_VALUES = 1000;
|
|
2
2
|
const linkText=(value,name,max)=>{if(value===undefined)return undefined;if(typeof value!=="string"||!/\S/.test(value) || value.length > max) throw new Error("CanopyX: link " + name + " must be visible text of at most " + max + " characters.");
|
|
3
3
|
return value};const linkIsoDate=value=>typeof value==="string"&&/^\d{4}-\d\d-\d\dT.*(?:Z|[+-]\d\d:\d\d)$/.test(value) && Number.isFinite(Date.parse(value));
|
|
4
4
|
function linkColumn(grid,field){const column=grid.view.columns.find(item=>item.id===field);if(!column)throw new Error("CanopyX: a link names the undeclared column '"+field+"'.");return column}
|