@evotecit/canopyx 0.3.16 → 0.3.18
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-board.css +50 -0
- package/CanopyX.Html/Assets/canopyx-board.js +39 -0
- package/CanopyX.Html/Assets/canopyx-buckets.js +15 -0
- package/CanopyX.Html/Assets/canopyx-calculations.css +7 -0
- package/CanopyX.Html/Assets/canopyx-calculations.js +52 -0
- package/CanopyX.Html/Assets/canopyx-calendar-edit.js +3 -3
- package/CanopyX.Html/Assets/canopyx-calendar.css +5 -24
- package/CanopyX.Html/Assets/canopyx-calendar.js +14 -19
- package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
- package/CanopyX.Html/Assets/canopyx-changes.css +6 -24
- package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
- package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
- package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
- package/CanopyX.Html/Assets/canopyx-data.js +3 -3
- package/CanopyX.Html/Assets/canopyx-editing.css +2 -2
- package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
- package/CanopyX.Html/Assets/canopyx-enhance.js +4 -4
- package/CanopyX.Html/Assets/canopyx-export.js +54 -13
- package/CanopyX.Html/Assets/canopyx-facets.css +14 -5
- package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +71 -85
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
- package/CanopyX.Html/Assets/canopyx-flow-checks.css +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-dialog.css +2 -2
- package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-entry.css +136 -12
- package/CanopyX.Html/Assets/canopyx-flow-entry.js +2 -2
- package/CanopyX.Html/Assets/canopyx-flow-module.mjs +2 -2
- package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
- package/CanopyX.Html/Assets/canopyx-formatting.js +10 -9
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +182 -128
- package/CanopyX.Html/Assets/canopyx-grid.css +228 -96
- package/CanopyX.Html/Assets/canopyx-grid.js +182 -128
- package/CanopyX.Html/Assets/canopyx-grouping.css +22 -15
- package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
- package/CanopyX.Html/Assets/canopyx-interactive.css +197 -74
- package/CanopyX.Html/Assets/canopyx-interactive.js +38 -45
- package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
- package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
- package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
- package/CanopyX.Html/Assets/canopyx-layouts.css +48 -20
- package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
- package/CanopyX.Html/Assets/canopyx-link.js +2 -2
- package/CanopyX.Html/Assets/canopyx-live.css +1 -3
- package/CanopyX.Html/Assets/canopyx-live.js +3 -3
- package/CanopyX.Html/Assets/canopyx-matrix.css +1 -8
- package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
- package/CanopyX.Html/Assets/canopyx-module.mjs +38 -45
- package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
- package/CanopyX.Html/Assets/canopyx-path.css +45 -0
- package/CanopyX.Html/Assets/canopyx-path.js +28 -0
- package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
- package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
- package/CanopyX.Html/Assets/canopyx-plan.css +56 -0
- package/CanopyX.Html/Assets/canopyx-plan.js +67 -0
- package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
- package/CanopyX.Html/Assets/canopyx-record-panel.css +8 -7
- package/CanopyX.Html/Assets/canopyx-record-panel.js +15 -14
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +222 -161
- package/CanopyX.Html/Assets/canopyx-reporting.css +240 -107
- package/CanopyX.Html/Assets/canopyx-reporting.js +222 -161
- package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
- package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
- package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
- package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
- package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +36 -35
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
- package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
- package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
- package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
- package/CanopyX.Html/Assets/canopyx-ui-overlays.js +42 -0
- package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
- package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
- package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
- package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
- package/CanopyX.Html/Assets/canopyx-values.css +5 -0
- package/CanopyX.Html/Assets/canopyx-values.js +13 -0
- package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
- package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
- package/CanopyX.Html/Assets/canopyx.css +197 -71
- package/CanopyX.Html/Assets/canopyx.js +29 -19
- package/JavaScript/board.d.ts +30 -0
- package/JavaScript/changes.d.ts +4 -1
- package/JavaScript/facets.d.ts +5 -3
- package/JavaScript/grid.d.ts +150 -16
- package/JavaScript/hosts.d.ts +14 -1
- package/JavaScript/index.d.ts +4 -2
- package/JavaScript/locales/de.mjs +177 -9
- package/JavaScript/locales/es.mjs +177 -9
- package/JavaScript/locales/fr.mjs +176 -8
- package/JavaScript/locales/it.mjs +176 -8
- package/JavaScript/locales/pl.mjs +176 -8
- package/JavaScript/matrix.d.ts +4 -1
- package/JavaScript/path.d.ts +33 -0
- package/JavaScript/pivot.d.ts +135 -0
- package/JavaScript/plan.d.ts +23 -0
- package/JavaScript/protocol.d.ts +16 -3
- package/JavaScript/records.d.ts +2 -0
- package/JavaScript/stack.d.ts +28 -0
- package/JavaScript/time-slider.d.ts +58 -0
- package/JavaScript/ui.d.ts +261 -0
- package/JavaScript/view-intents.d.ts +45 -0
- package/README.md +22 -3
- package/ThirdParty/OfficeIMO/LICENSE +21 -0
- package/ThirdParty/OfficeIMO/README.md +13 -0
- package/package.json +76 -3
|
@@ -1,39 +1,46 @@
|
|
|
1
1
|
/* ---------- row grouping: the group-by bar,headings and the totals row ---------- */
|
|
2
|
-
.cx-groupbar{flex:none;display:flex;align-items:center;flex-wrap:wrap;gap:var(--
|
|
3
|
-
.cx-gchip{display:inline-flex;align-items:center;gap:var(--
|
|
4
|
-
.cx-data-grid .cx-gchip .cx-button{width:var(--
|
|
2
|
+
.cx-groupbar{flex:none;display:flex;align-items:center;flex-wrap:wrap;gap:var(--hfx-space-2,0.5rem);padding:var(--hfx-space-1-5,6px) var(--hfx-space-3,0.75rem);border-bottom:var(--hfx-border-width,1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));background:var(--hfx-color-row-alt,light-dark(#fafafa,#1d1f23));font-size:var(--hfx-type-small-size,0.8125rem);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));min-height:calc(var(--hfx-space-1,0.25rem)*9.5);}
|
|
3
|
+
.cx-gchip{display:inline-flex;align-items:center;gap:var(--hfx-space-1-5,6px);height:calc(var(--hfx-space-1,0.25rem)*6.5);padding:0 var(--hfx-space-1-5,6px);border:var(--hfx-border-width,1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));}
|
|
4
|
+
.cx-data-grid .cx-gchip .cx-button{width:calc(var(--hfx-space-1,0.25rem)*4.5);min-height:calc(var(--hfx-space-1,0.25rem)*4.5);height:calc(var(--hfx-space-1,0.25rem)*4.5);padding:0;}
|
|
5
5
|
.cx-data-grid .cx-grid-group{background:var(--hfx-color-row-alt,light-dark(#fafafa,#1d1f23));font-weight:700;}
|
|
6
|
-
.cx-grid-group-toggle{flex:0 0 auto;padding:0;margin-right:var(--
|
|
6
|
+
.cx-grid-group-toggle{flex:0 0 auto;padding:0;margin-right:var(--hfx-space-1-5,6px);border:0;background:transparent;color:inherit;font:inherit;cursor:pointer;}
|
|
7
7
|
.cx-grid-group-toggle:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
|
|
8
8
|
.cx-data-grid .cx-grid-group .cx-cell:first-child{overflow:visible;z-index:3;}
|
|
9
9
|
.cx-grid-group-label{flex:none;display:flex;align-items:center;min-width:0;overflow:hidden;white-space:nowrap;}
|
|
10
10
|
.cx-grid-group-text{flex:0 0 auto;max-width:100%;overflow:hidden;text-overflow:ellipsis;}
|
|
11
|
-
.cx-grid-group-count{flex:none;margin-left:var(--
|
|
11
|
+
.cx-grid-group-count{flex:none;margin-left:var(--hfx-space-2,0.5rem);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--hfx-type-caption-size,0.75rem);font-weight:400;}
|
|
12
12
|
.cx-data-grid .cx-grid-group .cx-cell{background:var(--hfx-color-row-alt,light-dark(#fafafa,#1d1f23));}
|
|
13
|
-
.cx-data-grid .cx-grid-summary{position:sticky;bottom:0;z-index:4;background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-top:var(--
|
|
13
|
+
.cx-data-grid .cx-grid-summary{position:sticky;bottom:0;z-index:4;background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-top:var(--hfx-border-width,1px) solid var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));font:inherit;}
|
|
14
14
|
.cx-summary-row{display:flex;height:var(--hfx-table-header-height,calc(40px - var(--cx-compact,0) * 8px));font-weight:700;}
|
|
15
15
|
.cx-data-grid .cx-summary-row .cx-cell[data-cx-pin]{background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
|
|
16
|
-
.cx-summary-row .cx-summary-caption{font-size:var(--
|
|
16
|
+
.cx-summary-row .cx-summary-caption{font-size:calc(var(--hfx-type-caption-size,0.75rem)*.9583);letter-spacing:.04em;text-transform:none;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
17
17
|
.cx-groupbar-label{flex:none;}
|
|
18
18
|
.cx-groupbar-hint{font-style:italic;}
|
|
19
19
|
.cx-groupbar-spacer{flex:1 1 auto;}
|
|
20
|
-
.cx-groupbar.cx-group-drop{outline:var(--
|
|
21
|
-
.cx-data-grid .cx-groupbar .cx-groupbar-all{min-height:var(--
|
|
20
|
+
.cx-groupbar.cx-group-drop{outline:calc(var(--hfx-border-width,1px)*2) dashed var(--hfx-color-accent,light-dark(#11776f,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
|
|
21
|
+
.cx-data-grid .cx-groupbar .cx-groupbar-all{min-height:calc(var(--hfx-space-1,0.25rem)*6.5);height:calc(var(--hfx-space-1,0.25rem)*6.5);padding:0 var(--hfx-space-2,0.5rem);font-size:var(--hfx-type-caption-size,0.75rem);}
|
|
22
22
|
.cx-gchip-name{cursor:grab;touch-action:none;white-space:nowrap;}
|
|
23
23
|
.cx-data-grid .cx-gchip .cx-gchip-fold{font-weight:700;line-height:1;}
|
|
24
|
-
.cx-gchip-order{height:var(--
|
|
24
|
+
.cx-gchip-order{height:calc(var(--hfx-space-1,0.25rem)*5);max-width:140px;border:var(--hfx-border-width,1px) solid var(--hfx-color-border-control,light-dark(#8a8f98,#6e737c));border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font:inherit;font-size:var(--hfx-type-caption-size,0.75rem);}
|
|
25
25
|
.cx-gchip:focus-within{border-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
|
|
26
|
-
.cx-data-grid .cx-grid-group .cx-cell:first-child{padding-inline-start:calc(var(--hfx-cell-padding-x,calc(12px - var(--cx-compact,0) * 4px)) + var(--cx-group-level,0) * var(--
|
|
26
|
+
.cx-data-grid .cx-grid-group .cx-cell:first-child{padding-inline-start:calc(var(--hfx-cell-padding-x,calc(12px - var(--cx-compact,0) * 4px)) + var(--cx-group-level,0) * var(--hfx-space-4,1rem));}
|
|
27
27
|
.cx-grid-group-column{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-weight:400;}
|
|
28
|
-
.cx-grid-group-select{margin-inline-end:var(--
|
|
28
|
+
.cx-grid-group-select{margin-inline-end:var(--hfx-space-1-5,6px);}
|
|
29
29
|
.cx-aggregate{font-variant-numeric:tabular-nums;}
|
|
30
30
|
.cx-aggregate:not(:first-child){overflow:hidden;text-overflow:clip;}
|
|
31
|
-
.cx-grid-group-aggregates{flex:0 1000 auto;min-width:0;margin-inline-start:var(--
|
|
31
|
+
.cx-grid-group-aggregates{flex:0 1000 auto;min-width:0;margin-inline-start:var(--hfx-space-3,0.75rem);overflow:hidden;text-overflow:ellipsis;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font:inherit;font-weight:400;font-variant-numeric:tabular-nums;border:0;background:transparent;padding:0;cursor:pointer;white-space:nowrap;}
|
|
32
32
|
.cx-grid-group-aggregates:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
|
|
33
|
-
.cx-summary-row .cx-grid-group-aggregates{text-transform:none;letter-spacing:normal;font-size:var(--
|
|
33
|
+
.cx-summary-row .cx-grid-group-aggregates{text-transform:none;letter-spacing:normal;font-size:var(--hfx-type-small-size,0.8125rem);}
|
|
34
34
|
.cx-aggregate > .cx-aggregate-button{max-width:100%;margin-inline-start:0;font:inherit;color:inherit;flex:0 1 auto;text-align:left;}
|
|
35
|
-
.cx-phone .cx-groupbar{padding:var(--
|
|
35
|
+
.cx-phone .cx-groupbar{padding:var(--hfx-space-1,0.25rem) var(--hfx-space-2,0.5rem);gap:var(--hfx-space-1-5,6px);}
|
|
36
36
|
.cx-phone .cx-gchip{max-width:100%;}
|
|
37
37
|
.cx-phone .cx-gchip-name{min-width:0;overflow:hidden;text-overflow:ellipsis;}
|
|
38
38
|
.cx-phone :is(.cx-groupbar-label,.cx-gchip-order,.cx-gchip-fold){display:none;}
|
|
39
39
|
@media (forced-colors:active){.cx-gchip{border-color:CanvasText;}}
|
|
40
|
+
.cx-gchip-bucket-value{width:calc(var(--hfx-space-4,1rem)*7);min-width:calc(var(--hfx-space-4,1rem)*3);max-width:calc(var(--hfx-space-4,1rem)*10);padding:var(--hfx-space-0-5,2px) var(--hfx-space-1,0.25rem);font:inherit;}
|
|
41
|
+
.cx-phone .cx-gchip-bucket{display:inline-block;max-width:calc(var(--hfx-space-4,1rem)*6);}
|
|
42
|
+
.cx-phone .cx-gchip-bucket-value{width:calc(var(--hfx-space-4,1rem)*3.5);min-width:calc(var(--hfx-space-4,1rem)*2);}
|
|
43
|
+
.cx-phone .cx-gchip:has(.cx-gchip-bucket) .cx-gchip-name{max-width:calc(var(--hfx-space-4,1rem)*3.5);}
|
|
44
|
+
.cx-groupbar .cx-gchip{height:calc(var(--hfx-control-height-sm,calc(28px - var(--cx-compact,0) * 4px)) + var(--hfx-border-width,1px)*2);}
|
|
45
|
+
.cx-groupbar .cx-gchip-order,.cx-data-grid .cx-groupbar .cx-gchip .cx-button,.cx-data-grid .cx-groupbar .cx-groupbar-all{height:var(--hfx-control-height-sm,calc(28px - var(--cx-compact,0) * 4px));min-height:var(--hfx-control-height-sm,calc(28px - var(--cx-compact,0) * 4px));}
|
|
46
|
+
.cx-data-grid .cx-groupbar .cx-gchip .cx-button{width:var(--hfx-control-height-sm,calc(28px - var(--cx-compact,0) * 4px));}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"c7eead770d16a84b",requires:["detail-rows"],install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,GRID_ROWS,GRID_REPORTING,GRID_OPTIONS,GRID_OPTION_GRIDS,h,setText,fill,numberFormat,formatValue,cellValue,cellText,isCellObject,gridScalar,gridQuery,gridFreeze,gridOrder,gridIdOrder,gridQueryRows,gridButton,gridDecorateButton,gridCellRenderer,gridPresenterTone,GRID_TONE_RANK,validateGridRows,validateGridPage,checkDocument,requireIdentifier,validStructuralCount,PROTOCOL,gridOperationActive,reportingGroupKey,reportingGroupCompare,reportingSummaryEnabled,reportingDynamicGroups,GROUP_OPERATIONS,reportingAggregateParts,disposeRowHostCells,quietControls,TreeGrid,GRID_BUCKETS,gridBucketDefinition}=context;const groupCounting=operation=>operation==="count"||operation==="distinctCount";function groupSummaryAggregates(view){const bindings=new Map();const add=aggregate=>{const existing=bindings.get(aggregate.id);if(existing&&(existing.column!==aggregate.column||existing.operation!==aggregate.operation))
|
|
2
2
|
throw new Error("CanopyX: an aggregate identity must use the same column and operation.");if(!existing)bindings.set(aggregate.id,aggregate)};for(const aggregate of view.reporting?.aggregates||[])add(aggregate);for(const footer of view.footers||[])if(footer.scope==="all"||view.presentation!=="paged")
|
|
3
3
|
footer.aggregates.forEach(add);if(bindings.size>32)throw new Error("CanopyX: at most 32 full-query aggregates are supported.");return[...bindings.values()]}
|
|
4
4
|
function groupCustomAggregates(grid){const found=new Map();for(const plugin of grid.plugins)for(const[name,entry]of Object.entries(plugin.aggregates||{})){const definition=typeof entry==="function"?{compute:entry}:entry;if(!/^[a-z][a-zA-Z\d]{0,31}$/.test(name) || GROUP_OPERATIONS.includes(name) || !definition || typeof definition.compute !== "function" ||
|
|
@@ -13,37 +13,40 @@ return operation==="count"?count:distinct?distinct.size:!count?null:
|
|
|
13
13
|
operation==="sum"?sum+correction:operation==="average"?(sum+correction)/ count : operation === "minimum" ? minimum : maximum;
|
|
14
14
|
}
|
|
15
15
|
function groupAggregateValues(grid,rows,first=0,last=rows.length){const values=Object.create(null);for(const aggregate of groupSummaryAggregates(grid.view))values[aggregate.id]=groupAggregateValue(grid,aggregate,rows,first,last);return values}
|
|
16
|
-
function groupCheckValues(view,values,count){const declarations=groupSummaryAggregates(view);if(!values||typeof values!=="object"||Array.isArray(values)||Object.keys(values).length!==declarations.length)
|
|
16
|
+
GRID_ROWS.aggregateValue=groupAggregateValue;function groupCheckValues(view,values,count){const declarations=groupSummaryAggregates(view);if(!values||typeof values!=="object"||Array.isArray(values)||Object.keys(values).length!==declarations.length)
|
|
17
17
|
throw new Error("CanopyX: summary aggregate bindings differ.");for(const aggregate of declarations){const value=values[aggregate.id];if(!Object.hasOwn(values,aggregate.id)||value!==null&&(typeof value!=="number"||!Number.isFinite(value)||Math.abs(value)>Number.MAX_SAFE_INTEGER)||
|
|
18
18
|
groupCounting(aggregate.operation)&&(!validStructuralCount(value)||value>count)||
|
|
19
19
|
!count&&!groupCounting(aggregate.operation)&&value!==null)throw new Error("CanopyX: invalid aggregate value.")}}
|
|
20
20
|
const GROUP_MEASURE=DataGrid.prototype.measureGridColumn;Object.assign(DataGrid.prototype,{measureGridColumn(column){const result=GROUP_MEASURE.call(this,column),summary=this.summaryCandidate?.result||this.summary;const aggregates=this.rowsAttached&&summary&&!column.fixed&&(this.view.reporting.aggregates||[]).filter(item=>item.column===column.id);if(!aggregates?.length||!this.fitContext)return result;const context=this.fitContext,pad=this.fitFont[3];let widest=0,seen=0;context.font=this.fitFont[0].replace(/^\S+/, "700");
|
|
21
21
|
const measure=values=>{widest=Math.max(widest,context.measureText(reportingAggregateParts(this,column,aggregates,values).text).width)};measure(summary.aggregates);const walk=list=>{for(const group of list||[]){if(++seen>200)return;measure(group.aggregates);walk(group.groups)}};walk(summary.groups);const need=Math.min(Math.max(420,result.width),Math.ceil(widest+2*pad+4));return need>result.width?Object.freeze({...result,width:need}):result},paintAggregates(cell,column,aggregates,values){const parts=reportingAggregateParts(this,column,aggregates,values);cell.title=parts.title;cell.classList.add("cx-aggregate");if(parts.text)cell.setAttribute("aria-label",parts.title);else cell.removeAttribute("aria-label");if(!parts.text){cell.replaceChildren();return}
|
|
22
|
-
let button=cell.querySelector(":scope > .cx-aggregate-button");if(!button){button=h("button","cx-grid-group-aggregates cx-aggregate-button");button.type="button";button.setAttribute("aria-haspopup","dialog");cell.replaceChildren(button);button.addEventListener("click",event=>{event.stopPropagation();this.
|
|
23
|
-
if(button.textContent!==parts.text)setText(button,parts.text);
|
|
24
|
-
|
|
22
|
+
let button=cell.querySelector(":scope > .cx-aggregate-button");if(!button){button=h("button","cx-grid-group-aggregates cx-aggregate-button");button.type="button";button.setAttribute("aria-haspopup","dialog");cell.replaceChildren(button);button.addEventListener("click",event=>{event.stopPropagation();this.showAggregateMenu(column,aggregates,button._cxAggregateValues,button).catch(error=>this.emit("error",{error}))})}
|
|
23
|
+
if(button.textContent!==parts.text +(parts.caption||"")){setText(button,parts.text);if(parts.caption){const caption=h("span","cx-aggregate-caption");setText(caption,parts.caption);button.append(caption)}}
|
|
24
|
+
button._cxAggregateValues=values;button._cxAggregateText=parts.title;button.title=parts.title;button.setAttribute("aria-label",parts.title)}});function groupLevelsOf(view,query){const grouping=view.reporting?.grouping;return grouping?[{column:grouping.column,direction:grouping.direction}]:query?.groupBy||[]}
|
|
25
|
+
function groupOrder(view,level){const column=view.columns.find(item=>item.id===level.column),compare=reportingGroupCompare(GRID_REPORTING.compare(view));const byValue=(a,b,direction)=>level.bucket?a.value===null||b.value===null?a.value===b.value?0:a.value===null?1:-1:
|
|
26
|
+
direction==="desc"?gridOrder(b.value,a.value):gridOrder(a.value,b.value):compare({cells:{[column.id]:a.value}},{cells:{[column.id]:b.value}},column,direction);if(!level.aggregate)return(a,b)=>byValue(a,b,level.direction);return(a,b)=>{const x=a.aggregates[level.aggregate],y=b.aggregates[level.aggregate];if(x===null||y===null)return x===y?byValue(a,b,"asc"):x===null?1:-1;return(level.direction==="desc"?gridOrder(y,x):gridOrder(x,y))||byValue(a,b,"asc")}}
|
|
25
27
|
function groupSummaryResult(grid,query,page,summary){const view=grid.view;checkDocument(summary,"gridSummary");if(JSON.stringify(summary).length>4194304||summary.view!==view.id||summary.revision!==page.revision||summary.matched!==page.matched||
|
|
26
28
|
!Array.isArray(summary.groups)||!summary.query||
|
|
27
29
|
!["protocol","type","view","offset","limit","sort","filters","search","revision"].every(key=>Object.hasOwn(summary.query,key))||
|
|
28
30
|
summary.query.type!=="gridQuery"||summary.query.protocol!==PROTOCOL||summary.query.revision!==page.revision||summary.query.offset!==0||
|
|
29
31
|
JSON.stringify(gridQuery(view,summary.query))!==JSON.stringify(query))throw new Error("CanopyX: summary ownership or counts differ.");groupCheckValues(view,summary.aggregates,summary.matched);const levels=groupLevelsOf(view,query),keys=new Set();if(!levels.length&&summary.groups.length)throw new Error("CanopyX: an ungrouped summary has no groups.");const check=(groups,depth,start,count)=>{const level=levels[depth],column=view.columns.find(item=>item.id===level.column),order=groupOrder(view,level),values=new Set();let offset=start,previous=null;for(const group of groups){if(!group||typeof group!=="object"||!Object.hasOwn(group,"value")||
|
|
30
|
-
group.value!==null&&typeof group.value==="object")throw new Error("CanopyX: groups carry raw values.");requireIdentifier(group.key,"group key");const value=reportingGroupKey(gridScalar(group.value,column));if(group.cells!==undefined)validateGridRows([{id:group.key,cells:group.cells}],view.columns);if(keys.size>=10000||group.key.length>4096||keys.has(group.key)||values.has(value)||group.offset!==offset||
|
|
32
|
+
group.value!==null&&typeof group.value==="object")throw new Error("CanopyX: groups carry raw values.");requireIdentifier(group.key,"group key");const value=reportingGroupKey(gridScalar(group.value,level.bucket?{...column,kind:"number"}:column));if(group.cells!==undefined)validateGridRows([{id:group.key,cells:group.cells}],view.columns);if(keys.size>=10000||group.key.length>4096||keys.has(group.key)||values.has(value)||group.offset!==offset||
|
|
31
33
|
!validStructuralCount(group.count)||!group.count)throw new Error("CanopyX: invalid complete group range.");groupCheckValues(view,group.aggregates,group.count);if(previous&&order(previous,group)>=0)throw new Error("CanopyX: groups do not follow their level's order.");keys.add(group.key);values.add(value);previous=group;if(depth+1<levels.length){if(!Array.isArray(group.groups)||!group.groups.length)throw new Error("CanopyX: a group of an outer level lists its inner groups.");check(group.groups,depth+1,group.offset,group.count)}else if(group.groups!==undefined)throw new Error("CanopyX: a group of the innermost level has no inner groups.");offset +=group.count}
|
|
32
34
|
if(offset!==start+count)throw new Error("CanopyX: groups omit matching records.")};if(levels.length)check(summary.groups,0,0,summary.matched);return gridFreeze(JSON.parse(JSON.stringify(summary)))}
|
|
33
35
|
function groupPath(summary,ordinal){const path=[];for(let list=summary.groups;list?.length;){let low=0,high=list.length;while(low<high){const middle=(low+high)>>>1;if(list[middle].offset<=ordinal)low=middle+1;else high=middle}
|
|
34
36
|
const group=low?list[low-1]:null;if(!group||ordinal>=group.offset+group.count)break;path.push(group);list=group.groups}
|
|
35
37
|
return path}
|
|
36
|
-
const GROUP_GRIDS=new WeakMap();GRID_ROWS.order=(view,query)=>{const grid=GROUP_GRIDS.get(view),columns=new Map(view.columns.map(column=>[column.id,column])),levels=query.groupBy;const baseCompare=GRID_REPORTING.compare(view),compare=GRID_OPTION_GRIDS.has(view)?GRID_OPTIONS.compare(view,query,columns,baseCompare):baseCompare;const rest=query.sort.filter(sort=>!levels.some(level=>level.column===sort.column));const within=(a,b)=>{for(const sort of rest){const result=compare(a,b,columns.get(sort.column),sort.direction);if(result)return result}return gridIdOrder(a.id,b.id)};const arrange=(rows,depth)=>{if(depth===levels.length)return rows.sort(within);const level=levels[depth],column=columns.get(level.column),buckets=new Map();for(const row of rows){const key=reportingGroupKey(
|
|
37
|
-
const groups=[...buckets.values()].map(list=>({list,value:
|
|
38
|
+
const GROUP_GRIDS=new WeakMap();GRID_ROWS.order=(view,query)=>{const grid=GROUP_GRIDS.get(view),columns=new Map(view.columns.map(column=>[column.id,column])),levels=query.groupBy;const baseCompare=GRID_REPORTING.compare(view),compare=GRID_OPTION_GRIDS.has(view)?GRID_OPTIONS.compare(view,query,columns,baseCompare):baseCompare;const rest=query.sort.filter(sort=>!levels.some(level=>level.column===sort.column));const within=(a,b)=>{for(const sort of rest){const result=compare(a,b,columns.get(sort.column),sort.direction);if(result)return result}return gridIdOrder(a.id,b.id)};const arrange=(rows,depth)=>{if(depth===levels.length)return rows.sort(within);const level=levels[depth],column=columns.get(level.column),buckets=new Map();for(const row of rows){const key=reportingGroupKey(groupBucketValue(level,column,row.cells[column.id]));if(!buckets.has(key))buckets.set(key,[]);buckets.get(key).push(row)}
|
|
39
|
+
const groups=[...buckets.values()].map(list=>({list,value:groupBucketValue(level,column,list[0].cells[column.id]),aggregates:level.aggregate?{[level.aggregate]:groupAggregateValue(grid,view.reporting.aggregates.find(item=>item.id===level.aggregate),list,0,list.length)}:{}}));groups.sort(groupOrder(view,level));return groups.flatMap(group=>arrange(group.list,depth+1))};return arrange(gridQueryRows(view,query,columns,null),0)};GRID_OPTIONS.groupRows=GRID_ROWS.order;function groupInnerKey(parent,key){const text=parent+"\u001f"+key;if(text.length<=4096)return text;let a=0x811c9dc5,b=0x01000193;for(let i=0;i<text.length;i++){const code=text.charCodeAt(i);a=Math.imul(a^code,16777619);b=Math.imul(b^code,2246822519)^(b>>>13)}
|
|
38
40
|
return "#" +(a>>>0).toString(36)+(b>>>0).toString(36)+ ":"+text.length}
|
|
39
|
-
function groupInlineSummary(grid,query){const view=grid.view,columns=new Map(view.columns.map(column=>[column.id,column])),levels=groupLevelsOf(view,query);const rows=query.groupBy?.length?GRID_ROWS.order(view,query):gridQueryRows(view,query,columns,GRID_REPORTING.compare(view));let total=0;const build=(start,end,depth,parent)=>{const column=columns.get(levels[depth].column),groups=[];for(let offset=start;offset<end;){const value=
|
|
41
|
+
function groupInlineSummary(grid,query){const view=grid.view,columns=new Map(view.columns.map(column=>[column.id,column])),levels=groupLevelsOf(view,query);const rows=query.groupBy?.length?GRID_ROWS.order(view,query):gridQueryRows(view,query,columns,GRID_REPORTING.compare(view));let total=0;const build=(start,end,depth,parent)=>{const column=columns.get(levels[depth].column),groups=[];for(let offset=start;offset<end;){const value=groupBucketValue(levels[depth],column,rows[offset].cells[column.id]),key=reportingGroupKey(value);let last=offset+1;while(last<end&&reportingGroupKey(groupBucketValue(levels[depth],column,rows[last].cells[column.id]))===key)last++;const id=parent===null?key:groupInnerKey(parent,key);if(++total>10000||id.length>4096)throw new Error("CanopyX: inline grouping exceeds its metadata bounds.");const group={key:id,value,offset,count:last-offset,aggregates:groupAggregateValues(grid,rows,offset,last),...groupWorstCells(view,rows,offset,last)};if(depth+1<levels.length)group.groups=build(offset,last,depth+1,id);groups.push(group);offset=last}
|
|
40
42
|
return groups};return{protocol:PROTOCOL,type:"gridSummary",view:view.id,revision:query.revision,query,matched:rows.length,groups:levels.length?build(0,rows.length,0,null):[],aggregates:groupAggregateValues(grid,rows)}}
|
|
41
43
|
function groupWorstCells(view,rows,first,last){const cells=Object.create(null);for(const declared of view.columns){const presenter=declared.presenter||view.reporting.presenters?.[declared.id];if(!presenter||!["state","enum"].includes(presenter.kind))continue;let worst=null,rank=-1;for(let index=first;index<last;index++){const cell=rows[index].cells[declared.id],raw=cellValue(cell);if(raw==null)continue;const next=GRID_TONE_RANK[gridPresenterTone(presenter,raw,isCellObject(cell)?cell.tone:null)]??2;if(next>rank){worst=cell;rank=next}}
|
|
42
44
|
if(worst!==null)cells[declared.id]=worst}
|
|
43
45
|
return Object.keys(cells).length?{cells}:{}}
|
|
46
|
+
function groupBucketValue(level,column,cell){if(level.bucket)return GRID_BUCKETS.key(level.bucket,gridScalar(cell,column));const value=cellValue(cell)??null;return column.kind==="datetime"&&value!==null?new Date(gridScalar(cell,column)).toISOString():value}
|
|
44
47
|
const GROUP_ATTACH=DataGrid.prototype.attachRows;const groupSummaryQuery=(view,query,revision)=>gridQuery(view,{...query,offset:0,limit:view.pageSize,revision});const groupNeedsSummary=(view,query)=>!!view.reporting?.grouping||!!query.groupBy?.length||!!view.reporting?.aggregates?.length;GRID_ROWS.requestPage=async function(query,signal){const page=await GRID_ROWS.base.requestPage.call(this,query,signal);if(!reportingSummaryEnabled(this.view)||signal!==this.dataLifetime.signal||!groupNeedsSummary(this.view,query))return page;validateGridPage(page,this.view,query);const request=groupSummaryQuery(this.view,query,page.revision),key=JSON.stringify(request);if(this.summaryCandidate?.key!==key){const hook=this.source.summary||(this.view.source.kind==="inline"?request=>groupInlineSummary(this,request):null);if(!hook)throw new Error("CanopyX: hosted summaries need an explicit source summary hook.");const summary=await this.runGridHook(signal=>hook.call(this.source,request,{signal}),signal);gridOperationActive(this,signal);this.summaryCandidate={key,result:groupSummaryResult(this,request,page,summary)}}
|
|
45
48
|
const result=this.summaryCandidate.result,levels=groupLevelsOf(this.view,query);if(result.matched!==page.matched)throw new Error("CanopyX: a page differs from its complete-query summary count.");if(levels.length){const columns=levels.map(level=>this.view.columns.find(column=>column.id===level.column));for(let i=0;i<page.items.length;i++){const path=groupPath(result,page.offset+i);if(path.length!==levels.length||columns.some((column,depth)=>
|
|
46
|
-
reportingGroupKey(
|
|
49
|
+
reportingGroupKey(groupBucketValue(levels[depth],column,page.items[i].cells[column.id]))!==reportingGroupKey(path[depth].value)))
|
|
47
50
|
throw new Error("CanopyX: a page record differs from its complete-query group.")}}
|
|
48
51
|
return page};Object.assign(DataGrid.prototype,{attachRows(){if(this.rowsAttached)return;GROUP_ATTACH.call(this);if(!reportingSummaryEnabled(this.view))return;GROUP_GRIDS.set(this.view,this);this.groupAggregates=groupCustomAggregates(this);for(const aggregate of this.view.reporting.aggregates||[])
|
|
49
52
|
if(!GROUP_OPERATIONS.includes(aggregate.operation)&&this.view.source.kind==="inline"&&!this.groupAggregates.has(aggregate.operation))
|
|
@@ -59,27 +62,31 @@ const group=row.group,level=row.level,collapsed=this.collapsedGroups.has(group.k
|
|
|
59
62
|
else{element.removeAttribute("aria-level");element.removeAttribute("aria-expanded")}
|
|
60
63
|
element.style.height=this.rowH+"px";element.style.width=this.rowWidth+"px";element.style.setProperty("--cx-group-level",String(level-1));const priorButton=previous?.[0].cell.querySelector(".cx-grid-group-toggle"),button=priorButton||h("button","cx-grid-group-toggle");if(!priorButton){button.type="button";button.tabIndex=-1}
|
|
61
64
|
if(button.disabled!==!!this.pendingQuery)button.disabled=!!this.pendingQuery;button.setAttribute("aria-expanded",String(!collapsed));button.setAttribute("aria-label",collapsed?this.labels.gridGroupExpand:this.labels.gridGroupCollapse);if(button.textContent!==(collapsed?"▸":"▾"))setText(button,collapsed?"▸":"▾");if(!priorButton)button.addEventListener("click",()=>{if(this.pendingQuery)return;try{this.setFocus(row,false);this.setGroupCollapsed(group.key,!this.collapsedGroups.has(group.key));this.setFocus(this.focused,true)}
|
|
62
|
-
catch(error){this.emit("error",{error})}});const value=group.value===null?this.labels.gridGroupMissing:cellText(group.value,groupColumn,this.fmt),count=numberFormat(this.lang).format(group.count);const label=fill(this.view.reporting?.grouping?.headerTemplate||this.labels.gridGroupHeading,{column:groupColumn.title,value,count}),cells=[];this.cols.forEach((column,index)=>{const cell=previous?.[index].cell||this.cell(element,index,column.width,column.kind);cells.push({cell,content:cell});if(index===0){const priorHeading=cell.querySelector(".cx-grid-group-label"),heading=priorHeading||h("span","cx-grid-group-label");const text=heading.querySelector(".cx-grid-group-text")||h("span","cx-grid-group-text"),badge=heading.querySelector(".cx-grid-group-count")||h("span","cx-grid-group-count");text.replaceChildren();if(levels.length>1&&!this.view.reporting?.grouping?.headerTemplate){const name=h("span","cx-grid-group-column");setText(name,groupColumn.title);text.append(name,document.createTextNode(" "))}
|
|
63
|
-
text.appendChild(document.createTextNode(this.view.reporting?.grouping?.headerTemplate?label:value));setText(badge,count);badge.hidden=!!this.view.reporting?.grouping?.headerTemplate;if(!priorHeading)heading.append(text,badge);if(!priorButton)cell.append(button);this.paintGroupSelection(cell,group);if(!priorHeading)cell.append(heading);cell.title=label;this.paintHiddenAggregates(heading,group.aggregates,cell,column.id,label);return}
|
|
65
|
+
catch(error){this.emit("error",{error})}});const bucket=levels[level-1].bucket;const value=group.value===null?this.labels.gridGroupMissing:bucket?GRID_BUCKETS.label(bucket,group.value,this.lang):cellText(group.value,groupColumn,this.fmt),count=numberFormat(this.lang).format(group.count);const label=fill(this.view.reporting?.grouping?.headerTemplate||this.labels.gridGroupHeading,{column:groupColumn.title,value,count}),cells=[];this.cols.forEach((column,index)=>{const cell=previous?.[index].cell||this.cell(element,index,column.width,column.kind);cells.push({cell,content:cell});if(index===0){const priorHeading=cell.querySelector(".cx-grid-group-label"),heading=priorHeading||h("span","cx-grid-group-label");const text=heading.querySelector(".cx-grid-group-text")||h("span","cx-grid-group-text"),badge=heading.querySelector(".cx-grid-group-count")||h("span","cx-grid-group-count");text.replaceChildren();if(levels.length>1&&!this.view.reporting?.grouping?.headerTemplate){const name=h("span","cx-grid-group-column");setText(name,groupColumn.title);text.append(name,document.createTextNode(" "))}
|
|
66
|
+
text.appendChild(document.createTextNode(this.view.reporting?.grouping?.headerTemplate?label:value));setText(badge,count);badge.hidden=!!this.view.reporting?.grouping?.headerTemplate||this.view.reporting.aggregates?.some(aggregate=>aggregate.operation==="count"&&group.aggregates[aggregate.id]===group.count);if(!priorHeading)heading.append(text,badge);if(!priorButton)cell.append(button);this.paintGroupSelection(cell,group);if(!priorHeading)cell.append(heading);cell.title=label;this.paintHiddenAggregates(heading,group.aggregates,cell,column.id,label);return}
|
|
64
67
|
const aggregates=(this.view.reporting.aggregates||[]).filter(item=>item.column===column.id);if(aggregates.length)this.paintAggregates(cell,column,aggregates,group.aggregates);else{cell.replaceChildren();if(Object.hasOwn(group.cells||{},column.id)){const options=column.presenter||this.view.reporting.presenters?.[column.id];if(options)gridCellRenderer(this,column,options)({id:group.key,cells:group.cells},cell);else setText(cell,cellText(group.cells[column.id],column,this.fmt))}}});let room=this.cols[0].renderWidth??this.cols[0].width;for(let index=1;index<cells.length&&!cells[index].cell.textContent;index++)room +=this.cols[index].renderWidth??this.cols[index].width;const heading=cells[0].cell.querySelector(".cx-grid-group-label");heading.style.maxWidth=Math.max(40,room-44 -(level-1)*16 -(this.view.reporting.selectionControls&&this.multi?22:0))+ "px";element._cells=cells;quietControls(element);this.paintGridHighlights(element,row)},paintGroupSelection(cell,group){if(!this.view.reporting.selectionControls||!this.multi)return;const previous=cell.querySelector(".cx-grid-group-select"),check=previous||h("input","cx-grid-row-select cx-grid-group-select");if(!previous){check.type="checkbox";check.tabIndex=-1}
|
|
65
68
|
const state=this.groupSelection(group);check.checked=state===true;check.indeterminate=state==="mixed";check.disabled=!!this.pendingQuery;check.setAttribute("aria-label",fill(this.labels.gridSelectGroup,{group:group.value===null?this.labels.gridGroupMissing:String(group.value)}));if(!previous)check.addEventListener("click",event=>{event.preventDefault();event.stopPropagation();this.runReportingSelection(()=>this.selectRange(group.offset,group.offset+group.count-1,{selected:this.groupSelection(group)!==true,additive:true}))});if(!previous)cell.appendChild(check)},groupSelection(group){let selected=0,loaded=0;for(const[ordinal,record]of this.rowCache){if(ordinal<group.offset||ordinal>=group.offset+group.count)continue;loaded++;if(this.reportingRowSelected(record))selected++}
|
|
66
|
-
if(this.querySelection)return selected===loaded?true:selected?"mixed":false;return selected&&selected===group.count?true:selected?"mixed":false},paintHiddenAggregates(target,values,cell=target,headingColumn=null,title=this.labels.gridSummary||this.view.label){const shown=new Set(this.cols.filter(column=>column.id!==headingColumn).map(column=>column.id)),parts=[],details=[];for(const column of this.columns){const aggregates=shown.has(column.id)?[]:(this.view.reporting.aggregates||[]).filter(item=>item.column===column.id);if(aggregates.length){const formatted=reportingAggregateParts(this,column,aggregates,values);if(formatted.text){parts.push(column.title+" "+formatted.text);details.push(column.title+"\n"+formatted.title)}}}
|
|
69
|
+
if(this.querySelection)return selected===loaded?true:selected?"mixed":false;return selected&&selected===group.count?true:selected?"mixed":false},paintHiddenAggregates(target,values,cell=target,headingColumn=null,title=this.labels.gridSummary||this.view.label){const shown=new Set(this.cols.filter(column=>column.id!==headingColumn).map(column=>column.id)),parts=[],details=[],bindings=[];for(const column of this.columns){const aggregates=shown.has(column.id)?[]:(this.view.reporting.aggregates||[]).filter(item=>item.column===column.id);if(aggregates.length){const formatted=reportingAggregateParts(this,column,aggregates,values);if(formatted.text||aggregates.some(aggregate=>(this.aggregateShowAs?.[aggregate.id]??aggregate.showAs??"value")!=="value")){parts.push(column.title+" " +(formatted.text||"—")+(formatted.caption?" ("+formatted.caption+")":""));details.push(column.title+"\n"+formatted.title);bindings.push(...aggregates)}}}
|
|
67
70
|
const previous=target.querySelector(":scope > .cx-hidden-aggregates");if(!parts.length){previous?.remove();return}
|
|
68
|
-
const extra=previous||h("button","cx-grid-group-aggregates cx-hidden-aggregates");if(!previous)extra.type="button";extra.setAttribute("aria-haspopup","dialog");if(extra.textContent!==parts.join(" · "))setText(extra,parts.join(" · "));extra._cxAggregateText={title,text:details.join("\n")};extra.title=details.join("\n");extra.setAttribute("aria-label",details.join(", "));if(!previous){target.appendChild(extra);extra.addEventListener("click",event=>{event.stopPropagation();this.
|
|
71
|
+
const extra=previous||h("button","cx-grid-group-aggregates cx-hidden-aggregates");if(!previous)extra.type="button";extra.setAttribute("aria-haspopup","dialog");if(extra.textContent!==parts.join(" · "))setText(extra,parts.join(" · "));extra._cxAggregateText={title,text:details.join("\n"),bindings,values};extra.title=details.join("\n");extra.setAttribute("aria-label",details.join(", "));if(!previous){target.appendChild(extra);extra.addEventListener("click",event=>{event.stopPropagation();const current=extra._cxAggregateText;this.showAggregateMenu({id:current.bindings[0].column,title:current.title},current.bindings,current.values,extra,current.text).catch(error=>this.emit("error",{error}))})}
|
|
69
72
|
cell.title=(cell.title?cell.title+" · ":"")+ parts.join(" · ")},syncSummaryControls(){if(this.statusBar&&this.statusGroupSummary!==this.summary){this.statusGroupSummary=this.summary;this.statusGroups??=h("span");this.statusCount.after(this.statusGroups);this.statusGroups.hidden=!this.summary?.groups.length;if(this.summary)setText(this.statusGroups,fill(this.labels.gridGroupCount,{count:numberFormat(this.lang).format(this.summary.groups.length)}))}
|
|
70
73
|
if(!this.summaryControls)return;this.summaryControls.hidden=!this.summary;if(!this.summary)return;if(this.summaryControls.parentElement!==this.grid)this.grid.appendChild(this.summaryControls);const count=this.rowProjection?this.rowProjection.rowCount():this.rowCount();this.grid.setAttribute("aria-rowcount",String(count+2 +(this.headDepth||0)));const key=[this.summary,count,this.layout,this.rowWidth,this.lang,...this.cols.map(column=>column.renderWidth+":"+column.effectivePin)];if(this.summaryRenderKey?.every((value,index)=>value===key[index]))return;this.summaryRenderKey=key;this.summaryControls.replaceChildren();const row=h("div","cx-summary-row");row.setAttribute("role","row");row.setAttribute("aria-rowindex",String(count+2 +(this.headDepth||0)));row.style.width=this.rowWidth+"px";this.cols.forEach((column,index)=>{const cell=this.newCell(index,column.width,column.kind);cell.setAttribute("role","gridcell");cell.style.width=column.renderWidth+"px";const aggregates=this.view.reporting.aggregates.filter(item=>item.column===column.id);if(aggregates.length)this.paintAggregates(cell,column,aggregates,this.summary.aggregates);else if(index===0){setText(cell,this.labels.gridSummary);cell.classList.add("cx-summary-caption")}
|
|
71
74
|
if(index===0)this.paintHiddenAggregates(cell,this.summary.aggregates);row.appendChild(cell)});this.summaryControls.appendChild(row)}});const GROUP_CONTROL_BASE={};for(const name of["buildHeader","querySortHeader"])GROUP_CONTROL_BASE[name]=DataGrid.prototype[name];Object.assign(DataGrid.prototype,{attachGroupControls(){const reporting=this.view.reporting||{};this.groupingDynamic=reportingDynamicGroups(this.view);if(reporting.grouping||this.groupingDynamic){this.groupBar=h("div","cx-groupbar");this.groupBar.setAttribute("role","group");this.groupBar.setAttribute("aria-label",this.labels.gridGroupedBy);this.groupBar.hidden=this.opts.toolbar===false;this.notice.before(this.groupBar)}
|
|
72
75
|
if(reporting.aggregates?.length){this.summaryControls=h("div","cx-grid-summary");this.summaryControls.setAttribute("role","rowgroup");this.summaryControls.setAttribute("aria-label",this.labels.gridSummary);this.summaryControls.hidden=true}
|
|
73
|
-
|
|
76
|
+
this.syncGroupBar();this.buildHeader()},buildHeader(){GROUP_CONTROL_BASE.buildHeader.call(this);const column=this.view.reporting?.grouping?.column;const header=column&&this.headCells.find(cell=>cell.getAttribute("data-cx-column")===column),button=header?.querySelector(".cx-sort");if(button){button.disabled=true;button.title=this.labels.gridGroupOrder}},groupLevelsNow(){return this.view.reporting.grouping?[this.view.reporting.grouping]:this.queryForChange().groupBy||[]},querySortHeader(id,event){const levels=this.groupingDynamic&&this.groupLevelsNow();if(!levels||!levels.some(level=>level.column===id))return GROUP_CONTROL_BASE.querySortHeader.call(this,id,event);this.setGroupBy(levels.map(level=>level.column===id?{...level,direction:level.direction==="asc"?"desc":"asc"}:level)).catch(()=>{})},appendColumnGroupActions(column,add,separator){if(!this.groupingDynamic||!column.sortable)return;const id=column.id,levels=this.groupLevelsNow(),grouped=levels.some(level=>level.column===id);if(!grouped&&!this.view.reporting?.groupable)return;separator();add(grouped?this.labels.gridUngroup:this.labels.gridGroupBy,()=>{const latest=this.groupLevelsNow(),present=latest.some(level=>level.column===id);if(this.destroyed||!this.groupingDynamic||!this.columns.some(item=>item.id===id&&item.sortable)||
|
|
77
|
+
grouped!==present||!grouped&&(!this.view.reporting?.groupable||latest.length>=4))return;return this.setGroupBy(grouped?latest.filter(level=>level.column!==id):[...latest,{column:id,direction:"asc"}])},!grouped&&levels.length>=4)},groupDrop(column){const levels=this.groupingDynamic&&this.groupLevelsNow();if(!levels||!this.view.reporting?.groupable||!column.sortable||levels.length>=4||levels.some(level=>level.column===column.id))return false;this.setGroupBy([...levels,{column:column.id,direction:"asc"}]).catch(error=>this.emit("error",{error}));return true},syncGroupBar(){const bar=this.groupBar;if(!bar)return;const levels=this.groupLevelsNow(),levelsKey=JSON.stringify(levels),key=JSON.stringify([levels,this.groupCollapseVersion||0]);if(bar._levelsKey!==undefined&&bar._levelsKey!==levelsKey&&this.gridPopover?.panel.classList.contains("cx-column-menu"))
|
|
78
|
+
this.closeGridPopover(false);bar._levelsKey=levelsKey;if(bar._key===key&&bar._summary===this.summary)return;const active=bar.contains(document.activeElement)?document.activeElement:null,chip=active?.closest(".cx-gchip");const place=this.groupChipFocus||active&&{level:chip?Number(chip.dataset.cxLevel):0,control:[...(chip||bar).querySelectorAll("button,select")].indexOf(active)};this.groupChipFocus=null;bar._key=key;bar._summary=this.summary;bar.replaceChildren();if(place)queueMicrotask(()=>{const scope=place.level?bar.querySelector('.cx-gchip[data-cx-level="'+place.level+'"]'):bar;const controls=[...(scope||bar).querySelectorAll("button,select")];(controls[Math.max(0,Math.min(controls.length-1,place.control))]||bar.querySelector("button,select"))?.focus()});const lead=h("span","cx-groupbar-label");setText(lead,this.labels.gridGroupedBy);bar.appendChild(lead);if(this.view.reporting.grouping){const chip=h("span","cx-gchip");setText(chip,this.columns.find(column=>column.id===levels[0].column).title);if(typeof this.opts.onUngroup==="function"){const remove=gridDecorateButton(gridButton("",()=>this.runGridHook(signal=>this.opts.onUngroup({query:this.getQuery(),signal}),this.dataLifetime.signal)
|
|
74
79
|
.catch(error=>this.emit("error",{error}))),"close",true);remove.setAttribute("aria-label",this.labels.gridRemoveGrouping);chip.appendChild(remove)}
|
|
75
80
|
bar.appendChild(chip);return}
|
|
76
81
|
if(!levels.length){const hint=h("span","cx-groupbar-hint");setText(hint,this.labels.gridGroupDrop);bar.appendChild(hint);return}
|
|
77
82
|
levels.forEach((level,index)=>{if(index){const next=h("span","cx-groupbar-next");next.setAttribute("aria-hidden","true");setText(next,"›");bar.appendChild(next)}
|
|
78
|
-
bar.appendChild(this.groupChip(levels,level,index))});const spacer=h("span","cx-groupbar-spacer");bar.appendChild(spacer);const busy=!this.summary;for(const[label,collapsed]of[[this.labels.gridExpandAll,false],[this.labels.gridCollapseAll,true]]){const button=gridButton(label,()=>{if(!this.pendingQuery)this.setGroupLevelCollapsed(0,collapsed)});button.classList.add("cx-groupbar-all");button.disabled=busy;bar.appendChild(button)}},groupChip(levels,level,index){const column=this.columns.find(item=>item.id===level.column),chip=h("span","cx-gchip"),name=h("span","cx-gchip-name");const change=next=>this.setGroupBy(next).catch(error=>this.emit("error",{error}));chip.dataset.cxLevel=String(index+1);chip.title=this.labels.gridGroupMove;setText(name,column.title);chip.appendChild(name);const descending=level.direction==="desc",direction=gridDecorateButton(gridButton("",()=>
|
|
83
|
+
bar.appendChild(this.groupChip(levels,level,index))});const spacer=h("span","cx-groupbar-spacer");bar.appendChild(spacer);const busy=!this.summary;for(const[label,collapsed]of[[this.labels.gridExpandAll,false],[this.labels.gridCollapseAll,true]]){const button=gridButton(label,()=>{if(!this.pendingQuery)this.setGroupLevelCollapsed(0,collapsed)});button.classList.add("cx-groupbar-all");button.disabled=busy;bar.appendChild(button)}},groupChip(levels,level,index){const column=this.columns.find(item=>item.id===level.column),chip=h("span","cx-gchip"),name=h("span","cx-gchip-name");const change=next=>this.setGroupBy(next).catch(error=>this.emit("error",{error}));chip.dataset.cxLevel=String(index+1);chip.title=this.labels.gridGroupMove;setText(name,column.title);chip.appendChild(name);this.groupBucketControls(chip,levels,level,column);const descending=level.direction==="desc",direction=gridDecorateButton(gridButton("",()=>
|
|
79
84
|
change(levels.map(item=>item===level?{...item,direction:descending?"asc":"desc"}:item))),descending?"down":"up",true);direction.classList.add("cx-gchip-direction");direction.setAttribute("aria-label",column.title+": " +(descending?this.labels.gridSortAscending:this.labels.gridSortDescending));direction.setAttribute("aria-pressed",String(descending));chip.appendChild(direction);const aggregates=this.view.reporting.aggregates||[];if(aggregates.length){const order=h("select","cx-gchip-order");order.setAttribute("aria-label",column.title+": "+this.labels.gridGroupSortBy);const option=(value,text)=>{const item=h("option");item.value=value;setText(item,text);order.appendChild(item)};option("",this.labels.gridGroupSortValue);aggregates.forEach(item=>option(item.id,fill(this.labels.gridGroupSortAggregate,{aggregate:item.label})));order.value=level.aggregate||"";order.addEventListener("change",()=>change(levels.map(item=>{if(item!==level)return item;const{aggregate,...rest}=item;return order.value?{...rest,aggregate:order.value}:rest})));chip.appendChild(order)}
|
|
80
85
|
const keys=this.groupKeys(index+1),allCollapsed=keys.length>0&&keys.every(key=>this.collapsedGroups.has(key));const fold=gridButton(allCollapsed?"+":"−",()=>{if(!this.pendingQuery)this.setGroupLevelCollapsed(index+1,!allCollapsed)});fold.classList.add("cx-gchip-fold");fold.disabled=!keys.length;fold.setAttribute("aria-label",fill(allCollapsed?this.labels.gridExpandLevel:this.labels.gridCollapseLevel,{level:index+1}));fold.title=fold.getAttribute("aria-label");chip.appendChild(fold);const remove=gridDecorateButton(gridButton("",()=>change(levels.filter(item=>item!==level))),"close",true);remove.setAttribute("aria-label",column.title+": "+this.labels.gridUngroup);chip.appendChild(remove);chip.addEventListener("keydown",event=>{if(!event.altKey||!["ArrowLeft","ArrowRight"].includes(event.key))return;const target=index +(event.key==="ArrowLeft"?-1:1);if(target<0||target>=levels.length)return;event.preventDefault();const next=levels.slice();next.splice(target,0,next.splice(index,1)[0]);this.groupChipFocus={level:target+1,control:[...chip.querySelectorAll("button,select")].indexOf(event.target)};change(next)});name.addEventListener("pointerdown",event=>this.dragGroupChip(event,levels,index,chip));return chip},dragGroupChip(event,levels,index,chip){if(event.button!==0||this.pendingQuery)return;event.preventDefault();const pointer=event.pointerId,startX=event.clientX;let ghost=null,target=index;const chips=[...this.groupBar.querySelectorAll(".cx-gchip")];const move=ev=>{if(ev.pointerId!==pointer||!ghost&&Math.abs(ev.clientX-startX)<5)return;if(!ghost){ghost=h("div","cx-column-drag");ghost.setAttribute("aria-hidden","true");setText(ghost,chip.querySelector(".cx-gchip-name").textContent);document.body.appendChild(ghost)}
|
|
81
86
|
ghost.style.left=ev.clientX+12+"px";ghost.style.top=ev.clientY+12+"px";const before=chips.filter(item=>{const box=item.getBoundingClientRect();return ev.clientX>box.left+box.width / 2; }).length;
|
|
82
|
-
target=before>index?before-1:before};const stop=ev=>{if(ev&&ev.pointerId!==undefined&&ev.pointerId!==pointer)return;this.dragGroupChipEnd?.();const dropped=ghost&&ev?.type==="pointerup";ghost?.remove();if(dropped&&target!==index){const next=levels.slice();next.splice(target,0,next.splice(index,1)[0]);this.setGroupBy(next).catch(error=>this.emit("error",{error}))}};const cancel=ev=>{if(ev.pointerId===pointer){ghost?.remove();ghost=null;stop()}};const drag=new AbortController(),listen={signal:AbortSignal.any([drag.signal,this.lifetime.signal])};global.addEventListener("pointermove",move,listen);global.addEventListener("pointerup",stop,listen);global.addEventListener("pointercancel",cancel,listen);this.lifetime.signal.addEventListener("abort",()=>ghost?.remove(),{once:true,signal:drag.signal});this.dragGroupChipEnd=()=>drag.abort()}});
|
|
87
|
+
target=before>index?before-1:before};const stop=ev=>{if(ev&&ev.pointerId!==undefined&&ev.pointerId!==pointer)return;this.dragGroupChipEnd?.();const dropped=ghost&&ev?.type==="pointerup";ghost?.remove();if(dropped&&target!==index){const next=levels.slice();next.splice(target,0,next.splice(index,1)[0]);this.setGroupBy(next).catch(error=>this.emit("error",{error}))}};const cancel=ev=>{if(ev.pointerId===pointer){ghost?.remove();ghost=null;stop()}};const drag=new AbortController(),listen={signal:AbortSignal.any([drag.signal,this.lifetime.signal])};global.addEventListener("pointermove",move,listen);global.addEventListener("pointerup",stop,listen);global.addEventListener("pointercancel",cancel,listen);this.lifetime.signal.addEventListener("abort",()=>ghost?.remove(),{once:true,signal:drag.signal});this.dragGroupChipEnd=()=>drag.abort()}});DataGrid.prototype.groupBucketControls=function(chip,levels,level,column){if(!["number","datetime"].includes(column.kind))return;const select=h("select","cx-select cx-gchip-order cx-gchip-bucket"),labels=this.labels;select.setAttribute("aria-label",column.title+": "+labels.gridBucket);const choices=column.kind==="datetime"?["day","week","month","quarter","year","hour","weekday"]:["width","edges"];for(const kind of["",...choices]){const option=h("option");option.value=kind;setText(option,kind?labels["gridBucket"+kind[0].toUpperCase()+ kind.slice(1)]:labels.gridBucketNone);select.append(option)}
|
|
88
|
+
select.value=level.bucket?.kind||"";select.title=labels.gridBucket+": "+select.selectedOptions[0].textContent;const apply=bucket=>this.setGroupBy(levels.map(item=>{if(item!==level)return item;const{bucket:old,...rest}=item;return bucket?{...rest,bucket}:rest})).catch(error=>this.emit("error",{error}));select.addEventListener("change",()=>{const kind=select.value;apply(!kind?null:kind==="width"?{kind,width:10,origin:0}:kind==="edges"?{kind,edges:[0,10,100]}:{kind,timeZone:level.bucket?.timeZone||"UTC",firstWeekday:level.bucket?.firstWeekday??1})});chip.append(select);if(!["width","edges"].includes(level.bucket?.kind))return;const input=(name,value,type,read)=>{const field=h("input","cx-input cx-gchip-bucket-value");field.type=type;field.value=String(value);if(type==="number")field.step="any";else field.maxLength=4096;field.setAttribute("aria-label",column.title+": "+labels[name]);field.title=labels[name];field.addEventListener("change",()=>{try{const bucket=gridBucketDefinition(read(field.value),column);field.setCustomValidity("");apply(bucket)}
|
|
89
|
+
catch(_){field.setCustomValidity(labels.gridBucketInvalid);field.reportValidity()}});chip.append(field)};if(level.bucket.kind==="width"){input("gridBucketWidth",level.bucket.width,"number",text=>({...level.bucket,width:text.trim()?Number(text):NaN}));input("gridBucketOrigin",level.bucket.origin,"number",text=>({...level.bucket,origin:text.trim()?Number(text):NaN}))}else input("gridBucketEdges",level.bucket.edges.join(", "),"text",text=>({kind:"edges",edges:text.split(",").map(item=>item.trim()?Number(item):NaN)}))};const GROUP_QUERY=DataGrid.prototype.setQuery;Object.assign(DataGrid.prototype,{projectedRowKey(event,row){if(!row.group)return false;const cell=event.target.closest(".cx-cell");if(cell&&event.target===cell&&["Enter"," "].includes(event.key)){if(event.key==="Enter")this.focusCell(row,this.rowCells(cell.parentElement).indexOf(cell),0,true);event.preventDefault();return true}
|
|
83
90
|
if(cell&&(["ArrowLeft","ArrowRight","Home","End","Escape","F2"].includes(event.key)||
|
|
84
91
|
event.target!==cell&&["Enter"," "].includes(event.key)))return TreeGrid.prototype.onCellKey.call(this,event);if(event.key==="F2"){this.focusCell(row,0,0,true);event.preventDefault();return true}
|
|
85
92
|
if(!["ArrowLeft","ArrowRight","Enter"," "].includes(event.key))return false;if(event.target.closest("button,input,select")&&["Enter"," "].includes(event.key))return true;event.preventDefault();if(this.pendingQuery)return true;const collapsed=this.collapsedGroups.has(row.group.key),rows=this.rowProjection;if(event.key==="ArrowRight"&&!collapsed&&this.groupTree){const next=rows.rowItem(rows.indexOf(row)+ 1);if(next)this.focusProjected(next);return true}
|