@evotecit/canopyx 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CanopyX.Html/Assets/canopyx-calendar-edit.js +113 -0
- package/CanopyX.Html/Assets/canopyx-calendar-ics.js +87 -0
- package/CanopyX.Html/Assets/canopyx-calendar-recurrence.js +36 -0
- package/CanopyX.Html/Assets/canopyx-calendar.css +279 -0
- package/CanopyX.Html/Assets/canopyx-calendar.js +307 -0
- package/CanopyX.Html/Assets/canopyx-cell-range.css +38 -0
- package/CanopyX.Html/Assets/canopyx-cell-range.js +141 -0
- package/CanopyX.Html/Assets/canopyx-column-groups.css +18 -0
- package/CanopyX.Html/Assets/canopyx-column-groups.js +51 -0
- package/CanopyX.Html/Assets/canopyx-data.js +14 -0
- package/CanopyX.Html/Assets/canopyx-detail-rows.css +18 -0
- package/CanopyX.Html/Assets/canopyx-detail-rows.js +51 -0
- package/CanopyX.Html/Assets/canopyx-editing.css +44 -0
- package/CanopyX.Html/Assets/canopyx-editing.js +134 -0
- package/CanopyX.Html/Assets/canopyx-enhance.js +126 -0
- package/CanopyX.Html/Assets/canopyx-export.js +18 -0
- package/CanopyX.Html/Assets/canopyx-facets.css +86 -0
- package/CanopyX.Html/Assets/canopyx-facets.js +65 -0
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +15 -18
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +23 -17
- package/CanopyX.Html/Assets/canopyx-format-editor.css +77 -0
- package/CanopyX.Html/Assets/canopyx-format-editor.js +30 -0
- package/CanopyX.Html/Assets/canopyx-formatting.css +40 -0
- package/CanopyX.Html/Assets/canopyx-formatting.js +101 -0
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +352 -246
- package/CanopyX.Html/Assets/canopyx-grid.css +139 -117
- package/CanopyX.Html/Assets/canopyx-grid.js +352 -246
- package/CanopyX.Html/Assets/canopyx-grouping.css +39 -0
- package/CanopyX.Html/Assets/canopyx-grouping.js +85 -0
- package/CanopyX.Html/Assets/canopyx-highlight.css +34 -0
- package/CanopyX.Html/Assets/canopyx-highlight.js +80 -0
- package/CanopyX.Html/Assets/canopyx-history.js +13 -0
- package/CanopyX.Html/Assets/canopyx-interactive.css +18 -6
- package/CanopyX.Html/Assets/canopyx-interactive.js +179 -100
- package/CanopyX.Html/Assets/canopyx-labels-de.js +304 -0
- package/CanopyX.Html/Assets/canopyx-labels-es.js +304 -0
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +529 -0
- package/CanopyX.Html/Assets/canopyx-labels-it.js +529 -0
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +304 -0
- package/CanopyX.Html/Assets/canopyx-layouts.css +48 -0
- package/CanopyX.Html/Assets/canopyx-layouts.js +39 -0
- package/CanopyX.Html/Assets/canopyx-link.css +19 -0
- package/CanopyX.Html/Assets/canopyx-link.js +38 -0
- package/CanopyX.Html/Assets/canopyx-links.js +14 -0
- package/CanopyX.Html/Assets/canopyx-live.css +24 -0
- package/CanopyX.Html/Assets/canopyx-live.js +88 -0
- package/CanopyX.Html/Assets/canopyx-module.mjs +180 -100
- package/CanopyX.Html/Assets/canopyx-pager.css +10 -0
- package/CanopyX.Html/Assets/canopyx-pager.js +14 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.css +111 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.js +178 -0
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +406 -342
- package/CanopyX.Html/Assets/canopyx-reporting.css +140 -135
- package/CanopyX.Html/Assets/canopyx-reporting.js +406 -342
- package/CanopyX.Html/Assets/canopyx-search.js +32 -0
- package/CanopyX.Html/Assets/canopyx-timeline.css +80 -0
- package/CanopyX.Html/Assets/canopyx-timeline.js +88 -0
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +103 -0
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +92 -0
- package/CanopyX.Html/Assets/canopyx.css +17 -5
- package/CanopyX.Html/Assets/canopyx.js +175 -96
- package/JavaScript/calendar.d.ts +362 -0
- package/JavaScript/cell-ranges.d.ts +76 -0
- package/JavaScript/column-groups.d.ts +32 -0
- package/JavaScript/editing.d.ts +257 -0
- package/JavaScript/enhance.d.ts +202 -0
- package/JavaScript/facets.d.ts +58 -0
- package/JavaScript/formatting.d.ts +88 -0
- package/JavaScript/grid.d.ts +409 -56
- package/JavaScript/hosts.d.ts +177 -2
- package/JavaScript/index.d.ts +53 -4
- package/JavaScript/live.d.ts +115 -0
- package/JavaScript/locales/de.mjs +304 -0
- package/JavaScript/locales/es.mjs +304 -0
- package/JavaScript/locales/fr.d.ts +6 -0
- package/JavaScript/locales/fr.mjs +527 -0
- package/JavaScript/locales/it.d.ts +6 -0
- package/JavaScript/locales/it.mjs +527 -0
- package/JavaScript/locales/pl.mjs +304 -0
- package/JavaScript/plugins.d.ts +113 -0
- package/JavaScript/protocol.d.ts +139 -6
- package/JavaScript/records.d.ts +136 -0
- package/README.md +61 -9
- package/README.nuget.md +1 -1
- package/package.json +99 -3
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Facet panel: beside (side) or above (top) the grid in a frame,collapsible,and a full-screen sheet where it does not fit. */
|
|
2
|
+
.cx-facet-frame{display:flex;align-items:stretch;gap:var(--cx-size-12px);min-width:0;}
|
|
3
|
+
.cx-facet-frame[data-cx-position="top"]{flex-direction:column;}
|
|
4
|
+
.cx-facet-frame > .cx-data-grid{flex:1 1 auto;min-width:0;}
|
|
5
|
+
body.cx-page > .cx-facet-frame,body.cx-page > .cx-main > .cx-facet-frame{box-sizing:border-box;height:100vh;padding:12px 16px;}
|
|
6
|
+
body.cx-page > .cx-facet-frame > .cx-data-grid,body.cx-page > .cx-main > .cx-facet-frame > .cx-data-grid{height:auto;min-height:0;}
|
|
7
|
+
body.cx-page > .cx-facet-frame[data-cx-position="side"] > .cx-data-grid,body.cx-page > .cx-main > .cx-facet-frame[data-cx-position="side"] > .cx-data-grid{align-self:stretch;}
|
|
8
|
+
.cx-facets.cx-host{height:auto;min-height:0;border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);background:var(--cx-surface);overflow:hidden;}
|
|
9
|
+
.cx-facets.cx-host[hidden]{display:none;}
|
|
10
|
+
.cx-facets[data-cx-position="side"]{flex:none;width:var(--cx-facets-w,260px);align-self:flex-start;display:flex;flex-direction:column;}
|
|
11
|
+
.cx-facets-h{display:flex;align-items:center;gap:var(--cx-size-6px);min-height:var(--cx-size-44px);padding:var(--cx-size-6px) var(--cx-size-6px) var(--cx-size-6px) var(--cx-size-12px);border-bottom:var(--cx-size-1px) solid var(--cx-line);}
|
|
12
|
+
.cx-facets-title{flex:1;min-width:0;margin:0;font-size:var(--cx-size-14px);font-weight:600;line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
13
|
+
.cx-facets .cx-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--cx-size-6px);min-height:var(--cx-size-28px);padding:0 var(--cx-size-8px);border:var(--cx-size-1px) solid transparent;border-radius:var(--cx-radius-sm);background:transparent;color:var(--cx-text-2);font:inherit;font-size:var(--cx-size-13px);cursor:pointer;}
|
|
14
|
+
.cx-facets .cx-button:hover{background:var(--cx-head-bg);color:var(--cx-text);}
|
|
15
|
+
.cx-facets .cx-button:focus-visible,.cx-facet-toggle:focus-visible,.cx-facet-val input:focus-visible,.cx-facets .cx-input:focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-1px);}
|
|
16
|
+
.cx-facets-toggle{width:var(--cx-size-28px);padding:0;}
|
|
17
|
+
.cx-facets-toggle .cx-ico,.cx-facets-open .cx-ico{width:var(--cx-size-16px);height:var(--cx-size-16px);}
|
|
18
|
+
.cx-data-grid > .cx-facets-open{flex:none;align-self:flex-start;min-height:var(--cx-size-44px);margin:var(--cx-size-8px) var(--cx-size-12px);}
|
|
19
|
+
.cx-facets-list{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;}
|
|
20
|
+
.cx-facets[data-cx-position="top"] .cx-facets-list{display:flex;flex-wrap:wrap;gap:0;overflow-y:visible;}
|
|
21
|
+
.cx-facets[data-cx-position="top"] .cx-facet{flex:1 1 var(--cx-size-210px);min-width:var(--cx-size-180px);max-width:var(--cx-size-320px);border-inline-end:var(--cx-size-1px) solid var(--cx-line);}
|
|
22
|
+
.cx-facets.cx-facets-closed[data-cx-position="side"]{width:var(--cx-size-44px);}
|
|
23
|
+
.cx-facets.cx-facets-closed .cx-facets-list,.cx-facets.cx-facets-closed .cx-facets-clear{display:none;}
|
|
24
|
+
.cx-facets.cx-facets-closed[data-cx-position="side"] .cx-facets-title{display:none;}
|
|
25
|
+
.cx-facets.cx-facets-closed[data-cx-position="side"] .cx-facets-h{justify-content:center;padding:var(--cx-size-6px) 0;border-bottom:0;}
|
|
26
|
+
.cx-facet{position:relative;border-bottom:var(--cx-size-1px) solid var(--cx-line);}
|
|
27
|
+
.cx-facet-h{margin:0;font-size:inherit;font-weight:inherit;}
|
|
28
|
+
.cx-facet-top{position:relative;}
|
|
29
|
+
.cx-facets:not([data-cx-position="top"]) .cx-facet-top,.cx-facets.cx-facets-in-sheet .cx-facet-top{position:sticky;top:0;z-index:1;background:var(--cx-surface);}
|
|
30
|
+
.cx-facets:not([data-cx-position="top"]) .cx-facet-b,.cx-facets.cx-facets-in-sheet .cx-facet-b{position:relative;z-index:0;}
|
|
31
|
+
.cx-facet-toggle{display:flex;align-items:center;gap:var(--cx-size-6px);width:100%;min-height:var(--cx-size-36px);padding-block:var(--cx-size-6px);padding-inline:var(--cx-size-12px) var(--cx-size-64px);border:0;background:transparent;color:var(--cx-text);font:inherit;font-size:var(--cx-size-13d5px);font-weight:600;text-align:start;cursor:pointer;}
|
|
32
|
+
.cx-facet-toggle::after{content:"";flex:none;width:var(--cx-size-7px);height:var(--cx-size-7px);margin-inline-start:auto;border-right:var(--cx-size-1d5px) solid var(--cx-muted);border-bottom:var(--cx-size-1d5px) solid var(--cx-muted);transform:translateY(-25%) rotate(45deg);}
|
|
33
|
+
.cx-facet-toggle[aria-expanded="false"]::after{transform:rotate(-45deg);}
|
|
34
|
+
.cx-facet-toggle:hover{background:var(--cx-head-bg);}
|
|
35
|
+
.cx-facet-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
36
|
+
.cx-facet-badge{flex:none;min-width:var(--cx-size-20px);height:var(--cx-size-20px);padding:0 var(--cx-size-6px);border-radius:var(--cx-size-999px);background:var(--cx-accent-soft);color:var(--cx-text);font-size:var(--cx-size-12px);font-weight:600;line-height:var(--cx-size-20px);text-align:center;}
|
|
37
|
+
.cx-facet-badge[hidden]{display:none;}
|
|
38
|
+
.cx-facets .cx-facet-clear{position:absolute;top:var(--cx-size-4px);inset-inline-end:var(--cx-size-30px);width:var(--cx-size-28px);min-height:var(--cx-size-28px);padding:0;}
|
|
39
|
+
.cx-facets .cx-facet-clear .cx-ico{width:var(--cx-size-14px);height:var(--cx-size-14px);}
|
|
40
|
+
.cx-facet-empty{color:var(--cx-muted);font-style:italic;}
|
|
41
|
+
.cx-facet-b{padding:0 var(--cx-size-12px) var(--cx-size-10px);}
|
|
42
|
+
.cx-facet-b[hidden]{display:none;}
|
|
43
|
+
.cx-facets .cx-facet-search{width:100%;height:var(--cx-size-30px);margin:0 0 var(--cx-size-6px);padding:0 var(--cx-size-8px);border:var(--cx-size-1px) solid var(--cx-control-border);border-radius:var(--cx-radius-sm);background:var(--cx-surface);color:var(--cx-text);font:inherit;font-size:var(--cx-size-13px);}
|
|
44
|
+
.cx-facet-values{margin:0;padding:0;list-style:none;}
|
|
45
|
+
.cx-facet-val{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--cx-size-8px);min-height:var(--cx-size-28px);padding:0 var(--cx-size-4px);border-radius:var(--cx-radius-sm);font-size:var(--cx-size-13d5px);cursor:pointer;}
|
|
46
|
+
.cx-facet-val:hover{background:var(--cx-head-bg);}
|
|
47
|
+
.cx-facet-val input{width:var(--cx-size-16px);height:var(--cx-size-16px);margin:0;accent-color:var(--cx-accent);}
|
|
48
|
+
.cx-facet-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
49
|
+
.cx-facet-n{color:var(--cx-muted);font-size:var(--cx-size-12d5px);font-variant-numeric:tabular-nums;text-align:end;}
|
|
50
|
+
.cx-facet-zero .cx-facet-text,.cx-facet-zero .cx-facet-n{color:var(--cx-muted);}
|
|
51
|
+
.cx-facets .cx-facet-more{margin-top:var(--cx-size-2px);padding:0 var(--cx-size-4px);color:var(--cx-accent);}
|
|
52
|
+
.cx-facet-note{margin:var(--cx-size-6px) 0 0;color:var(--cx-muted);font-size:var(--cx-size-12d5px);}
|
|
53
|
+
.cx-facet-note[hidden],.cx-facets [hidden]{display:none;}
|
|
54
|
+
.cx-facet-hist{display:flex;align-items:flex-end;gap:var(--cx-size-2px);height:var(--cx-size-52px);margin:var(--cx-size-4px) 0 var(--cx-size-2px);padding-bottom:var(--cx-size-1px);border-bottom:var(--cx-size-1px) solid var(--cx-line);}
|
|
55
|
+
.cx-facet-bar{flex:1;min-width:var(--cx-size-2px);border-radius:var(--cx-size-2px) var(--cx-size-2px) 0 0;background:color-mix(in srgb,var(--cx-text) 22%,var(--cx-surface));cursor:pointer;}
|
|
56
|
+
.cx-facet-bar:hover{background:color-mix(in srgb,var(--cx-text) 40%,var(--cx-surface));}
|
|
57
|
+
.cx-facet-bar.cx-facet-in{background:var(--cx-accent);}
|
|
58
|
+
.cx-facet-axis{display:flex;justify-content:space-between;gap:var(--cx-size-8px);margin:0 0 var(--cx-size-6px);color:var(--cx-muted);font-size:var(--cx-size-12px);font-variant-numeric:tabular-nums;}
|
|
59
|
+
.cx-facet-range{display:grid;grid-template-columns:1fr 1fr;gap:var(--cx-size-8px);}
|
|
60
|
+
.cx-facet-field{display:flex;flex-direction:column;gap:var(--cx-size-2px);min-width:0;color:var(--cx-text-2);font-size:var(--cx-size-12d5px);}
|
|
61
|
+
.cx-facet-field .cx-input{width:100%;min-width:0;height:var(--cx-size-30px);padding:0 var(--cx-size-6px);border:var(--cx-size-1px) solid var(--cx-control-border);border-radius:var(--cx-radius-sm);background:var(--cx-surface);color:var(--cx-text);font:inherit;font-size:var(--cx-size-13px);color-scheme:inherit;}
|
|
62
|
+
.cx-data-grid .cx-facets-open[hidden]{display:none;}
|
|
63
|
+
.cx-data-grid .cx-facets-open .badge{min-width:var(--cx-size-18px);height:var(--cx-size-18px);padding:0 var(--cx-size-5px);border-radius:var(--cx-size-999px);background:var(--cx-accent);color:var(--cx-surface);font-size:var(--cx-size-11px);line-height:var(--cx-size-18px);}
|
|
64
|
+
.cx-facet-sheet.cx-host{position:fixed;inset:0;width:100%;max-width:none;height:100%;max-height:none;margin:0;padding:0;border:0;border-radius:0;flex-direction:column;}
|
|
65
|
+
.cx-facet-sheet.cx-host[open]{display:flex;}
|
|
66
|
+
.cx-facet-sheet::backdrop{background:color-mix(in srgb,black 40%,transparent);}
|
|
67
|
+
.cx-facet-sheet-h{display:flex;align-items:center;gap:var(--cx-size-8px);min-height:var(--cx-size-56px);padding:var(--cx-size-6px) var(--cx-size-12px) var(--cx-size-6px) var(--cx-size-16px);border-bottom:var(--cx-size-1px) solid var(--cx-line);}
|
|
68
|
+
.cx-facet-sheet-h h2{flex:1;margin:0;font-size:var(--cx-size-16px);}
|
|
69
|
+
.cx-facet-sheet-h .cx-button{min-height:var(--cx-size-44px);padding:0 var(--cx-size-16px);}
|
|
70
|
+
.cx-facets.cx-facets-in-sheet{flex:1;align-self:stretch;width:auto;min-height:0;border:0;border-radius:0;}
|
|
71
|
+
.cx-facets.cx-facets-in-sheet .cx-facets-list{display:block;overflow-y:auto;}
|
|
72
|
+
.cx-facets.cx-facets-in-sheet .cx-facet{max-width:none;border-inline-end:0;}
|
|
73
|
+
.cx-facets.cx-facets-in-sheet .cx-facet-values{max-height:none;}
|
|
74
|
+
.cx-facets.cx-facets-in-sheet .cx-facets-h{display:none;}
|
|
75
|
+
.cx-facet-sheet-h .cx-facets-clear{min-height:var(--cx-size-44px);padding:0 var(--cx-size-12px);border:0;background:transparent;color:var(--cx-accent);font:inherit;font-size:var(--cx-size-14px);cursor:pointer;}
|
|
76
|
+
.cx-facet-sheet-h .cx-facets-clear:focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-1px);}
|
|
77
|
+
.cx-facet-sheet-h .cx-facets-clear[hidden]{display:none;}
|
|
78
|
+
.cx-facets.cx-facets-in-sheet .cx-facet-val,.cx-facets.cx-facets-in-sheet .cx-facet-toggle,.cx-facets.cx-facets-in-sheet .cx-button{min-height:var(--cx-size-44px);}
|
|
79
|
+
.cx-facets.cx-facets-in-sheet .cx-facet-clear{top:0;}
|
|
80
|
+
@media (forced-colors:active){
|
|
81
|
+
.cx-facet-bar{background:CanvasText;}
|
|
82
|
+
.cx-facet-bar.cx-facet-in{background:Highlight;}
|
|
83
|
+
.cx-facet-badge,.cx-data-grid .cx-facets-open .badge{border:var(--cx-size-1px) solid CanvasText;}
|
|
84
|
+
.cx-facet-top{background:Canvas;}
|
|
85
|
+
}
|
|
86
|
+
@media print{.cx-facets,.cx-data-grid .cx-facets-open{display:none;}}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"f9219d35a87635f8",install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,fill,gridButton,gridIcon,gridQueryStart,gridQueryRows,gridColumnProjection,gridScalar,gridOrder,cellText,foldText,numberFormat,gridCellRenderer,gridFreeze}=context;function gridColumnGroup(operator,items){const filters=[],groups=[];for(const item of items){if(typeof item==="boolean"){if(item===(operator==="or"))return item;continue}
|
|
2
|
+
if(item.operator===operator){filters.push(...item.filters);groups.push(...item.groups)}
|
|
3
|
+
else(item.groups?groups:filters).push(item)}
|
|
4
|
+
return!filters.length&&!groups.length?operator==="and":!filters.length&&groups.length===1?groups[0]:{operator,filters,groups}}
|
|
5
|
+
function gridColumnClauses(query,id){const clauses=[],has=group=>group.filters.some(item=>item.column===id)||group.groups.some(has),only=group=>group.filters.every(item=>item.column===id)&&group.groups.every(only);const remove=group=>{if(!group)return undefined;if(only(group)){clauses.push(group);return undefined}
|
|
6
|
+
if(group.operator==="or"&&has(group))throw new Error("complex");const filters=group.filters.filter(item=>{if(item.column!==id)return true;clauses.push(item);return false}),groups=group.groups.map(remove).filter(Boolean);if(!filters.length&&!groups.length)return undefined;return gridColumnGroup(group.operator,[...filters,...groups])};const filters=(query.filters||[]).filter(item=>{if(item.column!==id)return true;clauses.push(item);return false}),filterGroup=remove(query.filterGroup);return{clauses,query:{...query,filters,filterGroup}}}
|
|
7
|
+
function gridInstallColumnClause(query,id,clause){const base=gridColumnClauses(query,id).query;if(!clause)return gridQueryStart(base);if(!clause.groups)return gridQueryStart(base,{filters:[...base.filters,clause]});return gridQueryStart(base,{filterGroup:base.filterGroup?gridColumnGroup("and",[base.filterGroup,clause]):clause})}
|
|
8
|
+
const FACET_KEYS=new Set(["columns","position","open","collapsible","width","label","target"]);const FACET_COLUMN_KEYS=new Set(["column","kind","label","limit","bins","sort","collapsed"]);const FACET_VALUES=200;function facetOptions(grid){const read=value=>{if(value===undefined)return{};if(!value||typeof value!=="object"||Array.isArray(value)||Object.keys(value).some(key=>!FACET_KEYS.has(key)))
|
|
9
|
+
throw new Error("CanopyX: facets takes columns, position, open, collapsible, width, label and target.");return value};const merged={...read(grid.view.facets),...read(grid.opts.facets)},columns=new Map(grid.view.columns.map(column=>[column.id,column]));if(!Array.isArray(merged.columns)||!merged.columns.length||merged.columns.length>24)throw new Error("CanopyX: facets need 1 to 24 columns.");const seen=new Set();const facets=merged.columns.map(entry=>{const facet=typeof entry==="string"?{column:entry}:entry;if(!facet||typeof facet!=="object"||Object.keys(facet).some(key=>!FACET_COLUMN_KEYS.has(key))||!columns.has(facet.column)||seen.has(facet.column)||
|
|
10
|
+
facet.kind!==undefined&&!["list","range"].includes(facet.kind)||facet.label!==undefined&&(typeof facet.label!=="string"||!facet.label.trim()||facet.label.length>256)||
|
|
11
|
+
facet.limit!==undefined&&(!Number.isInteger(facet.limit)||facet.limit<1||facet.limit>FACET_VALUES)||
|
|
12
|
+
facet.bins!==undefined&&(!Number.isInteger(facet.bins)||facet.bins<2||facet.bins>60)||facet.sort!==undefined&&!["count","value"].includes(facet.sort)||
|
|
13
|
+
facet.collapsed!==undefined&&typeof facet.collapsed!=="boolean")
|
|
14
|
+
throw new Error("CanopyX: invalid or duplicate facet column " +(facet&&facet.column));seen.add(facet.column);const column=columns.get(facet.column),kind=facet.kind||(column.kind==="text"?"list":"range");if(kind==="range"&&column.kind==="text")throw new Error("CanopyX: range facets need number or date columns.");const order=kind==="list"?facetDeclaredOrder(grid,column):null;return{column:facet.column,def:column,kind,label:facet.label||column.title,limit:facet.limit||8,bins:facet.bins||16,sort:facet.sort||(kind==="list"&&!order?"count":"value"),order,collapsed:!!facet.collapsed}});if(merged.position!==undefined&&!["side","top"].includes(merged.position)||["open","collapsible"].some(key=>merged[key]!==undefined&&typeof merged[key]!=="boolean")||
|
|
15
|
+
merged.width!==undefined&&(!Number.isInteger(merged.width)||merged.width<180||merged.width>480)||
|
|
16
|
+
merged.label!==undefined&&(typeof merged.label!=="string"||!merged.label.trim()||merged.label.length>256)||
|
|
17
|
+
merged.target!==undefined&&!(merged.target instanceof HTMLElement))
|
|
18
|
+
throw new Error("CanopyX: invalid facet panel options.");const hosted=grid.view.source.kind!=="inline"||!!grid.opts.source;if(hosted&&typeof grid.getFacets!=="function")throw new Error("CanopyX: a hosted grid's facet panel needs the reporting runtime.");if(hosted&&facets.some(facet=>!grid.view.reporting?.facetColumns?.includes(facet.column)))
|
|
19
|
+
throw new Error("CanopyX: a hosted grid's facets must be declared reporting facet columns.");return{facets,hosted,position:merged.position||"side",open:merged.open!==false,collapsible:merged.collapsible!==false,width:merged.width||260,label:merged.label||null,target:merged.target||null}}
|
|
20
|
+
function facetDeclaredOrder(grid,column){const presenter=column.presenter,values=grid.view.reporting?.ordering?.[column.id]?.categories||
|
|
21
|
+
(presenter&&(presenter.kind==="enum"||presenter.kind==="state")&&presenter.tones?Object.keys(presenter.tones):null);return values&&values.length?new Map(values.map((value,index)=>[foldText(String(value)),index])):null}
|
|
22
|
+
function facetSelection(query,facet){let clauses;try{({clauses}=gridColumnClauses(query,facet.column))}catch(_){return{custom:true,locked:true}}
|
|
23
|
+
if(!clauses.length)return{none:true};if(facet.kind==="list"){const listed=clause=>["in","eq","isNull"].includes(clause.operator)&&!clause.groups;const items=clauses.length!==1?null:clauses[0].groups?clauses[0].operator==="or"&&!clauses[0].groups.length&&clauses[0].filters.every(listed)?clauses[0].filters:null:listed(clauses[0])?clauses:null;return items?{values:items.flatMap(clause=>clause.operator==="isNull"?[null]:clause.values)}:{custom:true}}
|
|
24
|
+
let low=null,high=null,lowOpen=false,open=false;for(const clause of clauses){if(clause.groups||clauses.length>2)return{custom:true};if((clause.operator==="ge"||clause.operator==="gt")&&low===null){low=clause.values[0];lowOpen=clause.operator==="gt"}
|
|
25
|
+
else if((clause.operator==="le"||clause.operator==="lt")&&high===null){high=clause.values[0];if(clause.operator==="lt")open=true}
|
|
26
|
+
else return{custom:true}}
|
|
27
|
+
return{low,high,lowOpen,open}}
|
|
28
|
+
function facetQuery(query,facet,choice){const predicate=(operator,values=[])=>({column:facet.column,operator,values});try{if(facet.kind==="range"){const base=gridColumnClauses(query,facet.column).query;const bounds=[choice.low!=null&&predicate(choice.lowOpen?"gt":"ge",[choice.low]),choice.high!=null&&predicate(choice.open?"lt":"le",[choice.high])].filter(Boolean);return gridQueryStart(base,{filters:[...base.filters,...bounds]})}
|
|
29
|
+
const raw=choice.filter(value=>value!==null),empty=raw.length<choice.length;const items=[raw.length&&predicate("in",raw),empty&&predicate("isNull")].filter(Boolean);return gridInstallColumnClause(query,facet.column,!items.length?null:items.length===1?items[0]:{operator:"or",filters:items,groups:[]})}catch(_){return query}}
|
|
30
|
+
const facetShape=query=>query?JSON.stringify([query.search,query.searchMode,query.filters,query.filterGroup,query.revision]):"";const facetKey=(value,column)=>value===null?"null":column.kind==="text"&&typeof value==="string"?"s:"+foldText(value):typeof value+":"+value;function facetInlineCounts(grid,facet,query){const projection=gridColumnProjection(query,facet.column),columns=new Map(grid.view.columns.map(column=>[column.id,column]));const rows=gridQueryRows(grid.view,projection,columns,false),column=facet.def;if(facet.kind==="range"){const values=[];for(const row of rows){const value=gridScalar(row.cells[column.id],column);if(value!==null)values.push(value)}
|
|
31
|
+
return{matched:rows.length,values,complete:true}}
|
|
32
|
+
const buckets=new Map();for(const row of rows){const raw=gridScalar(row.cells[column.id],column),value=column.kind==="datetime"&&raw!==null?new Date(raw).toISOString():raw,key=facetKey(value,column);const bucket=buckets.get(key);if(bucket){bucket.count++;if(typeof value==="string"&&value<bucket.value)bucket.value=value}else buckets.set(key,{value,count:1})}
|
|
33
|
+
const items=[...buckets.values()];return{matched:rows.length,items,totalValues:items.length,truncated:false}}
|
|
34
|
+
async function facetHostedCounts(grid,facet,search,signal){const page=await grid.getFacets(facet.column,{search:search||"",includeCurrentFilter:false,limit:FACET_VALUES,signal});const column=facet.def;if(facet.kind==="range")
|
|
35
|
+
return{matched:page.matched,buckets:page.items.filter(item=>item.value!==null).map(item=>({value:gridScalar(item.value,column),count:item.count})),complete:!page.truncated};return{matched:page.matched,items:page.items.map(item=>({value:item.value,count:item.count})),totalValues:page.totalValues,truncated:page.truncated}}
|
|
36
|
+
const FACET_SEARCH_FROM=12;function facetListBody(panel,facet,body){const grid=panel.grid,search=h("input","cx-input cx-facet-search"),list=h("ul","cx-facet-values"),more=gridButton("",()=>{state.expanded=!state.expanded;draw()});const note=h("p","cx-facet-note"),state={expanded:false,search:"",counts:null,timer:0};search.type="search";search.placeholder=grid.labels.gridFacetSearch;search.setAttribute("aria-label",fill(grid.labels.gridFacetSearch,{})+ ": "+facet.label);search.hidden=true;more.classList.add("cx-facet-more");more.hidden=true;note.hidden=true;list.setAttribute("aria-label",facet.label);body.append(search,list,more,note);search.addEventListener("input",()=>{state.search=search.value;clearTimeout(state.timer);state.timer=setTimeout(()=>facet.hosted?panel.refresh([facet]):draw(),facet.hosted?250:0)});list.addEventListener("keydown",event=>{const boxes=[...list.querySelectorAll("input")],at=boxes.indexOf(document.activeElement);const next={ArrowDown:at+1,ArrowUp:at-1,Home:0,End:boxes.length-1}[event.key];if(at<0||next===undefined||!boxes[next])return;event.preventDefault();boxes.forEach(box=>{box.tabIndex=-1});boxes[next].tabIndex=0;boxes[next].focus()});const choose=(item,checked)=>{const chosen=new Map((state.chosen||[]).map(value=>[facetKey(value,facet.def),value]));if(checked)chosen.set(facetKey(item.value,facet.def),item.value);else chosen.delete(facetKey(item.value,facet.def));state.chosen=[...chosen.values()];panel.apply(facet,state.chosen)};function draw(){const counts=state.counts,selection=panel.selection(facet);if(!counts)return;state.chosen=selection.values||[];const chosen=new Set(state.chosen.map(value=>facetKey(value,facet.def))),focused=list.contains(document.activeElement)?document.activeElement:null;const focusKey=focused?.getAttribute("data-cx-key"),focusPosition=focused?[...list.querySelectorAll("input")].indexOf(focused):0;const needle=facet.hosted?"":foldText(state.search),locked=!!selection.locked;let items=counts.items.filter(item=>!needle||item.value!==null&&foldText(String(item.value)).includes(needle));if(!(facet.hosted&&state.search))for(const value of state.chosen)if(!items.some(item=>facetKey(item.value,facet.def)===facetKey(value,facet.def)))items.push({value,count:0});items.sort(facet.sort==="count"?(a,b)=>b.count-a.count||facetValueOrder(a.value,b.value,facet):(a,b)=>facetValueOrder(a.value,b.value,facet));const shown=state.expanded?items.filter((item,index)=>index<FACET_VALUES||chosen.has(facetKey(item.value,facet.def))):items.filter((item,index)=>index<facet.limit||chosen.has(facetKey(item.value,facet.def)));const retainedIndex=shown.findIndex(item=>facetKey(item.value,facet.def)===focusKey);const focusIndex=retainedIndex>=0?retainedIndex:Math.min(Math.max(0,focusPosition),Math.max(0,shown.length-1));const numbers=numberFormat(grid.lang);list.replaceChildren(...shown.map((item,index)=>{const row=h("li"),label=h("label","cx-facet-val"),box=h("input"),text=h("span","cx-facet-text"),count=h("span","cx-facet-n"),key=facetKey(item.value,facet.def);box.type="checkbox";box.checked=chosen.has(key);box.disabled=locked;box.setAttribute("data-cx-key",key);box.tabIndex=index===focusIndex?0:-1;const empty=item.value===null||item.value==="",display=empty?grid.labels.gridFacetEmptyValue:facetValueText(grid,facet,item.value,text);if(empty){setText(text,display);text.classList.add("cx-facet-empty")}
|
|
37
|
+
box.setAttribute("aria-label",fill(grid.labels.gridFacetValueCount,{value:display,count:numbers.format(item.count)}));setText(count,numbers.format(item.count));count.setAttribute("aria-hidden","true");if(!item.count)label.classList.add("cx-facet-zero");box.addEventListener("change",()=>choose(item,box.checked));label.append(box,text,count);row.appendChild(label);return row}));if(focusKey){const target=!locked&&list.querySelector('input[tabindex="0"]')||body.closest(".cx-facet")?.querySelector(".cx-facet-toggle");target?.focus({preventScroll:!locked&&retainedIndex>=0})}
|
|
38
|
+
const hidden=items.length-shown.length,capped=state.expanded&&hidden>0;more.hidden=!hidden&&!state.expanded||items.length<=facet.limit;setText(more,state.expanded?grid.labels.gridFacetShowFewer:fill(grid.labels.gridFacetShowMore,{count:numbers.format(Math.min(hidden,Math.max(1,FACET_VALUES-shown.length)))}));search.hidden=!state.search&&document.activeElement!==search&&counts.totalValues<=FACET_SEARCH_FROM;search.disabled=locked;note.hidden=!counts.truncated&&!capped;if(!note.hidden)setText(note,fill(grid.labels.gridFacetCounts,{count:numbers.format(counts.matched),shown:numbers.format(counts.truncated?counts.items.length:shown.length),total:numbers.format(counts.totalValues)}))}
|
|
39
|
+
return{draw,search:()=>state.search,update(counts){state.counts=counts;draw()}}}
|
|
40
|
+
function facetValueOrder(a,b,facet){const column=facet.def;if(a===null||b===null)return a===b?0:a===null?1:-1;if(facet.order){const at=facet.order.get(foldText(String(a)))??Infinity,bt=facet.order.get(foldText(String(b)))??Infinity;if(at!==bt)return at<bt?-1:1}
|
|
41
|
+
if(column.kind!=="text")return gridOrder(gridScalar(a,column),gridScalar(b,column));if(typeof a!==typeof b)return typeof a==="boolean"?-1:1;return gridOrder(typeof a==="string"?foldText(a):a,typeof b==="string"?foldText(b):b)}
|
|
42
|
+
function facetValueText(grid,facet,value,element){const column=facet.def,options=column.presenter,text=cellText(value,column,grid.fmt)||String(value);if(options&&!["statusStrip","sparklineBars","sparklineLine","change","identifier","longText","list","tags","structured"].includes(options.kind)){try{gridCellRenderer(grid,column,options)({id:"facet",cells:{[column.id]:value}},element);return text}catch(_){element.replaceChildren()}}
|
|
43
|
+
setText(element,text);return text}
|
|
44
|
+
function facetRangeBody(panel,facet,body){const grid=panel.grid,column=facet.def,date=column.kind==="datetime",numbers=numberFormat(grid.lang);const chart=h("div","cx-facet-hist"),axis=h("p","cx-facet-axis"),low=h("span"),high=h("span"),fields=h("div","cx-facet-range"),note=h("p","cx-facet-note");const field=(text,edge)=>{const label=h("label","cx-facet-field"),input=h("input","cx-input");input.type=date?"date":"number";if(!date)input.step="any";label.append(document.createTextNode(text),input);input.addEventListener("change",()=>submit(edge));input.addEventListener("keydown",event=>{if(event.key==="Enter"){event.preventDefault();submit(edge)}});return{label,input}};const from=field(grid.labels.gridFacetFrom,"low"),to=field(grid.labels.gridFacetTo,"high");chart.setAttribute("role","img");chart.setAttribute("aria-label",fill(grid.labels.gridFacetHistogram,{column:facet.label}));axis.append(low,high);axis.setAttribute("aria-hidden","true");fields.append(from.label,to.label);note.hidden=true;note.setAttribute("role","status");body.append(chart,axis,fields,note);const state={counts:null,bins:[]};const toInput=value=>{if(value==null)return "";if(!date)return String(value);const day=new Date(value),pad=part=>String(part).padStart(2,"0");return grid.local?day.getFullYear()+ "-"+pad(day.getMonth()+ 1)+ "-"+pad(day.getDate()):day.toISOString().slice(0,10)};const fromInput=(text,edge)=>{if(text==="")return null;if(!date){const value=Number(text);return Number.isFinite(value)?value:undefined}
|
|
45
|
+
const[year,month,day]=text.split("-").map(Number),end=edge==="high";const time=grid.local?new Date(year,month-1,day,end?23:0,end?59:0,end?59:0,end?999:0).getTime():Date.UTC(year,month-1,day,end?23:0,end?59:0,end?59:0,end?999:0);return Number.isFinite(time)?time:undefined};const wire=value=>value==null?null:date?new Date(value).toISOString():value;const current=(selection=panel.selection(facet))=>{return{low:selection.low==null?null:date?Date.parse(selection.low):selection.low,high:selection.high==null?null:date?Date.parse(selection.high):selection.high,lowOpen:!!selection.lowOpen,open:!!selection.open,locked:!!selection.locked}};const binChoice=index=>{const bin=state.bins[index],last=index===state.bins.length-1;if(date)return{low:Math.ceil(bin.start),high:last?bin.end:Math.ceil(bin.end)- 1,open:false};return{low:bin.start,high:bin.end,open:!last}};function submit(edge){const selection=panel.selection(facet),range=current(selection);const lowChanged=edge==="low"||from.input.value!==toInput(range.low),highChanged=edge==="high"||to.input.value!==toInput(range.high);const low=lowChanged?fromInput(from.input.value,"low"):range.low,high=highChanged?fromInput(to.input.value,"high"):range.high;if(low===undefined||high===undefined){setText(note,grid.labels.gridFacetInvalid);note.hidden=false;return}
|
|
46
|
+
if(low!==null&&high!==null&&low>high){setText(note,grid.labels.gridFacetReversed);note.hidden=false;(edge==="low"?from:to).input.focus();return}
|
|
47
|
+
note.hidden=true;panel.apply(facet,{low:lowChanged?wire(low):selection.low??null,high:highChanged?wire(high):selection.high??null,lowOpen:!lowChanged&&range.lowOpen,open:!highChanged&&range.open})}
|
|
48
|
+
let anchor=null;chart.addEventListener("click",event=>{const bar=event.target.closest(".cx-facet-bar"),range=current();if(!bar||range.locked)return;const index=Number(bar.getAttribute("data-cx-bin")),extend=event.shiftKey&&anchor!==null&&anchor<state.bins.length;const first=binChoice(extend?Math.min(anchor,index):index),last=binChoice(extend?Math.max(anchor,index):index);if(!extend)anchor=index;if(!extend&&!range.lowOpen&&range.low===first.low&&range.high===first.high&&range.open===first.open){panel.apply(facet,{low:null,high:null});return}
|
|
49
|
+
panel.apply(facet,{low:wire(first.low),high:wire(last.high),open:last.open})});const label=value=>date?new Intl.DateTimeFormat(grid.lang,{dateStyle:"medium",timeZone:grid.local?undefined:"UTC"}).format(value):cellText(value,column,grid.fmt);function draw(){const counts=state.counts,range=current();if(!from.input.matches(":focus"))from.input.value=toInput(range.low);if(!to.input.matches(":focus"))to.input.value=toInput(range.high);from.input.disabled=to.input.disabled=range.locked;if(!counts)return;const pairs=counts.values?null:counts.buckets;let min=Infinity,max=-Infinity;for(const value of counts.values||[]){if(value<min)min=value;if(value>max)max=value}
|
|
50
|
+
for(const pair of pairs||[]){if(pair.value<min)min=pair.value;if(pair.value>max)max=pair.value}
|
|
51
|
+
const drawable=counts.complete&&min<=max;chart.hidden=axis.hidden=!drawable;if(!counts.complete){setText(note,grid.labels.gridFacetNoChart);note.hidden=false}else if(note.textContent===grid.labels.gridFacetNoChart)note.hidden=true;if(!drawable){state.bins=[];chart.replaceChildren();return}
|
|
52
|
+
const count=min===max?1:facet.bins,width=min===max?1:(max-min)/ count, tallies = new Array(count).fill(0);
|
|
53
|
+
const place=value=>Math.min(count-1,Math.floor((value-min)/ width));
|
|
54
|
+
for(const value of counts.values||[])tallies[place(value)]++;for(const pair of pairs||[])tallies[place(pair.value)]+=pair.count;const highest=Math.max(1,...tallies);const bins=tallies.map((tally,index)=>({start:min+index*width,end:index===count-1?max:min +(index+1)*width,count:tally}));const sameBins=bins.length===state.bins.length&&bins.every((bin,index)=>bin.start===state.bins[index].start&&bin.end===state.bins[index].end);state.bins=bins;const bars=sameBins?Array.from(chart.children):bins.map(()=>h("span","cx-facet-bar"));bins.forEach((bin,index)=>{const last=index===count-1,bar=bars[index];const inside=(range.low==null||(last&&!range.lowOpen?bin.end>=range.low:bin.end>range.low))&&(range.high==null||(range.open?bin.start<range.high:bin.start<=range.high));bar.setAttribute("data-cx-bin",String(index));bar.style.height=Math.max(bin.count?6:0,Math.round(bin.count / highest * 100)) + "%";
|
|
55
|
+
bar.classList.toggle("cx-facet-in",inside&&(range.low!=null||range.high!=null));bar.title=fill(grid.labels.gridFacetBin,{from:label(bin.start),to:label(bin.end),count:numbers.format(bin.count)})});if(!sameBins)chart.replaceChildren(...bars);setText(low,label(min));setText(high,label(max))}
|
|
56
|
+
return{draw,search:()=>"",update(counts){state.counts=counts;draw()}}}
|
|
57
|
+
let facetSeq=0;const FACET_ICON='<path d="M4 6h16M7 12h10M10 18h4"/>';function facetTheme(grid,element){element.setAttribute("data-cx-theme",grid.host.getAttribute("data-cx-theme")||"auto");const style=grid.host.style;for(const name of style)if(name.startsWith("--cx-"))element.style.setProperty(name,style.getPropertyValue(name))}
|
|
58
|
+
Object.assign(DataGrid.prototype,{startFacets(){if(this.facetPanel)return;const options=this.facetOptions=facetOptions(this),id=this.id+"-facets-" + ++facetSeq,signal=this.lifetime.signal;this.facetColumns=options.facets.map(facet=>Object.assign(facet,{hosted:options.hosted}));this.facetOpen??=options.open;if(this.defaultState)this.defaultState.facets={open:options.open};const panel=this.facetPanel=h("aside","cx-host cx-chrome cx-facets"),head=h("div","cx-facets-h"),title=h("h2","cx-facets-title");const clear=gridButton(this.labels.gridClearAll,()=>this.facetClearAll()),toggle=gridButton("",()=>this.setFacetPanelOpen(!this.facetOpen));const list=h("div","cx-facets-list"),live=this.facetLive=h("p","cx-sr-only");panel.id=id;panel.setAttribute("aria-labelledby",id+"-title");title.id=id+"-title";setText(title,options.label||this.labels.gridFacetPanel);live.setAttribute("aria-live","polite");toggle.classList.add("cx-facets-toggle");toggle.setAttribute("aria-controls",id+"-list");list.id=id+"-list";toggle.appendChild(gridIcon(null,FACET_ICON));clear.classList.add("cx-facets-clear");this.facetClear=clear;toggle.hidden=!options.collapsible;head.append(title,clear,toggle);panel.append(head,list,live);facetTheme(this,panel);panel.setAttribute("data-cx-position",options.position);panel.style.setProperty("--cx-facets-w",options.width+"px");this.facetSections=this.facetColumns.map(facet=>this.facetSection(facet,list));if(options.target)options.target.appendChild(panel);else{const frame=this.facetFrame=h("div","cx-facet-frame");frame.setAttribute("data-cx-position",options.position);this.host.before(frame);frame.append(panel,this.host)}
|
|
59
|
+
const sheetButton=this.facetSheetButton=gridButton(this.labels.gridFacetPanel,()=>this.openFacetSheet());sheetButton.classList.add("cx-btn","cx-facets-open");sheetButton.prepend(gridIcon(null,FACET_ICON));sheetButton.hidden=true;sheetButton.setAttribute("aria-haspopup","dialog");const anchor=this.toolbar.querySelector(".cx-grid-filters")||this.toolbar.querySelector(".cx-grid-columns")||this.spacer;if(this.opts.toolbar===false)this.host.prepend(sheetButton);else if(anchor?.parentNode===this.toolbar)anchor.before(sheetButton);else this.toolbar.prepend(sheetButton);this.facetResize=new ResizeObserver(()=>requestAnimationFrame(()=>this.destroyed||this.facetFit()));this.facetResize.observe(this.facetFrame||this.host);if(this.facetFrame)this.facetResize.observe(this.host);this.host.addEventListener("canopyx:query",()=>{if(facetShape(this.acceptedQuery)!==this.facetCounted)this.facetRefresh()},{signal});this.host.addEventListener("canopyx:rowsChanged",()=>{clearTimeout(this.facetLiveTimer);this.facetLiveTimer=setTimeout(()=>this.facetRefresh(),300)},{signal});signal.addEventListener("abort",()=>this.facetDestroy(),{once:true});this.facetSync();this.facetFit();if(this.acceptedQuery)this.facetRefresh()},facetSection(facet,list){const section=h("section","cx-facet"),head=h("h3","cx-facet-h"),toggle=h("button","cx-facet-toggle"),name=h("span","cx-facet-name"),badge=h("span","cx-facet-badge");const clear=gridButton("",()=>this.facetApply(facet,facet.kind==="list"?[]:{low:null,high:null})),body=h("div","cx-facet-b"),custom=h("p","cx-facet-note cx-facet-custom");const failure=h("p","cx-facet-note cx-facet-error"),spoken=h("span","cx-sr-only");const bodyId=this.facetPanel.id+"-"+facet.column;section.setAttribute("data-cx-facet",facet.column);toggle.type="button";toggle.setAttribute("aria-controls",bodyId);body.id=bodyId;badge.setAttribute("aria-hidden","true");setText(name,facet.label);toggle.append(name,badge,spoken);head.appendChild(toggle);clear.classList.add("cx-facet-clear");clear.appendChild(gridIcon("close"));clear.setAttribute("aria-label",fill(this.labels.gridFacetClear,{column:facet.label}));clear.title=clear.getAttribute("aria-label");custom.hidden=true;custom.setAttribute("role","status");failure.hidden=true;failure.setAttribute("role","status");const facetView={grid:this,selection:target=>facetSelection(this.queryForChange(),target),apply:(target,choice)=>this.facetApply(target,choice),refresh:targets=>this.facetRefresh(targets)};const content=facet.kind==="list"?facetListBody(facetView,facet,body):facetRangeBody(facetView,facet,body);body.prepend(custom,failure);const collapsed=()=>{const closed=facet.collapsed;toggle.setAttribute("aria-expanded",String(!closed));body.hidden=closed;toggle.title=fill(this.labels[closed?"gridFacetExpand":"gridFacetCollapse"],{column:facet.label})};toggle.addEventListener("click",()=>{facet.collapsed=!facet.collapsed;collapsed()});collapsed();const top=h("div","cx-facet-top");top.append(head,clear);section.append(top,body);list.appendChild(section);return{facet,section,badge,spoken,clear,custom,failure,content,generation:0,controller:null}},facetApply(facet,choice){this.facetPending||=new Map();this.facetPending.set(facet.column,{facet,choice});clearTimeout(this.facetTimer);this.facetTimer=setTimeout(()=>this.facetFlush(),150)},facetFlush(){clearTimeout(this.facetTimer);this.facetTimer=0;const pending=this.facetPending;this.facetPending=null;if(!pending||this.destroyed)return Promise.resolve();let query=this.queryForChange(true);for(const{facet,choice}of pending.values())query=facetQuery(query,facet,choice);return this.setQuery(query).then(()=>this.facetAnnounce(),()=>{})},facetClearAll(){clearTimeout(this.facetTimer);this.facetPending=null;let query=this.queryForChange(true);for(const facet of this.facetColumns)query=facetQuery(query,facet,facet.kind==="list"?[]:{low:null,high:null});return this.setQuery(query).then(()=>this.facetAnnounce(),()=>{})},facetAnnounce(){const numbers=numberFormat(this.lang);setText(this.facetLive,"");setText(this.facetLive,fill(this.labels.gridFacetResult,{count:numbers.format(this.snapshot?.matched??0)}))},async facetRefresh(targets){if(!this.facetPanel||!this.acceptedQuery||this.destroyed)return;const query=this.acceptedQuery,run=targets?this.facetRun:this.facetRun=(this.facetRun||0)+ 1;if(!targets)this.facetCounted=facetShape(query);for(const section of this.facetSections){if(targets&&!targets.includes(section.facet))continue;section.controller?.abort();const controller=section.controller=new AbortController(),generation=++section.generation;const current=()=>!this.destroyed&&run===this.facetRun&&generation===section.generation;try{const counts=section.facet.hosted?await facetHostedCounts(this,section.facet,section.content.search(),controller.signal):facetInlineCounts(this,section.facet,query);if(current()){section.failure.hidden=true;section.content.update(counts)}}catch(error){if(current()&&error?.name!=="AbortError"){setText(section.failure,fill(this.labels.queryFailed,{error:error.message}));section.failure.hidden=false}}finally{if(section.controller===controller)section.controller=null;controller.abort()}
|
|
60
|
+
if(!section.facet.hosted)await new Promise(resolve=>setTimeout(resolve,0));if(this.destroyed||run!==this.facetRun)return}},facetSync(){if(!this.facetPanel)return;const query=this.queryForChange(),numbers=numberFormat(this.lang);let active=0;for(const section of this.facetSections||[]){const selection=facetSelection(query,section.facet),count=selection.values?selection.values.length:selection.custom||selection.low!=null||selection.high!=null?1:0;active +=count?1:0;setText(section.badge,selection.values?numbers.format(count):"");section.badge.hidden=!selection.values||!count;setText(section.spoken,section.badge.hidden?"":", "+fill(this.labels.gridFacetSelected,{count:numbers.format(count)}));section.clear.hidden=!count||!!selection.locked;section.section.classList.toggle("cx-facet-active",!!count);if(selection.custom){setText(section.custom,this.labels.gridFacetCustom);section.custom.hidden=false}
|
|
61
|
+
else if(section.custom.textContent===this.labels.gridFacetCustom)section.custom.hidden=true;section.content.draw()}
|
|
62
|
+
this.facetClear.hidden=!active;this.facetActive=active;if(this.facetSheetButton){this.facetSheetButton.querySelector(".badge")?.remove();if(active){const badge=h("span","badge");setText(badge,numbers.format(active));this.facetSheetButton.appendChild(badge)}}},facetFit(){const panel=this.facetPanel,options=this.facetOptions;if(!panel||this.facetSheet)return;const width=(this.facetFrame||this.host).clientWidth,fits=options.target?true:options.position==="side"?width>=options.width+480:width>640;this.facetFits=fits;panel.hidden=!fits;this.facetSheetButton.hidden=fits;this.facetFrame?.toggleAttribute("data-cx-sheet",!fits);panel.classList.toggle("cx-facets-closed",!this.facetOpen);panel.style.height=options.position==="side"&&this.facetFrame&&this.facetOpen?Math.max(360,this.host.offsetHeight)+ "px":"";const toggle=panel.querySelector(".cx-facets-toggle");toggle.setAttribute("aria-expanded",String(!!this.facetOpen));toggle.setAttribute("aria-label",this.labels[this.facetOpen?"gridFacetPanelHide":"gridFacetPanelShow"]);toggle.title=toggle.getAttribute("aria-label")},setFacetPanelOpen(open){if(typeof open!=="boolean")return Promise.reject(new Error("CanopyX: the facet panel's open state is a boolean."));if(open!==this.facetOpen){this.facetOpen=open;this.facetFit();this.stateChanged();this.emit("facetPanel",{open})}
|
|
63
|
+
return Promise.resolve(this.getFacetPanel())},getFacetPanel(){if(!this.facetPanel)return gridFreeze({open:this.facetOpen??null,columns:(this.facetColumns||[]).map(facet=>facet.column)});return gridFreeze({open:!!this.facetOpen,columns:this.facetColumns.map(facet=>facet.column),active:this.facetActive||0})},openFacetSheet(){if(this.facetSheet||!this.facetPanel)return;const sheet=this.facetSheet=h("dialog","cx-host cx-chrome cx-grid-overlay cx-facet-sheet"),head=h("div","cx-facet-sheet-h"),title=h("h2"),done=gridButton(this.labels.gridDone,()=>sheet.close());const panel=this.facetPanel,home=panel.parentNode,next=panel.nextSibling,returnFocus=document.activeElement;facetTheme(this,sheet);title.id=this.id+"-facet-sheet";sheet.setAttribute("aria-labelledby",title.id);setText(title,this.facetOptions.label||this.labels.gridFacetPanel);const clear=this.facetClear,clearHome=clear.parentNode,clearNext=clear.nextSibling;done.classList.add("cx-btn");head.append(title,clear,done);sheet.append(head,panel);panel.hidden=false;panel.classList.remove("cx-facets-closed");panel.classList.add("cx-facets-in-sheet");document.body.appendChild(sheet);sheet.addEventListener("close",()=>{if(this.facetPanel!==panel){sheet.remove();return}// The grid was destroyed meanwhile; the panel is gone.
|
|
64
|
+
panel.classList.remove("cx-facets-in-sheet");home?.insertBefore(panel,next);clearHome.insertBefore(clear,clearNext);sheet.remove();this.facetSheet=null;this.facetFit();if(returnFocus?.isConnected)returnFocus.focus({preventScroll:true})},{once:true});sheet.showModal();done.focus()},facetDestroy(){clearTimeout(this.facetTimer);clearTimeout(this.facetLiveTimer);this.facetResize?.disconnect();for(const section of this.facetSections||[])section.controller?.abort();const sheet=this.facetSheet;this.facetSheet=null;this.facetPanel?.remove();this.facetSheetButton?.remove();this.facetPanel=null;if(sheet){sheet.close();sheet.remove()}
|
|
65
|
+
if(this.facetFrame){this.facetFrame.replaceWith(this.host);this.facetFrame=null}}});const FACET_SUMMARY=DataGrid.prototype.syncQuerySummary;DataGrid.prototype.syncQuerySummary=function(){FACET_SUMMARY.call(this);if(this.facetPanel)this.facetSync()};const FACET_ZONE=DataGrid.prototype.setTimeZone;DataGrid.prototype.setTimeZone=function(zone){const result=FACET_ZONE.call(this,zone);if(this.facetPanel)this.facetSync();return result};installed.add(context.DataGrid.prototype)}};(global.CanopyXParts||=[]).push(["facets",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
.cx-grid-overlay.cx-phone .cx-mi,.cx-grid-overlay.cx-phone .cx-val,.cx-grid-overlay.cx-phone .cx-input{min-height:var(--cx-size-44px);}
|
|
15
15
|
.cx-grid-overlay.cx-phone .cx-button{min-height:var(--cx-size-44px);min-width:var(--cx-size-44px);}
|
|
16
16
|
.cx-grid-overlay.cx-phone.cx-pop::before{content:"";display:block;width:var(--cx-size-32px);height:var(--cx-size-4px);border-radius:var(--cx-radius);background:var(--cx-muted);margin:var(--cx-size-8px) auto;}
|
|
17
|
-
.cx-data-grid.cx-phone .cx-cond,.cx-data-grid.cx-phone .cx-group .cx-cond{grid-template-columns:1fr 1fr var(--cx-size-32px)!important;}
|
|
17
|
+
.cx-data-grid.cx-phone .cx-cond,.cx-data-grid.cx-phone .cx-grid-filter-group .cx-cond{grid-template-columns:1fr 1fr var(--cx-size-32px)!important;}
|
|
18
18
|
.cx-data-grid.cx-phone .cx-cond .w{grid-column:1/-1;text-align:left;}
|
|
19
19
|
.cx-data-grid.cx-phone .cx-grid-filter > button.icon{grid-column:3;grid-row:2;min-height:var(--cx-size-44px);}
|
|
20
20
|
.cx-data-grid.cx-phone .cx-adds{padding-left:0;}
|
|
21
|
-
.cx-data-grid.cx-phone .cx-group{margin-left:var(--cx-size-4px);}
|
|
21
|
+
.cx-data-grid.cx-phone .cx-grid-filter-group{margin-left:var(--cx-size-4px);}
|
|
22
22
|
.cx-fb{width:100%;max-width:var(--cx-size-640px);}
|
|
23
23
|
.cx-fb .cx-pop-b{gap:var(--cx-size-10px);}
|
|
24
24
|
.cx-cond{display:grid;grid-template-columns:var(--cx-size-56px) 1.2fr 1fr 1.2fr var(--cx-size-32px);gap:var(--cx-size-8px);align-items:start;}
|
|
25
25
|
.cx-cond .w{font-size:var(--cx-size-13px);line-height:var(--cx-control-h);color:var(--cx-muted);text-align:right;}
|
|
26
|
-
.cx-group{border-left:var(--cx-size-2px) solid var(--cx-line-strong);padding:var(--cx-size-8px) 0 var(--cx-size-8px) var(--cx-size-12px);margin-left:var(--cx-size-20px);display:grid;gap:var(--cx-size-8px);}
|
|
26
|
+
.cx-grid-filter-group{border-left:var(--cx-size-2px) solid var(--cx-line-strong);padding:var(--cx-size-8px) 0 var(--cx-size-8px) var(--cx-size-12px);margin-left:var(--cx-size-20px);display:grid;gap:var(--cx-size-8px);}
|
|
27
27
|
.cx-group-h{display:flex;align-items:center;gap:var(--cx-size-8px);font-size:var(--cx-size-13px);color:var(--cx-muted);}
|
|
28
28
|
.cx-adds{display:flex;gap:var(--cx-size-14px);padding-left:var(--cx-size-64px);}
|
|
29
29
|
.cx-grid-overlay.cx-pop{position:fixed;z-index:1000;margin:0;min-height:0;height:auto;padding:0;overflow:auto;display:block;border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);box-shadow:var(--cx-panel-shadow);background:var(--cx-surface);}
|
|
@@ -56,7 +56,6 @@
|
|
|
56
56
|
.cx-fb .cx-seg button{padding:var(--cx-size-3px) var(--cx-size-10px);font-size:var(--cx-size-12d5px);font-weight:700;color:var(--cx-text-2);border:0;background:transparent;text-transform:lowercase;}
|
|
57
57
|
.cx-fb .cx-seg button.on{background:var(--cx-accent-soft);color:var(--cx-accent-text);}
|
|
58
58
|
.cx-column-menu .cx-mi{justify-content:flex-start;gap:var(--cx-size-10px);}
|
|
59
|
-
.cx-grid-overlay :focus-visible{outline:var(--cx-size-2px) solid var(--cx-accent);outline-offset:var(--cx-size-2px);}
|
|
60
59
|
.cx-fb .cx-seg button + button{border-left:var(--cx-size-1px) solid var(--cx-line-strong);}
|
|
61
60
|
.cx-fb .cx-group-h .icon{margin-left:auto;}
|
|
62
61
|
.cx-fb .cx-grid-filter > button.icon{grid-column:5;grid-row:1;padding:0;}
|
|
@@ -95,9 +94,20 @@
|
|
|
95
94
|
.cx-text-dialog pre{padding:var(--cx-size-16px);margin:0;max-height:var(--cx-size-60vh);overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;font:inherit;}
|
|
96
95
|
.cx-text-dialog pre.p-mono{font-family:var(--cx-font-mono);}
|
|
97
96
|
.cx-text-dialog::backdrop{background:color-mix(in srgb,var(--cx-shadow-ink) 35%,transparent);}
|
|
97
|
+
.cx-data-grid .cx-grid-filter-form,.cx-data-grid .cx-grid-filter-form > div,.cx-data-grid .cx-grid-filter{display:flex;flex-direction:column;gap:var(--cx-size-8px);width:100%;min-width:0;}
|
|
98
|
+
.cx-data-grid .cx-grid-filter{border:var(--cx-size-1px) solid var(--cx-line);padding:var(--cx-size-8px);}
|
|
99
|
+
.cx-grid-column-choice{display:flex;align-items:center;border-radius:var(--cx-radius-sm);}
|
|
100
|
+
.cx-grid-column-choice label{flex:1;min-width:0;white-space:nowrap;}
|
|
101
|
+
.cx-grid-column-name{flex:1;overflow:hidden;text-overflow:ellipsis;}
|
|
102
|
+
:is(.cx-grid-column-note,.cx-grid-column-handle){flex:none;padding:0 var(--cx-size-6px);color:var(--cx-muted);font-size:var(--cx-size-12px);white-space:nowrap;}
|
|
103
|
+
.cx-grid-column-handle{height:var(--cx-size-28px);border:0;background:none;cursor:grab;touch-action:none;}
|
|
104
|
+
.cx-grid-column-choice.cx-drop-before{box-shadow:inset 0 var(--cx-size-2px) var(--cx-accent);}
|
|
105
|
+
.cx-grid-column-choice.cx-drop-after{box-shadow:inset 0 var(--cx-size-neg-2px) var(--cx-accent);}
|
|
106
|
+
.cx-grid-column-actions{display:flex;justify-content:space-between;margin-top:var(--cx-size-4px);padding-top:var(--cx-size-4px);border-top:var(--cx-size-1px) solid var(--cx-line);}
|
|
107
|
+
.cx-grid-column-actions .cx-button{border:0;color:var(--cx-accent-text);background:none;}
|
|
98
108
|
.cx-drawer{width:100%;max-width:var(--cx-size-440px);background:var(--cx-surface);border:var(--cx-size-1px) solid var(--cx-line);border-radius:var(--cx-radius);box-shadow:var(--cx-panel-shadow);font:var(--cx-size-14px)/1.45 var(--cx-font);color:var(--cx-text);overflow:hidden;}
|
|
99
109
|
.cx-drawer-h{display:flex;align-items:flex-start;gap:var(--cx-size-12px);padding:var(--cx-size-14px) var(--cx-size-16px);border-bottom:var(--cx-size-1px) solid var(--cx-line);}
|
|
100
|
-
.cx-drawer-h h4{margin:0;font-size:var(--cx-size-17px);}
|
|
110
|
+
.cx-drawer-h h4{margin:0;font-size:var(--cx-size-17px);width:fit-content;}
|
|
101
111
|
.cx-drawer-h p{color:var(--cx-muted);font-size:var(--cx-size-13px);}
|
|
102
112
|
.cx-drawer-h .cx-btn{margin-left:auto;}
|
|
103
113
|
.cx-dl{display:grid;grid-template-columns:var(--cx-size-140px) 1fr;gap:var(--cx-size-8px) var(--cx-size-16px);padding:var(--cx-size-14px) var(--cx-size-16px);margin:0;}
|
|
@@ -117,19 +127,6 @@ body .cx-host.cx-drawer.cx-phone{inset:0;width:100%;max-width:none;height:100%;m
|
|
|
117
127
|
.cx-drawer.cx-phone dd{margin-bottom:var(--cx-size-8px);}
|
|
118
128
|
.cx-drawer.cx-phone .cx-button{min-height:var(--cx-size-44px);min-width:var(--cx-size-44px);}
|
|
119
129
|
.cx-drawer::backdrop{background:color-mix(in srgb,var(--cx-shadow-ink) 35%,transparent);}
|
|
120
|
-
.cx-data-grid .cx-grid-filter-form,.cx-data-grid .cx-grid-filter-form > div,.cx-data-grid .cx-grid-filter{display:flex;flex-direction:column;gap:var(--cx-size-8px);width:100%;min-width:0;}
|
|
121
|
-
.cx-data-grid .cx-grid-filter{border:var(--cx-size-1px) solid var(--cx-line);padding:var(--cx-size-8px);}
|
|
122
130
|
.cx-grid-overlay{color:var(--cx-text);font:var(--cx-font-size)/1.45 var(--cx-font);}
|
|
123
131
|
body .cx-host.cx-grid-overlay{height:auto;min-height:0;padding:0;}
|
|
124
132
|
.cx-grid-overlay [hidden]{display:none!important;}
|
|
125
|
-
.cx-grid-column-choice{display:flex;align-items:center;border-radius:var(--cx-radius-sm);}
|
|
126
|
-
.cx-grid-column-choice:hover{background:var(--cx-hover-bg);}
|
|
127
|
-
.cx-grid-column-choice label{flex:1;min-width:0;white-space:nowrap;}
|
|
128
|
-
.cx-grid-column-name{flex:1;overflow:hidden;text-overflow:ellipsis;}
|
|
129
|
-
:is(.cx-grid-column-note,.cx-grid-column-handle){flex:none;padding:0 var(--cx-size-6px);color:var(--cx-muted);font-size:var(--cx-size-12px);white-space:nowrap;}
|
|
130
|
-
.cx-grid-column-handle{height:var(--cx-size-28px);border:0;background:none;cursor:grab;touch-action:none;}
|
|
131
|
-
.cx-grid-column-choice.cx-drop-before{box-shadow:inset 0 var(--cx-size-2px) var(--cx-accent);}
|
|
132
|
-
.cx-grid-column-choice.cx-drop-after{box-shadow:inset 0 var(--cx-size-neg-2px) var(--cx-accent);}
|
|
133
|
-
.cx-grid-column-find{margin-bottom:var(--cx-size-4px);}
|
|
134
|
-
.cx-grid-column-actions{display:flex;justify-content:space-between;margin-top:var(--cx-size-4px);padding-top:var(--cx-size-4px);border-top:var(--cx-size-1px) solid var(--cx-line);}
|
|
135
|
-
.cx-grid-column-actions .cx-button{border:0;color:var(--cx-accent-text);background:none;}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"99cafeec3da59ffa",install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,gridButton,gridInputLabel,gridOption,gridScalar,gridDateInputMoment,gridQuery,gridQueryStart,GRID_FILTER_LABELS,gridResultShape,gridQueryRows,gridOrder,gridColumnProjection,gridCellRenderer,cellValue,cellText,foldText,reachable,gridMatchesGroup,gridDecorateButton,gridIcon,numberFormat,numberText,fill,announceMenu,reportingRangeRows,applyTone,toneOf,badgeElement,isCellObject,RECORD_IMPL}=context;const buildFilters=DataGrid.prototype.buildGridFilters;function gridOverlayTheme(grid,element){element.setAttribute("data-cx-theme",grid.host.getAttribute("data-cx-theme"));const theme=getComputedStyle(grid.host);element.style.colorScheme=theme.colorScheme;for(const name of theme)if(name.startsWith("--cx-"))element.style.setProperty(name,theme.getPropertyValue(name))}
|
|
2
2
|
function gridRestoreFocus(grid,returnFocus,rowId,column){if(grid.destroyed)return;if(returnFocus?.isConnected&&reachable(returnFocus)){returnFocus.focus({preventScroll:true});return}
|
|
3
3
|
const row=[...grid.rowCache.values()].find(item=>!item.status&&item.key===rowId);const index=grid.visibleColumns().findIndex(item=>item.id===column?.id);if(row&&index>=0)grid.focusCell(row,index,0);else if(row)grid.setFocus(row,true);else grid.grid.focus({preventScroll:true})}
|
|
4
|
-
|
|
4
|
+
const COLUMNS_MENU={moveColumnChoice(column,target,after){column.pin=target.pin;const ids=this.columns.map(item=>item.id).filter(id=>id!==column.id);ids.splice(ids.indexOf(target.id)+ after,0,column.id);this.setColumnOrder(ids)},renderGridColumns(panel){if(!this.columnList){const find=this.columnFind=h("input","cx-grid-column-find"),actions=h("div","cx-grid-column-actions");find.type="search";find.placeholder=this.labels.gridFindColumn;find.setAttribute("aria-label",find.placeholder);find.hidden=this.columns.length<9;find.oninput=()=>this.syncColumnControls();actions.append(gridButton(this.labels.gridShowAllColumns,()=>this.showAllColumns()),gridButton(this.labels.gridResetColumns,()=>this.resetColumns()));panel.replaceChildren(find,this.columnList=h("div"),actions)}
|
|
5
5
|
this.syncColumnControls()},syncColumnControls(){const list=this.columnList,active=document.activeElement,query=foldText(this.columnFind?.value.trim()||"");if(!list)return;const focus=list.contains(active)&&active.closest(".cx-grid-column-choice").dataset.cxColumn,held=focus&&active.matches(".cx-grid-column-handle"),last=this.columns.filter(item=>!item.hidden).length<2;list.textContent="";for(const column of this.columns){const row=h("div","cx-grid-column-choice"),label=h("label"),input=h("input"),name=h("span","cx-grid-column-name"),handle=h("button","cx-grid-column-handle"),note=column.fitHidden||column.responsiveHidden?this.labels.gridResponsiveHidden:column.pin==="left"?this.labels.gridPinnedLeft:column.pin==="right"?this.labels.gridPinnedRight:"";input.type="checkbox";input.checked=!column.hidden;input.disabled=!column.hidden&&last;input.onchange=()=>{input.focus({preventScroll:true});this.setColumnVisible(column.id,input.checked)};setText(name,name.title=column.title);handle.type="button";setText(handle,"⋮⋮");handle.setAttribute("aria-label",fill(this.labels.gridReorderColumn,{column:column.title}));label.append(input,name);row.append(handle,label);row.hidden=!!query&&!foldText(column.title).includes(query);if(note){const span=h("span","cx-grid-column-note");setText(span,note);row.append(span)}
|
|
6
6
|
row.onkeydown=event=>{const target=event.altKey&&this.columns[this.columns.indexOf(column)+(event.key==="ArrowUp"?-1:event.key==="ArrowDown"?1:NaN)];if(target){event.preventDefault();event.stopPropagation();this.moveColumnChoice(column,target,event.key==="ArrowDown")}};handle.onpointerdown=event=>{if(event.button)return;event.preventDefault();handle.focus();handle.setPointerCapture(event.pointerId);let target,after;const clear=()=>{for(const item of list.children)item.classList.remove("cx-drop-before","cx-drop-after")};handle.onpointermove=move=>{clear();const over=document.elementFromPoint(move.clientX,move.clientY)?.closest(".cx-grid-column-choice");target=over!==row&&list.contains(over)&&this.columns[[...list.children].indexOf(over)];if(target){const box=over.getBoundingClientRect();after=move.clientY>box.top+box.height / 2; over.classList.add(after ? "cx-drop-after" : "cx-drop-before"); }
|
|
7
|
-
};handle.onpointerup=handle.onpointercancel=up=>{handle.onpointermove=handle.onpointerup=handle.onpointercancel=null;clear();if(up.type==="pointerup"&&target)this.moveColumnChoice(column,target,after)}};row.dataset.cxColumn=column.id;list.appendChild(row);if(focus===column.id)(held?handle:input).focus({preventScroll:true})}}}
|
|
8
|
-
if(column.kind==="datetime"){
|
|
7
|
+
};handle.onpointerup=handle.onpointercancel=up=>{handle.onpointermove=handle.onpointerup=handle.onpointercancel=null;clear();if(up.type==="pointerup"&&target)this.moveColumnChoice(column,target,after)}};row.dataset.cxColumn=column.id;list.appendChild(row);if(focus===column.id)(held?handle:input).focus({preventScroll:true})}}};function gridFilterValue(grid,column,type,raw){if(column.kind==="number"){if(!raw.trim()||!Number.isFinite(Number(raw)))throw new Error(grid.labels.gridInvalidFilter);return Number(raw)}
|
|
8
|
+
if(column.kind==="datetime"){let text=raw;if(!/(?:Z|[+-]\d\d:\d\d)$/.test(raw)) {
|
|
9
|
+
const moment=gridDateInputMoment(raw,grid.local);if(!moment)throw new Error(grid.labels.gridInvalidFilter);text=grid.local?moment.toISOString():raw+"Z"}
|
|
9
10
|
gridScalar(text,column);return text}
|
|
10
11
|
if(type==="boolean"){if(!["true","false"].includes(raw))throw new Error(grid.labels.gridInvalidFilter);return raw==="true"}
|
|
11
12
|
if(type==="mixed")throw new Error(grid.labels.gridInvalidFilter);return raw}
|
|
12
13
|
function gridMultiSelect(grid,columnOf,typeOf){const box=h("details","cx-ms"),summary=h("summary","cx-input sel"),text=h("span"),list=h("div","cx-ms-list"),search=h("input","cx-input"),values=h("div","cx-val-list"),selected=new Map(),facets=new Map(),key=value=>typeof value+":"+foldText(value),name=value=>cellText(value,columnOf(),grid.fmt);let loaded;search.type="search";search.placeholder=grid.labels.gridFacetSearch;search.setAttribute("aria-label",search.placeholder);summary.appendChild(text);list.append(search,values);box.append(summary,list);const sync=()=>{setText(text,[...selected.values()].map(name).join(", ")||grid.labels.gridFacetChoose);text.classList.toggle("ph",!selected.size)};const render=()=>{const all=new Map(facets);values.replaceChildren();for(const[id,value]of selected)if(!all.has(id))all.set(id,{value});for(const[id,item]of all){const label=h("label","cx-val"),check=h("input"),count=h("span","cx-val-n"),title=name(item.value);check.type="checkbox";check.checked=selected.has(id);if(item.count)setText(count,numberFormat(grid.lang).format(item.count));label.append(check,title,count);label.hidden=!foldText(title).includes(foldText(search.value));values.appendChild(label);check.addEventListener("change",()=>{if(check.checked)selected.set(id,item.value);else selected.delete(id);sync()})}};box.addEventListener("toggle",async()=>{if(box.open&&!loaded){const column=columnOf();loaded=true;try{for(const item of(await grid.columnFacetItems(column,"")).items)if(item.value!=null&&column===columnOf())facets.set(key(item.value),item)}catch(_){}}
|
|
13
14
|
render();if(box.open)list.scrollIntoView({block:"nearest"})});search.addEventListener("input",render);search.addEventListener("keydown",event=>{if(event.key!=="Enter")return;event.preventDefault();try{box._add(gridFilterValue(grid,columnOf(),typeOf(),search.value));search.value="";render();box.dispatchEvent(new Event("change",{bubbles:true}))}catch(_){}});return Object.assign(box,{_values:selected,_sync:sync,_add(value){selected.set(key(value),value);sync()},_reset(){selected.clear();facets.clear();loaded=box.open=false;sync()}})}
|
|
14
|
-
Object.assign(DataGrid.prototype,{addGridFilter(parent,predicate){if(parent.children.length>=64)return;const row=h("fieldset","cx-grid-filter"),column=h("select"),operator=h("select"),type=h("select"),multiple=gridMultiSelect(this,()=>this.columns.find(item=>item.id===column.value),()=>type.value),multipleField=h("div","cx-grid-field cx-condition-value");multipleField.setAttribute("role","group");multipleField.setAttribute("aria-label",this.labels.gridConditionValue);let remove,input=h("input","cx-grid-filter-value"),current;const legend=h("legend","cx-sr-only");setText(legend,this.labels.gridFilters);row.appendChild(legend);for(const item of this.columns)column.appendChild(gridOption(item.id,item.title));if(predicate)column.value=predicate.column;for(const[value,name]of[["string","gridText"],["boolean","gridBoolean"]]){type.appendChild(gridOption(value,this.labels[name]))}
|
|
15
|
+
Object.assign(DataGrid.prototype,{addGridFilter(parent,predicate){if(parent.children.length>=64)return;const row=h("fieldset","cx-grid-filter"),column=h("select"),operator=h("select"),type=h("select"),multiple=gridMultiSelect(this,()=>this.columns.find(item=>item.id===column.value),()=>type.value),multipleField=h("div","cx-grid-field cx-condition-value");multipleField.setAttribute("role","group");multipleField.setAttribute("aria-label",this.labels.gridConditionValue);let remove,input=h("input","cx-grid-filter-value"),current;const legend=h("legend","cx-sr-only");setText(legend,this.labels.gridFilters);row.appendChild(legend);for(const item of this.columns)if(item.filterable!==false)column.appendChild(gridOption(item.id,item.title));if(!column.options.length)return;if(predicate)column.value=predicate.column;for(const[value,name]of[["string","gridText"],["boolean","gridBoolean"]]){type.appendChild(gridOption(value,this.labels[name]))}
|
|
15
16
|
if(predicate&&predicate.values.length&&predicate.values.some(value=>typeof value==="boolean")){if(predicate.values.every(value=>typeof value==="boolean"))type.value="boolean";else{type.appendChild(gridOption("mixed",this.labels.gridText+" / "+this.labels.gridBoolean));type.value="mixed"}}
|
|
16
17
|
const columnField=gridInputLabel(this.labels.gridColumn,column),conditionField=gridInputLabel(this.labels.gridOperator,operator);const typeField=gridInputLabel(this.labels.gridValueType,type),valueField=gridInputLabel(this.labels.gridConditionValue,input);columnField.classList.add("cx-condition-column");conditionField.classList.add("cx-condition-operator");typeField.classList.add("cx-condition-type");valueField.classList.add("cx-condition-value");multipleField.appendChild(multiple);multipleField.hidden=true;row.append(columnField,conditionField,typeField,valueField,multipleField);const change=()=>{const definition=this.columns.find(item=>item.id===column.value),previous=operator.value;const declaredBoolean=definition.presenter?.kind==="boolean";if(declaredBoolean)type.value="boolean";if(current!==column.value){if(current!==undefined)multiple._reset();current=column.value}
|
|
17
18
|
const operators=definition.kind==="text"?["eq","ne","contains","startsWith","in","isNull","isNotNull"]:
|
|
@@ -28,16 +29,16 @@ return!filters.length&&!groups.length?operator==="and":!filters.length&&groups.l
|
|
|
28
29
|
function gridColumnClauses(query,id){const clauses=[],has=group=>group.filters.some(item=>item.column===id)||group.groups.some(has),only=group=>group.filters.every(item=>item.column===id)&&group.groups.every(only);const remove=group=>{if(!group)return undefined;if(only(group)){clauses.push(group);return undefined}
|
|
29
30
|
if(group.operator==="or"&&has(group))throw new Error("complex");const filters=group.filters.filter(item=>{if(item.column!==id)return true;clauses.push(item);return false}),groups=group.groups.map(remove).filter(Boolean);if(!filters.length&&!groups.length)return undefined;return gridColumnGroup(group.operator,[...filters,...groups])};const filters=(query.filters||[]).filter(item=>{if(item.column!==id)return true;clauses.push(item);return false}),filterGroup=remove(query.filterGroup);return{clauses,query:{...query,filters,filterGroup}}}
|
|
30
31
|
function gridInstallColumnClause(query,id,clause){const base=gridColumnClauses(query,id).query;if(!clause)return gridQueryStart(base);if(!clause.groups)return gridQueryStart(base,{filters:[...base.filters,clause]});return gridQueryStart(base,{filterGroup:base.filterGroup?gridColumnGroup("and",[base.filterGroup,clause]):clause})}
|
|
31
|
-
Object.assign(DataGrid.prototype,{columnFacetItems(column,search="",signal){if(this.view.source.kind==="host")return this.getFacets(column.id,{search,includeCurrentFilter:false,limit:200,signal});const query=gridColumnProjection(this.queryForChange(),column.id),columns=new Map(this.view.columns.map(item=>[item.id,item])),rows=gridQueryRows(this.view,query,columns,false),buckets=new Map();for(const row of rows){const value=cellValue(row.cells[column.id])??null,key=typeof value+":"+foldText(value),item=buckets.get(key);if(item)item.count++;else buckets.set(key,{value,count:1})}
|
|
32
|
+
Object.assign(DataGrid.prototype,{columnFacetItems(column,search="",signal){if(!column||column.filterable===false)throw new Error("CanopyX: facets require a filterable column.");if(this.view.source.kind==="host")return this.getFacets(column.id,{search,includeCurrentFilter:false,limit:200,signal});const query=gridColumnProjection(this.queryForChange(false,true),column.id),columns=new Map(this.view.columns.map(item=>[item.id,item])),rows=gridQueryRows(this.view,query,columns,false),buckets=new Map();for(const row of rows){const value=cellValue(row.cells[column.id])??null,key=typeof value+":"+foldText(value),item=buckets.get(key);if(item)item.count++;else buckets.set(key,{value,count:1})}
|
|
32
33
|
const items=[...buckets.values()].filter(item=>foldText(item.value).includes(foldText(search)));items.sort((a,b)=>a.value===null||b.value===null?(a.value===b.value?0:a.value===null?1:-1):
|
|
33
|
-
gridOrder(typeof a.value,typeof b.value)||gridOrder(foldText(a.value),foldText(b.value)));return{items:items.slice(0,200),matched:rows.length,totalValues:items.length,truncated:items.length>200}},openColumnFilter(id,anchor){if(!this.acceptedQuery||this.pendingQuery)return;const column=this.columns.find(item=>item.id===id)
|
|
34
|
+
gridOrder(typeof a.value,typeof b.value)||gridOrder(foldText(a.value),foldText(b.value)));return{items:items.slice(0,200),matched:rows.length,totalValues:items.length,truncated:items.length>200}},openColumnFilter(id,anchor){if(!this.acceptedQuery||this.pendingQuery)return;const column=this.columns.find(item=>item.id===id);if(!column||column.filterable===false)throw new Error("CanopyX: column filters require a filterable column.");const panel=this.openGridPopover(anchor,"cx-column-filter",column.title+": "+this.labels.gridFilterColumn,id);const head=h("div","cx-pop-h"),body=h("div","cx-pop-b"),footer=h("div","cx-pop-f"),error=h("p","cx-grid-control-error");setText(head,column.title);error.setAttribute("role","status");panel.append(head,body,error,footer);let timer,clauses,draft;const signal=this.gridPopover.controller.signal,filters=this.reportingFilters;const complex=()=>{setText(body,this.labels.gridComplexFilter);if(filters)body.appendChild(gridButton(this.labels.gridEditAsText,()=>{this.closeGridPopover(false);filters.details.open=true}))};try{({clauses}=gridColumnClauses(this.queryForChange(),id))}catch(_){complex();return}
|
|
34
35
|
const flush=()=>{clearTimeout(timer);timer=null;if(signal.aborted||draft===undefined)return;try{const promise=this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,draft));draft=undefined;this.reportingFilterSubmitEpoch=this.queryEpoch;promise.then(()=>setText(error,""),failure=>setText(error,failure.message))}catch(failure){setText(error,failure.message)}};const apply=clause=>{draft=clause??null;clearTimeout(timer);timer=setTimeout(flush,200)};apply.cancel=()=>{clearTimeout(timer);draft=undefined};signal.addEventListener("abort",()=>clearTimeout(timer),{once:true});footer.append(gridButton(this.labels.gridClearColumnFilter,()=>{clearTimeout(timer);this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,null)).catch(failure=>this.emit("error",{error:failure}));this.closeGridPopover()}),gridButton(this.labels.gridDone,()=>{flush();this.closeGridPopover()}));const faceted=column.kind==="text"&&(this.view.source.kind==="inline"||this.view.reporting?.facetColumns?.includes(id)&&typeof this.source.facet==="function");if(!faceted&&clauses.some(item=>item.groups&&(item.groups.length||item.filters.length>2))||!faceted&&clauses.length>2)complex();else if(faceted)this.renderColumnValues(column,body,clauses,apply,error,signal);else this.renderColumnConditions(column,body,clauses,apply,error);this.gridPopover.position()},renderColumnValues(column,body,clauses,apply,error,signal){const search=h("input","cx-input"),all=h("input"),list=h("div","cx-val-list"),status=h("p","cx-muted");search.type="search";search.setAttribute("aria-label",this.labels.gridFilterValues);search.placeholder=this.labels.gridFilterValues;all.type="checkbox";all.checked=!clauses.length;const allLabel=h("label","cx-val-all"),allCount=h("span","cx-val-n");allCount.setAttribute("aria-hidden","true");allLabel.append(all,this.labels.gridSelectAllValues,allCount);body.append(search,allLabel,list,status);const criteria=()=>JSON.stringify([gridResultShape(gridColumnProjection(this.getQuery(),column.id)),this.snapshot.revision]),originalCriteria=criteria();this.host.addEventListener("canopyx:query",()=>{if(criteria()!==originalCriteria)this.closeGridPopover(false)},{signal});let baseline=gridColumnGroup("and",clauses),items=[],selected=new Map(),request=0,facetController;signal.addEventListener("abort",()=>facetController?.abort(),{once:true});const key=value=>typeof value+":"+foldText(value),columns=new Map([[column.id,column]]),matchesClause=(value,clause)=>typeof clause==="boolean"?clause:gridMatchesGroup({cells:{[column.id]:value}},clause,columns),predicate=(operator,values=[])=>({column:column.id,operator,values}),matches=value=>matchesClause(value,baseline),chosen=value=>selected.get(key(value))?.checked??matches(value);const syncAll=()=>{all.checked=items.length>0&&items.every(item=>chosen(item.value));all.indeterminate=!all.checked&&items.some(item=>chosen(item.value))};const commit=()=>{const withoutEdited=clause=>{if(clause.groups)return gridColumnGroup(clause.operator,[...clause.filters,...clause.groups].map(withoutEdited));if(clause.operator==="in"){const values=clause.values.filter(value=>!selected.has(key(value)));return values.length?{...clause,values}:false}
|
|
35
36
|
if(["eq","ne","isNull","isNotNull"].includes(clause.operator)&&selected.has(key(clause.values[0]??null)))return["ne","isNotNull"].includes(clause.operator);return clause};let clause=typeof baseline==="boolean"?baseline:withoutEdited(baseline);const included=[],excluded=[];for(const item of selected.values())if(item.checked!==matchesClause(item.value,clause))(item.checked?included:excluded).push(item.value);clause=gridColumnGroup("and",[clause,...excluded.map(value=>predicate(value==null?"isNotNull":"ne",value==null?[]:[value]))]);const additions=[],raw=included.filter(value=>value!=null);if(raw.length<included.length)additions.push(predicate("isNull"));if(raw.length)additions.push(predicate("in",raw));clause=gridColumnGroup("or",[clause,...additions]);apply(clause===true?undefined:clause===false?gridColumnGroup("and",[predicate("isNull"),predicate("isNotNull")]):clause)};const render=()=>{list.replaceChildren();for(const item of items){const label=h("label","cx-val"),check=h("input"),value=h("span","cx-facet-value"),count=h("span","cx-val-n");check.type="checkbox";check.checked=chosen(item.value);const options=column.presenter;if(options&&!['statusStrip','sparklineBars','sparklineLine','change','identifier','longText','list','tags'].includes(options.kind))gridCellRenderer(this,column,options)({id:"facet",cells:{[column.id]:item.value}},value);else setText(value,cellText(item.value,column,this.fmt)||"—");setText(count,numberFormat(this.lang).format(item.count));label.append(check,value,count);list.appendChild(label);check.addEventListener("change",()=>{if(check.checked===matches(item.value))selected.delete(key(item.value));else selected.set(key(item.value),{value:item.value,checked:check.checked});syncAll();commit()})}
|
|
36
37
|
syncAll()};const load=async()=>{const generation=++request;facetController?.abort();facetController=new AbortController();setText(status,this.labels.loading);try{const page=await this.columnFacetItems(column,search.value,facetController.signal);if(signal.aborted||generation!==request)return;const previous=new Map(items.map(item=>[key(item.value),item]));for(const item of page.items)previous.set(key(item.value),item);items=[...previous.values()];render();for(const row of list.children)row.hidden=!foldText(row.querySelector('.cx-facet-value').textContent).includes(foldText(search.value));if(!search.value){search.hidden=page.totalValues<=12;setText(allCount,numberFormat(this.lang).format(page.totalValues))}
|
|
37
|
-
setText(status,page.truncated?fill(this.labels.gridFacetCounts,{count:page.matched,shown:page.items.length,total:page.totalValues}):"");this.gridPopover?.position()}catch(failure){if(!signal.aborted&&generation===request&&failure.name!=="AbortError")setText(error,failure.message)}};all.addEventListener("change",()=>{baseline=all.checked;selected.clear();render();commit()});search.addEventListener("input",load);load()}});function gridDateInput(value,local){const date=new Date(value);return Number.isFinite(date.getTime())?new Date(date.getTime()-(local?date.getTimezoneOffset()*60000:0)).toISOString().slice(0
|
|
38
|
+
setText(status,page.truncated?fill(this.labels.gridFacetCounts,{count:page.matched,shown:page.items.length,total:page.totalValues}):"");this.gridPopover?.position()}catch(failure){if(!signal.aborted&&generation===request&&failure.name!=="AbortError")setText(error,failure.message)}};all.addEventListener("change",()=>{baseline=all.checked;selected.clear();render();commit()});search.addEventListener("input",load);load()}});function gridDateInput(value,local){const date=new Date(value);return Number.isFinite(date.getTime())?new Date(date.getTime()-(local?date.getTimezoneOffset()*60000:0)).toISOString().slice(0,-1):""}
|
|
38
39
|
const GRID_DATE_PRESETS=[["today","gridToday"],["yesterday","gridYesterday"],["last7","gridLastSevenDays"],["last30","gridLastThirtyDays"],["month","gridThisMonth"]];function gridDatePreset(local,preset){const start=new Date(),end=new Date(),zone=local?"":"UTC",get=(date,part)=>date["get"+zone+part](),set=(date,part,...values)=>date["set"+zone+part](...values),shift=(date,days)=>set(date,"Date",get(date,"Date")+days);set(start,"Hours",0,0,0,0);set(end,"Hours",0,0,0,0);shift(end,1);if(preset==="yesterday"){shift(start,-1);shift(end,-1)}else if(preset==="last7")shift(start,-6);else if(preset==="last30")shift(start,-29);else if(preset==="month"){set(start,"Date",1);end.setTime(start.getTime());set(end,"Month",get(end,"Month")+1,1)}
|
|
39
40
|
return[start.toISOString(),end.toISOString()]}
|
|
40
|
-
DataGrid.prototype.renderColumnConditions=function(column,body,clauses,apply,error){const rows=h("div","cx-column-conditions"),join=h("select","cx-input"),date=column.kind==="datetime",text=column.kind==="text";join.append(gridOption("and",this.labels.gridAnd),gridOption("or",this.labels.gridOr));join.setAttribute("aria-label",this.labels.gridFilterMatch||this.labels.gridOperator);join.hidden=true;const filters=clauses.flatMap(item=>item.groups?item.filters:item),original=clauses.find(item=>item.groups);if(original)join.value=original.operator;let preset;const read=()=>{const predicates=[...rows.children].map(row=>{const{operator,input,original}=row._condition;if(["isNull","isNotNull"].includes(operator.value))return{column:column.id,operator:operator.value,values:[]};if(original&&input.value===original.input&&operator.value===original.filter.operator)return original.filter;const
|
|
41
|
+
DataGrid.prototype.renderColumnConditions=function(column,body,clauses,apply,error){const rows=h("div","cx-column-conditions"),join=h("select","cx-input"),date=column.kind==="datetime",text=column.kind==="text";join.append(gridOption("and",this.labels.gridAnd),gridOption("or",this.labels.gridOr));join.setAttribute("aria-label",this.labels.gridFilterMatch||this.labels.gridOperator);join.hidden=true;const filters=clauses.flatMap(item=>item.groups?item.filters:item),original=clauses.find(item=>item.groups);if(original)join.value=original.operator;let preset;const read=()=>{const predicates=[...rows.children].map(row=>{const{operator,input,original}=row._condition;if(["isNull","isNotNull"].includes(operator.value))return{column:column.id,operator:operator.value,values:[]};if(original&&input.value===original.input&&operator.value===original.filter.operator)return original.filter;const moment=date?gridDateInputMoment(input.value,this.local):null;if(date&&!moment)throw new Error(this.labels.gridInvalidFilter);const value=column.kind==="number"?Number(input.value):date?moment.toISOString():input.value;if(column.kind==="number"&&!input.value.trim())throw new Error(this.labels.gridInvalidFilter);gridScalar(value,column);return{column:column.id,operator:operator.value,values:[value]}});return predicates.length===1?predicates[0]:{operator:join.value,filters:predicates,groups:[]}};const update=()=>{apply.cancel();try{apply(read());setText(error,"");if(preset)preset.value="range"}catch(failure){setText(error,this.labels.gridInvalidFilter)}};const add=filter=>{if(rows.children.length>=2)return;const row=h("div","cx-column-condition"),operator=h("select","cx-input"),input=h("input","cx-input");for(const value of text?["contains","eq","ne","startsWith","isNull","isNotNull"]:["eq","ne","gt","ge","lt","le","isNull","isNotNull"])operator.appendChild(gridOption(value,this.labels[GRID_FILTER_LABELS[value]]||GRID_FILTER_LABELS[value]));operator.setAttribute("aria-label",this.labels.gridOperator);input.setAttribute("aria-label",this.labels.gridConditionValue);input.type=date?"datetime-local":text?"text":"number";if(!text)input.step="any";if(filter){operator.value=filter.operator;input.value=date?gridDateInput(filter.values[0],this.local):String(filter.values[0]??"")}
|
|
41
42
|
input.disabled=["isNull","isNotNull"].includes(operator.value);row._condition={operator,input,original:filter?{filter,input:input.value}:null};row.append(operator,input);if(rows.children.length){const remove=gridDecorateButton(gridButton("",()=>{row.remove();join.hidden=true;addButton.hidden=false;update()}),"close",true);remove.setAttribute("aria-label",this.labels.gridDeleteCondition);row.appendChild(remove);rows.appendChild(row)}else rows.appendChild(row);input.addEventListener("input",update);operator.addEventListener("change",()=>{input.disabled=["isNull","isNotNull"].includes(operator.value);update()})};if(date){preset=h("select","cx-input");preset.setAttribute("aria-label",this.labels.gridDateRange);for(const[value,label]of[["range","gridDateRange"],...GRID_DATE_PRESETS])preset.appendChild(gridOption(value,this.labels[label]));preset.addEventListener("change",()=>{if(preset.value==="range")return;const[start,end]=gridDatePreset(this.local,preset.value);rows.replaceChildren();add({column:column.id,operator:"ge",values:[start]});add({column:column.id,operator:"lt",values:[end]});join.value="and";join.hidden=false;addButton.hidden=true;apply(read())});body.appendChild(preset)}
|
|
42
43
|
const addButton=gridButton(this.labels.gridAddCondition,()=>{add(null);join.hidden=false;addButton.hidden=true;rows.lastElementChild.querySelector('input').focus()});addButton.classList.add("cx-link");add(filters[0]);if(filters[1]){add(filters[1]);join.hidden=false;addButton.hidden=true}
|
|
43
44
|
join.addEventListener("change",update);body.append(rows,join,addButton);if(date){const zone=h("p","cx-muted");setText(zone,new Intl.DateTimeFormat(this.lang,{timeZone:this.local?undefined:"UTC"}).resolvedOptions().timeZone);body.appendChild(zone)}};const FILTER_SUMMARY=DataGrid.prototype.syncQuerySummary;DataGrid.prototype.syncQuerySummary=function(){FILTER_SUMMARY.call(this);const controls=this.reportingFilters,query=this.getQuery(),shape=JSON.stringify([query?.filters||[],query?.filterGroup||null]);if(!controls?.details.open||shape===this.reportingFilterDraftBase)return;if(this.reportingFilterSubmitEpoch===this.queryEpoch)this.reportingFilterDraftBase=shape;else{const hadFocus=controls.panel.contains(document.activeElement);controls.details.open=false;if(hadFocus)controls.details.querySelector("summary").focus({preventScroll:true})}};function gridFilterDepth(group){return group?1+Math.max(0,...group.groups.map(gridFilterDepth)):0}
|
|
@@ -45,17 +46,22 @@ function gridFilterSegment(grid,initial,onChange){const segment=h("div","cx-seg"
|
|
|
45
46
|
function sync(){for(const button of buttons){button.setAttribute("aria-pressed",String(button.dataset.cxJoin===segment._operator));button.classList.toggle("on",button.dataset.cxJoin===segment._operator)}}
|
|
46
47
|
sync();return segment}
|
|
47
48
|
DataGrid.prototype.renderGridFilters=function(panel){panel.replaceChildren();panel.classList.add("cx-fb");this.reportingFilterDraftBase=JSON.stringify([this.queryForChange().filters||[],this.queryForChange().filterGroup||null]);const form=h("form","cx-grid-filter-form cx-fb"),head=h("div","cx-pop-h"),body=h("div","cx-pop-b"),footer=h("div","cx-pop-f"),error=h("p","cx-grid-control-error");setText(head,this.labels.gridFilters);error.setAttribute("role","status");panel.append(head,form);form.append(body,error,footer);panel._filterLifetime?.abort();const controller=panel._filterLifetime=new AbortController();let timer,editingText=false,text,draft;const flush=()=>{clearTimeout(timer);timer=null;if(!draft||!panel.isConnected||!panel.parentElement.open||this.destroyed)return;const query=draft;draft=null;try{const validated=gridQuery(this.view,query);if(gridResultShape(validated)===gridResultShape(this.queryForChange()))return;const promise=this.setQuery(validated);this.reportingFilterSubmitEpoch=this.queryEpoch;promise.then(()=>setText(error,""),failure=>setText(error,failure.message))}catch(failure){setText(error,this.labels.gridInvalidFilter)}};const apply=query=>{draft=query;clearTimeout(timer);timer=setTimeout(flush,200)};controller.signal.addEventListener("abort",()=>clearTimeout(timer),{once:true});this.lifetime.signal.addEventListener("abort",()=>controller.abort(),{once:true,signal:controller.signal});document.addEventListener("click",event=>{for(const box of form.querySelectorAll(".cx-ms[open]"))if(!box.contains(event.target))box.open=false},{signal:controller.signal});form.addEventListener("keydown",event=>{const box=event.target.closest(".cx-ms[open]");if(event.key==="Escape"&&box){box.open=false;box.firstChild.focus();event.stopPropagation()}});panel.parentElement.addEventListener("toggle",()=>{if(!panel.parentElement.open)controller.abort()},{signal:controller.signal});const close=()=>{clearTimeout(timer);panel.parentElement.open=false;panel.parentElement.querySelector("summary").focus()};footer.append(gridButton(this.labels.gridClearFilters,()=>{clearTimeout(timer);this.setQuery(gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:undefined})).catch(failure=>setText(error,failure.message));this.renderGridFilters(panel)}),gridButton(this.labels.gridDone,()=>{draft=gridQueryStart(draft||this.queryForChange(),{search:this.queryForChange(true).search});flush();close()}));if(gridFilterDepth(this.queryForChange().filterGroup)>2){const notice=h("p");setText(notice,this.labels.gridDeepFilters);text=h("textarea","cx-filter-text");text.setAttribute("aria-label",this.labels.gridFilterText);text.readOnly=true;text.value=JSON.stringify({filters:this.queryForChange().filters||[],filterGroup:this.queryForChange().filterGroup},null,2);const edit=gridButton(this.labels.gridEditAsText,()=>{editingText=true;text.readOnly=false;text.focus()});body.append(notice,text,edit);text.addEventListener("input",()=>{try{const value=JSON.parse(text.value);apply(gridQueryStart(this.queryForChange(true),{filters:value.filters||[],filterGroup:value.filterGroup}))}catch(_){clearTimeout(timer);draft=null;setText(error,this.labels.gridInvalidFilter)}});return}
|
|
48
|
-
const update=()=>{try{syncWords(root);apply(readQuery());setText(error,"")}catch(_){clearTimeout(timer);draft=null;setText(error,this.labels.gridInvalidFilter)}};const makeGroup=(parent,definition,depth)=>{const block=h("div",depth?"cx-
|
|
49
|
+
const update=()=>{try{syncWords(root);apply(readQuery());setText(error,"")}catch(_){clearTimeout(timer);draft=null;setText(error,this.labels.gridInvalidFilter)}};const makeGroup=(parent,definition,depth)=>{const block=h("div",depth?"cx-grid-filter-group":"cx-filter-root"),heading=h("div","cx-group-h"),rows=h("div","cx-condition-rows"),children=h("div","cx-grid-filter-group-children"),actions=h("div","cx-adds");const segment=gridFilterSegment(this,definition?.operator||"and",update);if(!depth)heading.append(document.createTextNode(this.labels.gridShowRowsWhere+" "));heading.append(segment,document.createTextNode(" "+(depth?this.labels.gridOfThese:this.labels.gridOfTheseAreTrue)));block._group={segment,rows,children};block.append(heading,rows,children,actions);parent.appendChild(block);const add=predicate=>{if(form.querySelectorAll('.cx-grid-filter').length>=64)return;this.addGridFilter(rows,predicate);const row=rows.lastElementChild;if(!row)return;row._design=true;row.classList.add("cx-cond");row._filter.type.closest("label").hidden=row._filter.type.value==="string";const word=h("span","w");row.prepend(word);const typeLabel=row._filter.type.closest('label');if(this.columns.find(column=>column.id===row._filter.column.value)?.presenter?.kind==="boolean"){row._filter.type.value="boolean";row._filter.type.dispatchEvent(new Event("change"));typeLabel.hidden=true}
|
|
49
50
|
const remove=row.querySelector(':scope > button');if(remove){remove.replaceChildren(gridIcon("close"));remove.classList.add("icon");remove.setAttribute("aria-label",this.labels.gridDeleteCondition);remove.addEventListener("click",update)}
|
|
50
51
|
syncWords(block);return row};const condition=gridButton(this.labels.gridAddCondition,()=>{const row=add(null);row?._filter.column.focus()});condition.classList.add("cx-link");const group=gridButton(this.labels.gridAddGroup,()=>{makeGroup(children,null,depth+1);syncWords(block)});group.classList.add("cx-link");group.disabled=depth>=2;actions.append(condition,group);if(depth){const remove=gridDecorateButton(gridButton("",()=>{const target=parent.parentElement.querySelector(":scope > .cx-adds > button");block.remove();update();target?.focus()}),"close",true);remove.classList.add("icon");remove.setAttribute("aria-label",this.labels.gridDeleteFilterGroup);heading.appendChild(remove)}
|
|
51
52
|
const predicates=definition?.filters||[];(this.view.reporting&&reportingRangeRows&&definition?.operator==="and"?reportingRangeRows(predicates):predicates).forEach(add);(definition?.groups||[]).forEach(child=>makeGroup(children,child,depth+1));return block};const syncWords=block=>{const data=block._group;[...data.rows.children].forEach((row,index)=>setText(row.querySelector('.w'),index===0?this.labels.gridWhere:data.segment._operator==="and"?this.labels.gridAnd:this.labels.gridOr));for(const child of data.children.children)syncWords(child)};const readBlock=block=>{const{segment,rows,children}=block._group,filters=[],groups=[...children.children].map(readBlock).filter(Boolean);for(const row of rows.children){if(!row._filter.original&&!row._filter.edited)continue;const predicates=[].concat(this.readGridFilter(row));if(segment._operator==="or"&&predicates.length>1)groups.push({operator:"and",filters:predicates,groups:[]});else filters.push(...predicates)}
|
|
52
53
|
return filters.length||groups.length?{operator:segment._operator,filters,groups}:null};const readQuery=()=>{if(editingText){const value=JSON.parse(text.value);return gridQueryStart(this.queryForChange(true),{filters:value.filters||[],filterGroup:value.filterGroup})}
|
|
53
54
|
const value=readBlock(root);if(!value)return gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:undefined});if(value.operator==="or")return gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:value});return gridQueryStart(this.queryForChange(true),{filters:value.filters,filterGroup:value.groups.length===1?value.groups[0]:value.groups.length?{operator:"and",filters:[],groups:value.groups}:undefined})};const root=makeGroup(body,{operator:"and",filters:this.queryForChange().filters||[],groups:this.queryForChange().filterGroup?[this.queryForChange().filterGroup]:[]},0);syncWords(root);form.addEventListener("input",update);form.addEventListener("change",update);form.addEventListener("submit",event=>{event.preventDefault();update()})};function gridMenuFocus(panel,event){const items=[...panel.querySelectorAll('[role="menuitem"]')].filter(item=>!item.disabled),index=items.indexOf(document.activeElement);if(!items.length)return;let next;if(["ArrowDown","ArrowUp","Home","End"].includes(event.key))next=event.key==="Home"?0:event.key==="End"?items.length-1:(index+(event.key==="ArrowDown"?1:-1)+items.length)%items.length;else if(event.key.length===1&&!event.ctrlKey&&!event.metaKey&&!event.altKey){const now=performance.now();panel._typeAhead=now-(panel._typeAt||0)>700?event.key:panel._typeAhead+event.key;panel._typeAt=now;const matches=items.map((_,i)=>(index+i+1)%items.length);next=matches.find(i=>foldText(items[i].textContent.trim()).startsWith(foldText(panel._typeAhead)))}else return;if(next===undefined)return;event.preventDefault();items.forEach((item,i)=>item.tabIndex=i===next?0:-1);items[next].focus({preventScroll:true})}
|
|
54
|
-
Object.assign(DataGrid.prototype,{openGridPopover(anchor,className,title,columnId){this.closeGridPopover(false);const panel=h("div","cx-host cx-grid-overlay cx-pop "+className),controller=new AbortController(),signal=controller.signal;gridOverlayTheme(this,panel);panel.setAttribute("role","dialog");panel.setAttribute("aria-label",title);panel.tabIndex=-1;panel.id=this.id+"-popover";anchor.setAttribute("aria-controls",panel.id);anchor.setAttribute("aria-expanded","true");document.body.appendChild(panel);const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if(
|
|
55
|
+
Object.assign(DataGrid.prototype,{openGridPopover(anchor,className,title,columnId){this.closeGridPopover(false);const panel=h("div","cx-host cx-grid-overlay cx-pop "+className),controller=new AbortController(),signal=controller.signal;gridOverlayTheme(this,panel);panel.setAttribute("role","dialog");panel.setAttribute("aria-label",title);panel.tabIndex=-1;panel.id=this.id+"-popover";anchor.setAttribute("aria-controls",panel.id);anchor.setAttribute("aria-expanded","true");document.body.appendChild(panel);announceMenu(panel);const pressed=new Set();let positionPending=false,releaseFrame=0;const position=()=>{if(signal.aborted)return;if(pressed.size||releaseFrame){positionPending=true;return}
|
|
56
|
+
positionPending=false;const current=this.headCells.find(cell=>cell.dataset.cxColumn===columnId)||anchor,bounds=current.getBoundingClientRect();if(panel.classList.toggle("cx-phone",this.host.clientWidth<=640)){panel.style.left="0";panel.style.top="auto";panel.style.bottom="0";panel.style.width="100%";panel.style.maxHeight="80vh"}
|
|
57
|
+
else{panel.style.width="";panel.style.bottom="auto";panel.style.maxHeight=Math.min(500,global.innerHeight-16)+"px";panel.style.left=Math.max(8,Math.min(bounds.left,global.innerWidth-panel.offsetWidth-8))+"px";panel.style.top=Math.max(8,Math.min(bounds.bottom,global.innerHeight-panel.offsetHeight-8))+"px"}};this.gridPopover={panel,controller,anchor,columnId,position};panel.addEventListener("pointerdown",event=>pressed.add(event.pointerId),{signal});const release=event=>{if(!pressed.delete(event.pointerId))return;if(!releaseFrame)releaseFrame=global.requestAnimationFrame(()=>{releaseFrame=0;if(positionPending)position()})};for(const type of["pointerup","pointercancel"])global.addEventListener(type,release,{capture:true,signal});global.addEventListener("resize",position,{signal});global.addEventListener("scroll",position,{capture:true,signal});panel.addEventListener("keydown",event=>{if(event.key==="Escape"){event.preventDefault();event.stopPropagation();this.closeGridPopover()}else gridMenuFocus(panel,event)},{signal});this.lifetime.signal.addEventListener("abort",()=>controller.abort(),{once:true,signal});signal.addEventListener("abort",()=>{global.cancelAnimationFrame(releaseFrame);pressed.clear();panel.remove()},{once:true});queueMicrotask(position);return panel},openColumnMenu(id,anchor){const column=this.columns.find(item=>item.id===id),panel=this.openGridPopover(anchor,"cx-column-menu",fill(this.labels.gridColumnMenu,{column:column.title}),id);const menu=h("div");menu.setAttribute("role","menu");menu.setAttribute("aria-label",panel.getAttribute("aria-label"));panel.appendChild(menu);const icons=new Map([[this.labels.gridSortAscending,"up"],[this.labels.gridSortDescending,"down"],[this.labels.gridFilterColumn,"filter"],[this.labels.gridPinLeft,"pin"],[this.labels.gridPinRight,"pin"],[this.labels.gridFitContent,"fit"],[this.labels.gridHideColumn,"hide"]]);const paths={pin:'<path d="M9 4h6l-1 6 3 3H7l3-3zM12 13v7"/>',fit:'<path d="M4 12h16M7 9l-3 3 3 3M17 9l3 3-3 3M4 5v14M20 5v14"/>',hide:'<path d="M3 3l18 18M10.6 6.1A9.8 9.8 0 0 1 12 6c5 0 8.5 4.5 9 6-.3.8-1.2 2.3-2.6 3.6M6.4 7.6C4.6 8.9 3.4 10.8 3 12c.5 1.5 4 6 9 6 1.6 0 3-.4 4.3-1.1"/>'};const add=(label,action,disabled=false)=>{const button=gridButton(label,()=>{this.closeGridPopover(false);Promise.resolve().then(action).catch(error=>this.emit("error",{error}))});const icon=h("span","ico"),name=icons.get(label);if(name){icon.appendChild(gridIcon(name,paths[name]))}button.prepend(icon);button.classList.add("cx-mi");button.setAttribute("role","menuitem");button.tabIndex=-1;button.disabled=disabled;menu.appendChild(button)};const sort=direction=>this.setQuery(gridQueryStart(this.queryForChange(true),{sort:[...(this.queryForChange().sort||[]).filter(item=>item.column!==id),...direction?[{column:id,direction}]:[]]}));add(this.labels.gridSortAscending,()=>sort("asc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridSortDescending,()=>sort("desc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridClearSort,()=>sort(null),!(this.getQuery()?.sort||[]).some(item=>item.column===id));menu.appendChild(h("hr","cx-menu-rule"));add(this.labels.gridFilterColumn,()=>this.openColumnFilter(id,this.headRow.querySelector('[data-cx-column-menu="'+CSS.escape(id)+'"]')),column.filterable===false);menu.appendChild(h("hr","cx-menu-rule"));for(const[pin,label]of[["left","gridPinLeft"],["right","gridPinRight"],["none","gridUnpin"]])add(this.labels[label],()=>this.setColumnPinned(id,pin));menu.appendChild(h("hr","cx-menu-rule"));add(this.labels.gridFitContent,()=>this.autoFitColumn(id),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridFitAllColumns,()=>this.autoFitColumns(),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridHideColumn,()=>this.setColumnVisible(id,false),this.columns.filter(item=>!item.hidden).length===1);const first=panel.querySelector('[role="menuitem"]:not(:disabled)');if(first){first.tabIndex=0;first.focus()}}});let activeRecordDrawer;DataGrid.prototype.openGridDrawer=function(record,index,returnFocus,options){if(activeRecordDrawer?.contains(returnFocus))returnFocus=activeRecordDrawer._returnFocus;if(activeRecordDrawer){activeRecordDrawer._replaced=true;activeRecordDrawer.close();activeRecordDrawer.remove()}
|
|
58
|
+
const dialog=h("dialog","cx-host cx-grid-overlay cx-drawer"),head=h("div","cx-drawer-h"),identity=h("div"),title=h("h4"),subtitle=h("p"),body=h("div","cx-drawer-body");dialog._returnFocus=returnFocus;gridOverlayTheme(this,dialog);title.id=this.id+"-record-title";title.tabIndex=-1;title.setAttribute("aria-level","2");dialog.setAttribute("aria-labelledby",title.id);const previous=gridDecorateButton(gridButton("",()=>navigate(-1)),"up",true),next=gridDecorateButton(gridButton("",()=>navigate(1)),"down",true),close=gridDecorateButton(gridButton("",()=>dialog.close()),"close",true);previous.setAttribute("aria-label",this.labels.gridPreviousRecord);next.setAttribute("aria-label",this.labels.gridNextRecord);close.setAttribute("aria-label",this.labels.gridCloseRecord);for(const button of[previous,next,close])button.classList.add("icon");identity.append(title,subtitle);head.append(identity,previous,next,close);dialog.append(head,body);document.body.appendChild(dialog);activeRecordDrawer=dialog;this.recordDrawer=dialog;DataGrid.activeDrawers.set(dialog,this);const primary=this.visibleColumns()[0],shape=gridResultShape(this.acceptedQuery),owner=this.dataLifetime;let retiredForNavigation=false,paints=null;const placed=()=>Number.isInteger(index);const steps=()=>{previous.disabled=!placed()||index<=0||this.cursor&&index<=this.rowBounds().first;next.disabled=!placed()||index>=this.rowCount()-1};const paint=(row,position)=>{record=row;index=position;paints?.abort();paints=new AbortController();setText(title,cellText(row.cells[primary.id],primary,this.fmt)||row.id);const options=primary.presenter;const secondary=row.cells[primary.id]?.secondary||options?.secondaryColumn&&cellText(row.cells[options.secondaryColumn],this.columns.find(column=>column.id===options.secondaryColumn),this.fmt)||"";setText(subtitle,secondary);subtitle.hidden=!secondary;dialog._cxRecord=row;dialog._cxIndex=index;dialog.setAttribute("data-cx-record",row.id);dialog.setAttribute("data-cx-view",this.view.id);steps();this.paintDrawerBody(row,body,dialog,{index,signal:paints.signal});dialog.dispatchEvent(new CustomEvent("cx-drawer-paint",{detail:{id:row.id,index}}))};const navigate=async direction=>{const position=index+direction;if(!placed()||position<0||position>=this.rowCount()||this.pendingQuery)return;dialog._navigating=true;previous.disabled=next.disabled=true;try{await this.focusResult(position,false);if(this.destroyed||this.pendingQuery||gridResultShape(this.acceptedQuery)!==shape)return;const row=this.rowCache.get(position);if(!row)return;if(dialog.isConnected){paint(row.h,position);this.focusRing(title)}else if(retiredForNavigation)await this.openDetails(row.key)}catch(error){if(error.name!=="AbortError")this.emit("error",{error})}
|
|
59
|
+
finally{dialog._navigating=false;if(dialog.isConnected)steps()}};dialog._cxPaint=paint;dialog.addEventListener("keydown",event=>{if(event.key==="Escape"&&!event.defaultPrevented){event.preventDefault();dialog.close()}
|
|
60
|
+
else if(["ArrowUp","ArrowDown"].includes(event.key)&&!event.defaultPrevented&&!event.target.matches('input,textarea,select,[contenteditable],[role=tab]')&&!event.target.closest(".cx-record-nested")){event.preventDefault();navigate(event.key==="ArrowUp"?-1:1)}});const abort=()=>{retiredForNavigation=dialog._navigating;dialog.close()};owner.signal.addEventListener("abort",abort,{once:true});const refreshHooks=()=>DataGrid.refreshDrawerHooks(this,dialog);this.host.addEventListener("canopyx:format",refreshHooks);dialog.addEventListener("close",()=>{owner.signal.removeEventListener("abort",abort);this.host.removeEventListener("canopyx:format",refreshHooks);DataGrid.activeDrawers.delete(dialog);cancelAnimationFrame(dialog._cxHooksFrame);paints?.abort();dialog.remove();if(activeRecordDrawer===dialog)activeRecordDrawer=null;if(this.recordDrawer===dialog)this.recordDrawer=null;if(!this.recordDrawer&&!dialog._navigating&&!dialog._replaced&&!this.destroyed)gridRestoreFocus(this,returnFocus,record.id,primary)},{once:true});RECORD_IMPL.decorate?.(this,dialog,{head,identity,title,subtitle,body,options:options||{}});DataGrid.applyDrawerHooks(this,dialog);paint(record,index);const phone=this.host.clientWidth<=640;dialog.classList.toggle("cx-phone",phone);if(phone)dialog.showModal();else dialog.show();this.focusRing(title);return dialog};Object.assign(DataGrid.prototype,{paintDrawerBody(row,body,dialog,context){if(RECORD_IMPL.paint&&this.recordNeeded(row))return RECORD_IMPL.paint(this,row,body,dialog,context);body.replaceChildren();const sections=new Map();for(const column of this.columns){if(column.drawer===false)continue;const name=column.section||this.labels.gridDetailsSection;if(!sections.has(name)){const heading=h("div","cx-drawer-s"),list=h("dl","cx-dl");setText(heading,name);sections.set(name,list);body.append(heading,list)}
|
|
61
|
+
const label=h("dt"),value=h("dd");setText(label,column.title);label.setAttribute("data-cx-field",column.id);value.setAttribute("data-cx-field",column.id);this.paintDrawerValue(column,row,value,context);sections.get(name).append(label,value)}},paintDrawerValue(column,row,value,context){const cell=row.cells[column.id],object=isCellObject(cell),presenter=column.presenter||(column.wrap?{kind:"longText"}:null);if(column.render&&column.hostRenderer!==false){try{if(column.render(row,value,{column:column.id,index:this.columns.indexOf(column),signal:context.signal,onDispose:cleanup=>{if(context.signal.aborted)cleanup();else context.signal.addEventListener("abort",cleanup,{once:true})}})===true)return}
|
|
62
|
+
catch(error){this.emit("error",{error})}}
|
|
63
|
+
if(presenter){gridCellRenderer(this,{...column,renderWidth:context.width||260},presenter)(row,value);return}
|
|
64
|
+
const text=cellText(cell,column,this.fmt),span=h("span");applyTone(span,"cx-drawer-text"+(text?"":" p-missing"),toneOf(object?cell.tone:null));setText(span,text||"—");if(object&&cell.title)span.title=cell.title;value.appendChild(span);if(object)for(const badge of cell.badges||[])value.appendChild(badgeElement(badge))},drawerFields(dialog=this.recordDrawer){return dialog?[...dialog.querySelectorAll("dd[data-cx-field],.cx-record-block-b[data-cx-field]")].filter(value=>value.closest(".cx-drawer")===dialog).map(value=>{const id=value.getAttribute("data-cx-field");return{id,column:this.columns.find(column=>column.id===id)||null,term:value.previousElementSibling,value}}):[]}});DataGrid.prototype.showReportingText=function(column,text,returnFocus,rowId,mono=false){if(this.destroyed||this.pendingQuery||!this.acceptedQuery)return;this.reportingText?.close();const dialog=h("dialog","cx-host cx-grid-overlay cx-text-dialog cx-reporting-text"),head=h("div","cx-drawer-h"),title=h("h4"),content=h("pre",mono?"p-mono":"");gridOverlayTheme(this,dialog);title.id=this.id+"-text-title";title.setAttribute("aria-level","2");setText(title,column.title);dialog.setAttribute("aria-labelledby",title.id);const copy=gridDecorateButton(gridButton(this.labels.gridCopy,()=>this.writeClipboard(text).catch(error=>this.emit("error",{error}))),"copy",true);const close=gridDecorateButton(gridButton("",()=>dialog.close()),"close",true);close.classList.add("icon");close.setAttribute("aria-label",this.labels.gridCloseCell);setText(content,text);content.tabIndex=0;head.append(title,copy,close);dialog.append(head,content);document.body.appendChild(dialog);this.reportingText=dialog;const signal=this.dataLifetime.signal,abort=()=>dialog.close();signal.addEventListener("abort",abort,{once:true});dialog.addEventListener("keydown",event=>{if(event.key!=="Tab"||event.altKey||event.ctrlKey||event.metaKey)return;const controls=[content,copy,close],index=controls.indexOf(document.activeElement);event.preventDefault();controls[(index+(event.shiftKey?-1:1)+controls.length)%controls.length].focus({preventScroll:true})});dialog.addEventListener("close",()=>{signal.removeEventListener("abort",abort);dialog.remove();if(this.reportingText===dialog)this.reportingText=null;if(!this.reportingText&&!signal.aborted)gridRestoreFocus(this,returnFocus,rowId,column)},{once:true});dialog.showModal();content.focus()};DataGrid.prototype.calculateGridAggregates=async function(columns){const controller=this.statusAggregateController=new AbortController(),signal=controller.signal,owner=this.dataLifetime,abort=()=>controller.abort();owner.signal.addEventListener("abort",abort,{once:true});setText(this.statusAggregates,this.labels.loading);try{const totals=new Map(columns.map(column=>[column.id,{count:0,sum:0,min:Infinity,max:-Infinity}]));let read=0;const selected=this.prepareExport({scope:"selected",columns:columns.map(column=>column.id),signal}).rows();for await(const row of selected){if(++read>50000)throw new Error(this.labels.gridUnknownCount);for(const column of columns){const value=cellValue(row.cells[column.id]);if(typeof value!=="number")continue;const total=totals.get(column.id);total.count++;total.sum+=value;total.min=Math.min(total.min,value);total.max=Math.max(total.max,value)}}
|
|
65
|
+
if(signal.aborted||this.destroyed)return;this.statusAggregates.replaceChildren();for(const column of columns){const total=totals.get(column.id),item=h("span"),number={format:value=>numberText(value,this.lang,column.format)};setText(item,column.title+": "+(total.count?number.format(total.sum):"—"));item.title=fill(this.labels.gridSelectionAggregate,{count:total.count,sum:number.format(total.sum),average:total.count?number.format(total.sum/total.count):"—",minimum:total.count?number.format(total.min):"—",maximum:total.count?number.format(total.max):"—"});this.statusAggregates.appendChild(item);}
|
|
60
66
|
}catch(error){if(!signal.aborted&&!this.destroyed)setText(this.statusAggregates,this.labels.gridNoData)}
|
|
61
|
-
finally{owner.signal.removeEventListener("abort",abort)}};DataGrid.prototype
|
|
67
|
+
finally{owner.signal.removeEventListener("abort",abort)}};Object.assign(DataGrid.prototype,COLUMNS_MENU,{buildGridFilters:buildFilters});context.GRID_REPORTING?.installFilters?.({gridDateInput});installed.add(context.DataGrid.prototype)}};(global.CanopyXParts||=[]).push(["filter-editor",part])})(typeof window!=="undefined"?window:globalThis);
|