graphein 0.20.0 → 0.22.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/dist/animation/animate.d.ts +6 -1
- package/dist/animation/animate.d.ts.map +1 -1
- package/dist/animation/animate.js +2 -2
- package/dist/animation/animate.js.map +2 -2
- package/dist/animation/env.d.ts +5 -0
- package/dist/animation/env.d.ts.map +1 -1
- package/dist/animation/env.js +4 -0
- package/dist/animation/env.js.map +2 -2
- package/dist/animation/index.d.ts +1 -0
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/animation/index.js +1 -0
- package/dist/animation/index.js.map +2 -2
- package/dist/animation/stagger.d.ts +13 -0
- package/dist/animation/stagger.d.ts.map +1 -0
- package/dist/animation/stagger.js +13 -0
- package/dist/animation/stagger.js.map +7 -0
- package/dist/axes/draw.d.ts +5 -1
- package/dist/axes/draw.d.ts.map +1 -1
- package/dist/axes/draw.js +13 -1
- package/dist/axes/draw.js.map +2 -2
- package/dist/axes/morph.d.ts +111 -0
- package/dist/axes/morph.d.ts.map +1 -0
- package/dist/axes/morph.js +207 -0
- package/dist/axes/morph.js.map +7 -0
- package/dist/axes/overlay.d.ts.map +1 -1
- package/dist/axes/overlay.js +88 -25
- package/dist/axes/overlay.js.map +2 -2
- package/dist/axes/text.d.ts +2 -0
- package/dist/axes/text.d.ts.map +1 -1
- package/dist/axes/text.js +1 -0
- package/dist/axes/text.js.map +2 -2
- package/dist/axes/tickLabels.d.ts +2 -0
- package/dist/axes/tickLabels.d.ts.map +1 -1
- package/dist/axes/tickLabels.js +2 -2
- package/dist/axes/tickLabels.js.map +2 -2
- package/dist/charts/annotations.d.ts +9 -3
- package/dist/charts/annotations.d.ts.map +1 -1
- package/dist/charts/annotations.js +82 -27
- package/dist/charts/annotations.js.map +2 -2
- package/dist/charts/area.d.ts +37 -1
- package/dist/charts/area.d.ts.map +1 -1
- package/dist/charts/area.js +35 -17
- package/dist/charts/area.js.map +2 -2
- package/dist/charts/bar.d.ts +53 -0
- package/dist/charts/bar.d.ts.map +1 -1
- package/dist/charts/bar.js +117 -83
- package/dist/charts/bar.js.map +2 -2
- package/dist/charts/box.d.ts +31 -0
- package/dist/charts/box.d.ts.map +1 -1
- package/dist/charts/box.js +93 -70
- package/dist/charts/box.js.map +2 -2
- package/dist/charts/bubbleMap.d.ts +20 -0
- package/dist/charts/bubbleMap.d.ts.map +1 -0
- package/dist/charts/bubbleMap.js +951 -0
- package/dist/charts/bubbleMap.js.map +7 -0
- package/dist/charts/bullet.d.ts.map +1 -1
- package/dist/charts/bullet.js +69 -51
- package/dist/charts/bullet.js.map +2 -2
- package/dist/charts/calendarHeatmap.d.ts.map +1 -1
- package/dist/charts/calendarHeatmap.js +56 -19
- package/dist/charts/calendarHeatmap.js.map +2 -2
- package/dist/charts/candlestick.d.ts +40 -0
- package/dist/charts/candlestick.d.ts.map +1 -0
- package/dist/charts/candlestick.js +325 -0
- package/dist/charts/candlestick.js.map +7 -0
- package/dist/charts/choropleth.d.ts.map +1 -1
- package/dist/charts/choropleth.js +46 -67
- package/dist/charts/choropleth.js.map +2 -2
- package/dist/charts/combo.d.ts.map +1 -1
- package/dist/charts/combo.js +127 -27
- package/dist/charts/combo.js.map +3 -3
- package/dist/charts/dumbbell.d.ts.map +1 -1
- package/dist/charts/dumbbell.js +100 -31
- package/dist/charts/dumbbell.js.map +2 -2
- package/dist/charts/funnel.d.ts.map +1 -1
- package/dist/charts/funnel.js +93 -28
- package/dist/charts/funnel.js.map +3 -3
- package/dist/charts/gantt.d.ts +22 -0
- package/dist/charts/gantt.d.ts.map +1 -0
- package/dist/charts/gantt.js +564 -0
- package/dist/charts/gantt.js.map +7 -0
- package/dist/charts/gauge.d.ts.map +1 -1
- package/dist/charts/gauge.js +30 -4
- package/dist/charts/gauge.js.map +2 -2
- package/dist/charts/geo.d.ts +87 -0
- package/dist/charts/geo.d.ts.map +1 -0
- package/dist/charts/geo.js +140 -0
- package/dist/charts/geo.js.map +7 -0
- package/dist/charts/geometry.d.ts +20 -0
- package/dist/charts/geometry.d.ts.map +1 -0
- package/dist/charts/geometry.js +25 -0
- package/dist/charts/geometry.js.map +7 -0
- package/dist/charts/heatmap.d.ts.map +1 -1
- package/dist/charts/heatmap.js +58 -49
- package/dist/charts/heatmap.js.map +2 -2
- package/dist/charts/histogram.d.ts +1 -1
- package/dist/charts/histogram.d.ts.map +1 -1
- package/dist/charts/histogram.js +49 -31
- package/dist/charts/histogram.js.map +2 -2
- package/dist/charts/index.d.ts +35 -1
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +12 -0
- package/dist/charts/index.js.map +2 -2
- package/dist/charts/legibility.d.ts +38 -0
- package/dist/charts/legibility.d.ts.map +1 -0
- package/dist/charts/legibility.js +72 -0
- package/dist/charts/legibility.js.map +7 -0
- package/dist/charts/line.d.ts +39 -1
- package/dist/charts/line.d.ts.map +1 -1
- package/dist/charts/line.js +48 -16
- package/dist/charts/line.js.map +2 -2
- package/dist/charts/matrix.d.ts +2 -1
- package/dist/charts/matrix.d.ts.map +1 -1
- package/dist/charts/matrix.js +481 -319
- package/dist/charts/matrix.js.map +3 -3
- package/dist/charts/morphFrame.d.ts +83 -0
- package/dist/charts/morphFrame.d.ts.map +1 -0
- package/dist/charts/morphFrame.js +128 -0
- package/dist/charts/morphFrame.js.map +7 -0
- package/dist/charts/pie.d.ts.map +1 -1
- package/dist/charts/pie.js +89 -26
- package/dist/charts/pie.js.map +2 -2
- package/dist/charts/pieState.d.ts +27 -0
- package/dist/charts/pieState.d.ts.map +1 -0
- package/dist/charts/pieState.js +55 -0
- package/dist/charts/pieState.js.map +7 -0
- package/dist/charts/radar.d.ts +62 -0
- package/dist/charts/radar.d.ts.map +1 -0
- package/dist/charts/radar.js +912 -0
- package/dist/charts/radar.js.map +7 -0
- package/dist/charts/radialBar.d.ts +60 -0
- package/dist/charts/radialBar.d.ts.map +1 -0
- package/dist/charts/radialBar.js +708 -0
- package/dist/charts/radialBar.js.map +7 -0
- package/dist/charts/sankey.d.ts.map +1 -1
- package/dist/charts/sankey.js +223 -57
- package/dist/charts/sankey.js.map +3 -3
- package/dist/charts/scatter.d.ts +31 -0
- package/dist/charts/scatter.d.ts.map +1 -1
- package/dist/charts/scatter.js +48 -12
- package/dist/charts/scatter.js.map +2 -2
- package/dist/charts/slope.d.ts.map +1 -1
- package/dist/charts/slope.js +55 -3
- package/dist/charts/slope.js.map +2 -2
- package/dist/charts/sunburst.d.ts +14 -0
- package/dist/charts/sunburst.d.ts.map +1 -0
- package/dist/charts/sunburst.js +885 -0
- package/dist/charts/sunburst.js.map +7 -0
- package/dist/charts/table.d.ts +2 -1
- package/dist/charts/table.d.ts.map +1 -1
- package/dist/charts/table.js +214 -224
- package/dist/charts/table.js.map +3 -3
- package/dist/charts/tableView/canvas.d.ts +16 -1
- package/dist/charts/tableView/canvas.d.ts.map +1 -1
- package/dist/charts/tableView/canvas.js +361 -252
- package/dist/charts/tableView/canvas.js.map +3 -3
- package/dist/charts/tableView/conditional.d.ts +66 -40
- package/dist/charts/tableView/conditional.d.ts.map +1 -1
- package/dist/charts/tableView/conditional.js +163 -256
- package/dist/charts/tableView/conditional.js.map +3 -3
- package/dist/charts/tableView/dom.d.ts +26 -2
- package/dist/charts/tableView/dom.d.ts.map +1 -1
- package/dist/charts/tableView/dom.js +609 -269
- package/dist/charts/tableView/dom.js.map +3 -3
- package/dist/charts/tableView/layout.d.ts +22 -0
- package/dist/charts/tableView/layout.d.ts.map +1 -0
- package/dist/charts/tableView/layout.js +246 -0
- package/dist/charts/tableView/layout.js.map +7 -0
- package/dist/charts/tableView/sketch.d.ts +3 -2
- package/dist/charts/tableView/sketch.d.ts.map +1 -1
- package/dist/charts/tableView/sketch.js +2 -2
- package/dist/charts/tableView/sketch.js.map +2 -2
- package/dist/charts/tableView/sketchBar.d.ts +7 -0
- package/dist/charts/tableView/sketchBar.d.ts.map +1 -0
- package/dist/charts/tableView/sketchBar.js +32 -0
- package/dist/charts/tableView/sketchBar.js.map +7 -0
- package/dist/charts/tableView/sort.d.ts +9 -0
- package/dist/charts/tableView/sort.d.ts.map +1 -0
- package/dist/charts/tableView/sort.js +70 -0
- package/dist/charts/tableView/sort.js.map +7 -0
- package/dist/charts/tableView/sparkline.d.ts +30 -0
- package/dist/charts/tableView/sparkline.d.ts.map +1 -0
- package/dist/charts/tableView/sparkline.js +63 -0
- package/dist/charts/tableView/sparkline.js.map +7 -0
- package/dist/charts/tableView/style.d.ts +67 -0
- package/dist/charts/tableView/style.d.ts.map +1 -0
- package/dist/charts/tableView/style.js +131 -0
- package/dist/charts/tableView/style.js.map +7 -0
- package/dist/charts/tableView/types.d.ts +69 -46
- package/dist/charts/tableView/types.d.ts.map +1 -1
- package/dist/charts/tableView/types.js +22 -87
- package/dist/charts/tableView/types.js.map +2 -2
- package/dist/charts/tableView.d.ts +10 -5
- package/dist/charts/tableView.d.ts.map +1 -1
- package/dist/charts/tableView.js +12 -8
- package/dist/charts/tableView.js.map +2 -2
- package/dist/charts/treemap.d.ts.map +1 -1
- package/dist/charts/treemap.js +177 -68
- package/dist/charts/treemap.js.map +3 -3
- package/dist/charts/trendline.d.ts +13 -5
- package/dist/charts/trendline.d.ts.map +1 -1
- package/dist/charts/trendline.js +205 -56
- package/dist/charts/trendline.js.map +2 -2
- package/dist/charts/waterfall.d.ts.map +1 -1
- package/dist/charts/waterfall.js +76 -5
- package/dist/charts/waterfall.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interaction/cartesian.d.ts +4 -1
- package/dist/interaction/cartesian.d.ts.map +1 -1
- package/dist/interaction/cartesian.js +104 -34
- package/dist/interaction/cartesian.js.map +2 -2
- package/dist/interaction/controller.d.ts +29 -1
- package/dist/interaction/controller.d.ts.map +1 -1
- package/dist/interaction/controller.js +131 -8
- package/dist/interaction/controller.js.map +2 -2
- package/dist/interaction/focus.d.ts +23 -0
- package/dist/interaction/focus.d.ts.map +1 -0
- package/dist/interaction/focus.js +65 -0
- package/dist/interaction/focus.js.map +7 -0
- package/dist/interaction/tooltip.d.ts +6 -0
- package/dist/interaction/tooltip.d.ts.map +1 -1
- package/dist/interaction/tooltip.js +41 -16
- package/dist/interaction/tooltip.js.map +2 -2
- package/dist/interaction/types.d.ts +19 -0
- package/dist/interaction/types.d.ts.map +1 -1
- package/dist/interaction/veil.d.ts +25 -0
- package/dist/interaction/veil.d.ts.map +1 -0
- package/dist/interaction/veil.js +35 -0
- package/dist/interaction/veil.js.map +7 -0
- package/dist/pivot/pivot.d.ts +18 -0
- package/dist/pivot/pivot.d.ts.map +1 -1
- package/dist/pivot/pivot.js +46 -34
- package/dist/pivot/pivot.js.map +2 -2
- package/dist/render/chromeMotion.d.ts +65 -0
- package/dist/render/chromeMotion.d.ts.map +1 -0
- package/dist/render/chromeMotion.js +79 -0
- package/dist/render/chromeMotion.js.map +7 -0
- package/dist/render/pathSample.d.ts +24 -0
- package/dist/render/pathSample.d.ts.map +1 -0
- package/dist/render/pathSample.js +76 -0
- package/dist/render/pathSample.js.map +7 -0
- package/dist/render/transient.d.ts +18 -0
- package/dist/render/transient.d.ts.map +1 -0
- package/dist/render/transient.js +19 -0
- package/dist/render/transient.js.map +7 -0
- package/dist/runtime/candlestick.d.ts +112 -0
- package/dist/runtime/candlestick.d.ts.map +1 -0
- package/dist/runtime/candlestick.js +531 -0
- package/dist/runtime/candlestick.js.map +7 -0
- package/dist/runtime/cartesian.d.ts +14 -3
- package/dist/runtime/cartesian.d.ts.map +1 -1
- package/dist/runtime/cartesian.js.map +2 -2
- package/dist/runtime/chartAnimation.d.ts +54 -7
- package/dist/runtime/chartAnimation.d.ts.map +1 -1
- package/dist/runtime/chartAnimation.js +146 -28
- package/dist/runtime/chartAnimation.js.map +2 -2
- package/dist/runtime/chartRuntime.d.ts +42 -0
- package/dist/runtime/chartRuntime.d.ts.map +1 -1
- package/dist/runtime/chartRuntime.js +196 -30
- package/dist/runtime/chartRuntime.js.map +2 -2
- package/dist/runtime/dashboardDom.d.ts.map +1 -1
- package/dist/runtime/dashboardDom.js +45 -0
- package/dist/runtime/dashboardDom.js.map +2 -2
- package/dist/runtime/facet.d.ts +1 -1
- package/dist/runtime/facet.d.ts.map +1 -1
- package/dist/runtime/gantt.d.ts +137 -0
- package/dist/runtime/gantt.d.ts.map +1 -0
- package/dist/runtime/gantt.js +647 -0
- package/dist/runtime/gantt.js.map +7 -0
- package/dist/runtime/morph.d.ts +33 -0
- package/dist/runtime/morph.d.ts.map +1 -0
- package/dist/runtime/morph.js +332 -0
- package/dist/runtime/morph.js.map +7 -0
- package/dist/runtime/radar.d.ts +75 -0
- package/dist/runtime/radar.d.ts.map +1 -0
- package/dist/runtime/radar.js +201 -0
- package/dist/runtime/radar.js.map +7 -0
- package/dist/runtime/radialBar.d.ts +81 -0
- package/dist/runtime/radialBar.d.ts.map +1 -0
- package/dist/runtime/radialBar.js +125 -0
- package/dist/runtime/radialBar.js.map +7 -0
- package/dist/runtime/report/constants.d.ts +2 -2
- package/dist/runtime/report/constants.d.ts.map +1 -1
- package/dist/runtime/runtimeShared.d.ts +3 -3
- package/dist/runtime/runtimeShared.d.ts.map +1 -1
- package/dist/runtime/sunburst.d.ts +74 -0
- package/dist/runtime/sunburst.d.ts.map +1 -0
- package/dist/runtime/sunburst.js +150 -0
- package/dist/runtime/sunburst.js.map +7 -0
- package/dist/runtime/wire.d.ts.map +1 -1
- package/dist/runtime/wire.js +3 -1
- package/dist/runtime/wire.js.map +2 -2
- package/dist/shape/arc.d.ts +15 -2
- package/dist/shape/arc.d.ts.map +1 -1
- package/dist/shape/arc.js +204 -32
- package/dist/shape/arc.js.map +2 -2
- package/dist/spec/chartDefinitions.d.ts +6 -0
- package/dist/spec/chartDefinitions.d.ts.map +1 -1
- package/dist/spec/chartDefinitions.js +7 -1
- package/dist/spec/chartDefinitions.js.map +2 -2
- package/dist/spec/templates.d.ts.map +1 -1
- package/dist/spec/templates.js +177 -2
- package/dist/spec/templates.js.map +2 -2
- package/dist/spec/types.d.ts +258 -6
- package/dist/spec/types.d.ts.map +1 -1
- package/dist/spec/types.js +6 -0
- package/dist/spec/types.js.map +2 -2
- package/dist/spec/validate/charts.js +147 -15
- package/dist/spec/validate/charts.js.map +2 -2
- package/dist/spec/validate/common.d.ts +6 -0
- package/dist/spec/validate/common.d.ts.map +1 -1
- package/dist/spec/validate/overlays.js +2 -2
- package/dist/spec/validate/overlays.js.map +2 -2
- package/dist/spec/validate.data.d.ts.map +1 -1
- package/dist/spec/validate.data.js +8 -3
- package/dist/spec/validate.data.js.map +2 -2
- package/package.json +1 -1
|
@@ -1,299 +1,639 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1
4
|
import { recordDomLabels } from "../../render/labelLedger.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
5
|
+
import { measureText } from "../../render/text.js";
|
|
6
|
+
import {
|
|
7
|
+
BAR_LANE_ALPHA,
|
|
8
|
+
BAR_OVERLAY_ALPHA,
|
|
9
|
+
barFill,
|
|
10
|
+
barTrack,
|
|
11
|
+
buildColumnFormatter,
|
|
12
|
+
negativeTextColor
|
|
13
|
+
} from "./conditional.js";
|
|
14
|
+
import { buildSketchDataBar } from "./sketchBar.js";
|
|
15
|
+
import { createSketchGridCanvas, paintSketchGridOverlay } from "./sketch.js";
|
|
16
|
+
import { columnOffsets, layoutColumns } from "./layout.js";
|
|
17
|
+
import { fontFor, resolveTableStyle, rowBackground, tableStylesheet } from "./style.js";
|
|
18
|
+
import { sparklinePath } from "./sparkline.js";
|
|
19
|
+
import {
|
|
20
|
+
SKETCH_BORDER_RADIUS,
|
|
21
|
+
cellText,
|
|
22
|
+
clampInt,
|
|
23
|
+
defaultRowInfo,
|
|
24
|
+
normalizedHeaderRows,
|
|
25
|
+
setStyles,
|
|
26
|
+
sumWidths
|
|
27
|
+
} from "./types.js";
|
|
28
|
+
const RENDER_ALL_CELLS = 2400;
|
|
29
|
+
const RENDER_ALL_ROWS = 250;
|
|
30
|
+
const BUFFER_ROWS = 6;
|
|
31
|
+
const DEFAULT_FORMAT_KINDS = ["leaf"];
|
|
32
|
+
let scopeSeq = 0;
|
|
4
33
|
let cachedScrollbarWidth = null;
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
const reserve = willScrollVertically(opts) ? scrollbarWidth() : 0;
|
|
8
|
-
const available = Math.max(0, rect.width - 2 - reserve);
|
|
9
|
-
opts.widths = computeFittedWidths(opts.columns, available);
|
|
10
|
-
const tableWidth = Math.max(available, sumWidths(opts.widths));
|
|
11
|
-
setStyles(container, {
|
|
12
|
-
position: "absolute",
|
|
13
|
-
left: `${rect.x}px`,
|
|
14
|
-
top: `${rect.y}px`,
|
|
15
|
-
width: `${Math.max(0, rect.width)}px`,
|
|
16
|
-
height: `${Math.max(0, rect.height)}px`,
|
|
17
|
-
overflow: "auto",
|
|
18
|
-
pointerEvents: "auto",
|
|
19
|
-
boxSizing: "border-box",
|
|
20
|
-
border: `1px solid ${opts.sketch ? "transparent" : tokens.color.border}`,
|
|
21
|
-
borderRadius: opts.sketch ? SKETCH_BORDER_RADIUS : `${tokens.radius.sm}px`,
|
|
22
|
-
background: tokens.color.background
|
|
23
|
-
});
|
|
24
|
-
container.replaceChildren();
|
|
25
|
-
const table = document.createElement("table");
|
|
26
|
-
table.setAttribute("role", "table");
|
|
27
|
-
setStyles(table, {
|
|
28
|
-
width: `${tableWidth}px`,
|
|
29
|
-
minWidth: "100%",
|
|
30
|
-
borderCollapse: "separate",
|
|
31
|
-
borderSpacing: "0",
|
|
32
|
-
tableLayout: "fixed",
|
|
33
|
-
fontFamily: tokens.font.family,
|
|
34
|
-
fontSize: `${tokens.font.size.small}px`,
|
|
35
|
-
lineHeight: "1.35",
|
|
36
|
-
color: tokens.color.text
|
|
37
|
-
});
|
|
38
|
-
table.appendChild(buildColGroup(opts.widths));
|
|
39
|
-
table.appendChild(buildHeader(opts));
|
|
40
|
-
table.appendChild(buildBody(opts));
|
|
41
|
-
const footer = buildFooter(opts);
|
|
42
|
-
if (footer) table.appendChild(footer);
|
|
43
|
-
container.appendChild(table);
|
|
44
|
-
opts.refreshEvidence = () => recordTableDom(opts, table);
|
|
45
|
-
opts.refreshEvidence();
|
|
34
|
+
function mountTable(opts) {
|
|
35
|
+
return new TableDom(opts);
|
|
46
36
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
rowIndex++;
|
|
37
|
+
class TableDom {
|
|
38
|
+
constructor(opts) {
|
|
39
|
+
__publicField(this, "host");
|
|
40
|
+
__publicField(this, "widths", []);
|
|
41
|
+
__publicField(this, "opts");
|
|
42
|
+
__publicField(this, "scope", `gtv-${++scopeSeq}`);
|
|
43
|
+
__publicField(this, "style");
|
|
44
|
+
__publicField(this, "formatters", []);
|
|
45
|
+
__publicField(this, "layout");
|
|
46
|
+
__publicField(this, "offsets", []);
|
|
47
|
+
__publicField(this, "baseClass", []);
|
|
48
|
+
__publicField(this, "table");
|
|
49
|
+
__publicField(this, "tbody");
|
|
50
|
+
__publicField(this, "topSpacer");
|
|
51
|
+
__publicField(this, "bottomSpacer");
|
|
52
|
+
__publicField(this, "pool", []);
|
|
53
|
+
__publicField(this, "start", 0);
|
|
54
|
+
__publicField(this, "end", 0);
|
|
55
|
+
__publicField(this, "windowed", false);
|
|
56
|
+
__publicField(this, "frame", 0);
|
|
57
|
+
__publicField(this, "mounted", false);
|
|
58
|
+
__publicField(this, "headerRowCount", 1);
|
|
59
|
+
__publicField(this, "hierarchy", false);
|
|
60
|
+
__publicField(this, "bodyFont", "");
|
|
61
|
+
__publicField(this, "boldFont", "");
|
|
62
|
+
__publicField(this, "textWidths", /* @__PURE__ */ new Map());
|
|
63
|
+
__publicField(this, "sketchCanvas", null);
|
|
64
|
+
this.opts = opts;
|
|
65
|
+
this.host = document.createElement("div");
|
|
66
|
+
this.host.className = `graphein-table ${this.scope}`;
|
|
67
|
+
opts.container.appendChild(this.host);
|
|
68
|
+
this.host.addEventListener("scroll", () => this.onScroll(), { passive: true });
|
|
69
|
+
this.build(true);
|
|
81
70
|
}
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
update(next, relayout = false) {
|
|
72
|
+
this.opts = next;
|
|
73
|
+
this.build(relayout || next.columns.length !== this.widths.length);
|
|
84
74
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
75
|
+
build(relayout) {
|
|
76
|
+
const o = this.opts;
|
|
77
|
+
this.style = resolveTableStyle(o.tokens, o.density, o.gridlines);
|
|
78
|
+
const m = this.style.metrics;
|
|
79
|
+
this.bodyFont = fontFor(this.style, this.style.weight.normal);
|
|
80
|
+
this.boldFont = fontFor(this.style, this.style.weight.bold);
|
|
81
|
+
this.formatters = o.formatters ?? o.columns.map((column, i) => buildColumnFormatter(column.conditionalFormat, o.conditionalDomains?.[i] ?? null, o.tokens, this.style.color.background));
|
|
82
|
+
const headerRows = normalizedHeaderRows(o);
|
|
83
|
+
this.headerRowCount = headerRows.length;
|
|
84
|
+
this.hierarchy = this.hasHierarchy();
|
|
85
|
+
const contentHeight = headerRows.length * m.headerHeight + o.rowCount * m.rowHeight + (o.footerRow ? m.rowHeight : 0) + 2;
|
|
86
|
+
const scrollsY = contentHeight > o.rect.height + 1;
|
|
87
|
+
if (relayout || !this.layout) {
|
|
88
|
+
const available = Math.max(0, o.rect.width - 2 - (scrollsY ? scrollbarWidth() : 0));
|
|
89
|
+
const measureInput = o.measure ? { ...o, ...o.measure } : o;
|
|
90
|
+
this.layout = layoutColumns(measureInput, this.style, this.formatters, available, "scroll");
|
|
91
|
+
}
|
|
92
|
+
this.widths = this.layout.widths;
|
|
93
|
+
o.widths = this.widths;
|
|
94
|
+
this.offsets = columnOffsets(this.widths);
|
|
95
|
+
this.windowed = o.rowCount > RENDER_ALL_ROWS || o.rowCount * Math.max(1, o.columns.length) > RENDER_ALL_CELLS;
|
|
96
|
+
const frozen = Math.min(o.frozenColumns ?? 0, o.columns.length);
|
|
97
|
+
this.baseClass = o.columns.map((column, i) => columnClass(column, i, frozen, this.windowed));
|
|
98
|
+
setStyles(this.host, {
|
|
99
|
+
position: "absolute",
|
|
100
|
+
left: `${o.rect.x}px`,
|
|
101
|
+
top: `${o.rect.y}px`,
|
|
102
|
+
width: `${Math.max(0, o.rect.width)}px`,
|
|
103
|
+
maxHeight: `${Math.max(0, o.rect.height)}px`,
|
|
104
|
+
overflow: "auto",
|
|
105
|
+
pointerEvents: "auto",
|
|
106
|
+
boxSizing: "border-box",
|
|
107
|
+
border: `1px solid ${o.sketch ? "transparent" : o.tokens.color.border}`,
|
|
108
|
+
borderRadius: o.sketch ? SKETCH_BORDER_RADIUS : `${this.style.radius}px`,
|
|
109
|
+
background: this.style.color.background,
|
|
110
|
+
overscrollBehavior: "contain"
|
|
111
|
+
});
|
|
112
|
+
const sheet = document.createElement("style");
|
|
113
|
+
sheet.textContent = tableStylesheet(this.style, {
|
|
114
|
+
scope: this.scope,
|
|
115
|
+
stickyHeader: o.stickyHeader !== false,
|
|
116
|
+
frozenOffsets: this.offsets.slice(0, frozen),
|
|
117
|
+
sketch: Boolean(o.sketch)
|
|
118
|
+
});
|
|
119
|
+
const table = document.createElement("table");
|
|
120
|
+
table.setAttribute("role", "table");
|
|
121
|
+
table.style.width = `${sumWidths(this.widths)}px`;
|
|
122
|
+
if (this.windowed) table.setAttribute("aria-rowcount", String(headerRows.length + o.rowCount + (o.footerRow ? 1 : 0)));
|
|
123
|
+
table.appendChild(this.buildColgroup());
|
|
124
|
+
table.appendChild(this.buildHeader(headerRows, frozen));
|
|
125
|
+
this.tbody = document.createElement("tbody");
|
|
126
|
+
this.topSpacer = spacerRow(o.columns.length);
|
|
127
|
+
this.bottomSpacer = spacerRow(o.columns.length);
|
|
128
|
+
this.tbody.addEventListener("click", (event) => this.onBodyClick(event));
|
|
129
|
+
this.tbody.addEventListener("keydown", (event) => this.onBodyKey(event));
|
|
130
|
+
this.host.classList.toggle("gtv-pick", Boolean(o.onRowClick));
|
|
131
|
+
table.appendChild(this.tbody);
|
|
132
|
+
const footer = this.buildFooter(headerRows.length);
|
|
133
|
+
if (footer) table.appendChild(footer);
|
|
134
|
+
this.table = table;
|
|
135
|
+
this.pool = [];
|
|
136
|
+
this.start = 0;
|
|
137
|
+
this.end = 0;
|
|
138
|
+
const restore = this.mounted ? { top: this.host.scrollTop || 0, left: this.host.scrollLeft || 0 } : { top: o.scrollTop ?? 0, left: o.scrollLeft ?? 0 };
|
|
139
|
+
this.mounted = true;
|
|
140
|
+
this.host.replaceChildren(sheet, table);
|
|
141
|
+
this.renderWindow(true, restore.top);
|
|
142
|
+
if (this.host.scrollTop !== restore.top) this.host.scrollTop = restore.top;
|
|
143
|
+
if (this.host.scrollLeft !== restore.left) this.host.scrollLeft = restore.left;
|
|
144
|
+
this.mountSketch(Math.min(o.rect.height, contentHeight));
|
|
145
|
+
this.recordEvidence();
|
|
98
146
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
probe.remove();
|
|
108
|
-
return cachedScrollbarWidth;
|
|
109
|
-
}
|
|
110
|
-
function contentHeight(opts) {
|
|
111
|
-
const headerRows = opts.headerRows?.length ?? 1;
|
|
112
|
-
const metrics = densityMetrics(opts.density);
|
|
113
|
-
const rowHeight = opts.visibleRange?.rowHeight ?? metrics.rowHeight;
|
|
114
|
-
return headerRows * metrics.headerHeight + opts.rowCount * rowHeight + (opts.footerRow ? metrics.rowHeight : 0);
|
|
115
|
-
}
|
|
116
|
-
function willScrollVertically(opts) {
|
|
117
|
-
return contentHeight(opts) > opts.rect.height + 1;
|
|
118
|
-
}
|
|
119
|
-
function sumWidths(widths) {
|
|
120
|
-
return widths.reduce((sum, w) => sum + w, 0);
|
|
121
|
-
}
|
|
122
|
-
function buildColGroup(widths) {
|
|
123
|
-
const colgroup = document.createElement("colgroup");
|
|
124
|
-
for (const width of widths) {
|
|
125
|
-
const col = document.createElement("col");
|
|
126
|
-
col.style.width = `${width}px`;
|
|
127
|
-
colgroup.appendChild(col);
|
|
147
|
+
buildColgroup() {
|
|
148
|
+
const colgroup = document.createElement("colgroup");
|
|
149
|
+
for (const width of this.widths) {
|
|
150
|
+
const col = document.createElement("col");
|
|
151
|
+
col.style.width = `${width}px`;
|
|
152
|
+
colgroup.appendChild(col);
|
|
153
|
+
}
|
|
154
|
+
return colgroup;
|
|
128
155
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
156
|
+
buildHeader(headerRows, frozen) {
|
|
157
|
+
const o = this.opts;
|
|
158
|
+
const m = this.style.metrics;
|
|
159
|
+
const thead = document.createElement("thead");
|
|
160
|
+
headerRows.forEach((row, rowIndex) => {
|
|
161
|
+
const tr = document.createElement("tr");
|
|
162
|
+
let cursor = 0;
|
|
136
163
|
for (const cell of row) {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
164
|
+
const start = cell.colIndex ?? cursor;
|
|
165
|
+
const span = Math.max(1, cell.colSpan ?? 1);
|
|
166
|
+
cursor = start + span;
|
|
167
|
+
const th = document.createElement("th");
|
|
168
|
+
th.scope = span > 1 ? "colgroup" : "col";
|
|
169
|
+
if (span > 1) th.colSpan = span;
|
|
170
|
+
if ((cell.rowSpan ?? 1) > 1) th.rowSpan = cell.rowSpan;
|
|
171
|
+
const classes = [];
|
|
172
|
+
const align = cell.align ?? "left";
|
|
173
|
+
if (align !== "left") classes.push(align === "right" ? "a-r" : "a-c");
|
|
174
|
+
if (cell.colIndex == null && span > 1) classes.push("gtv-hg");
|
|
175
|
+
if (start + span <= frozen) classes.push("fz", `fz${start}`);
|
|
176
|
+
if (start > 0 && o.columns[start]?.groupStart) classes.push("gs");
|
|
177
|
+
th.style.top = o.stickyHeader === false ? "" : `${rowIndex * m.headerHeight}px`;
|
|
178
|
+
if ((cell.rowSpan ?? 1) > 1) th.style.height = `${(cell.rowSpan ?? 1) * m.headerHeight}px`;
|
|
179
|
+
th.title = cell.title;
|
|
180
|
+
const colIndex = cell.colIndex;
|
|
181
|
+
const sorted = colIndex != null && o.sortState?.col === colIndex;
|
|
182
|
+
if (sorted) {
|
|
183
|
+
classes.push("sorted");
|
|
184
|
+
th.setAttribute("aria-sort", o.sortState?.dir === "desc" ? "descending" : "ascending");
|
|
185
|
+
}
|
|
186
|
+
th.className = classes.join(" ");
|
|
187
|
+
if (colIndex != null && o.onSort && o.columns[colIndex]?.sortable !== false) {
|
|
188
|
+
const button = document.createElement("button");
|
|
189
|
+
button.type = "button";
|
|
190
|
+
button.className = "gtv-sort";
|
|
191
|
+
button.addEventListener("click", () => o.onSort?.(colIndex));
|
|
192
|
+
const label = document.createElement("span");
|
|
193
|
+
label.className = "gtv-lbl";
|
|
194
|
+
label.textContent = cell.title;
|
|
195
|
+
const glyph = document.createElement("span");
|
|
196
|
+
glyph.className = "gtv-glyph";
|
|
197
|
+
glyph.setAttribute("aria-hidden", "true");
|
|
198
|
+
glyph.textContent = sorted ? o.sortState?.dir === "desc" ? "\u2193" : "\u2191" : "";
|
|
199
|
+
button.append(label, glyph);
|
|
200
|
+
th.appendChild(button);
|
|
201
|
+
} else {
|
|
202
|
+
th.textContent = cell.title;
|
|
203
|
+
}
|
|
204
|
+
tr.appendChild(th);
|
|
141
205
|
}
|
|
142
|
-
thead.appendChild(
|
|
206
|
+
thead.appendChild(tr);
|
|
143
207
|
});
|
|
144
208
|
return thead;
|
|
145
209
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
setCellBaseStyles(th, opts.tokens, align ?? "left", opts.stickyHeader !== false, metrics.padding, gridBorderColor(opts));
|
|
161
|
-
setStyles(th, {
|
|
162
|
-
top: `${rowIndex * metrics.headerHeight}px`,
|
|
163
|
-
zIndex: "4",
|
|
164
|
-
background: opts.tokens.color.surface,
|
|
165
|
-
color: opts.tokens.color.text,
|
|
166
|
-
fontWeight: String(opts.tokens.font.weight.bold),
|
|
167
|
-
borderBottom: `1px solid ${gridBorderColor(opts)}`,
|
|
168
|
-
userSelect: "none",
|
|
169
|
-
height: `${metrics.headerHeight}px`
|
|
170
|
-
});
|
|
171
|
-
if (colIndex != null && opts.onSort && opts.columns[colIndex]?.sortable !== false) {
|
|
172
|
-
th.textContent = "";
|
|
173
|
-
const button = document.createElement("button");
|
|
174
|
-
button.type = "button";
|
|
175
|
-
button.addEventListener("click", () => opts.onSort?.(colIndex));
|
|
176
|
-
setStyles(button, {
|
|
177
|
-
all: "unset",
|
|
178
|
-
boxSizing: "border-box",
|
|
179
|
-
display: "inline-flex",
|
|
180
|
-
alignItems: "center",
|
|
181
|
-
justifyContent: align === "right" ? "flex-end" : align === "center" ? "center" : "flex-start",
|
|
182
|
-
gap: "5px",
|
|
183
|
-
width: "100%",
|
|
184
|
-
cursor: "pointer",
|
|
185
|
-
color: "inherit",
|
|
186
|
-
font: "inherit"
|
|
210
|
+
buildFooter(headerRowCount) {
|
|
211
|
+
const o = this.opts;
|
|
212
|
+
if (!o.footerRow) return null;
|
|
213
|
+
const tfoot = document.createElement("tfoot");
|
|
214
|
+
const tr = document.createElement("tr");
|
|
215
|
+
if (this.windowed) tr.setAttribute("aria-rowindex", String(headerRowCount + o.rowCount + 1));
|
|
216
|
+
const kind = o.footerRow.kind === "grandtotal" ? "grandtotal" : "subtotal";
|
|
217
|
+
o.columns.forEach((column, col) => {
|
|
218
|
+
const el = document.createElement(column.rowHeader ? "th" : "td");
|
|
219
|
+
if (column.rowHeader) el.scope = "row";
|
|
220
|
+
const slot = { el, kind: "text", styled: false, titled: false };
|
|
221
|
+
const cell = o.footerRow?.cells[col] ?? { value: null, raw: null };
|
|
222
|
+
this.bindCell(slot, -1, col, { kind, depth: 0 }, cell);
|
|
223
|
+
tr.appendChild(el);
|
|
187
224
|
});
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
label.style.overflow = "hidden";
|
|
191
|
-
label.style.textOverflow = "ellipsis";
|
|
192
|
-
const glyph = document.createElement("span");
|
|
193
|
-
glyph.textContent = isSorted ? opts.sortState?.dir === "desc" ? "\u2193" : "\u2191" : "";
|
|
194
|
-
glyph.setAttribute("aria-hidden", "true");
|
|
195
|
-
glyph.style.color = opts.tokens.color.textMuted;
|
|
196
|
-
button.append(label, glyph);
|
|
197
|
-
th.appendChild(button);
|
|
225
|
+
tfoot.appendChild(tr);
|
|
226
|
+
return tfoot;
|
|
198
227
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
228
|
+
onScroll() {
|
|
229
|
+
this.opts.onScroll?.(this.host.scrollTop || 0, this.host.scrollLeft || 0);
|
|
230
|
+
if (this.frame !== 0) return;
|
|
231
|
+
let ran = false;
|
|
232
|
+
const run = () => {
|
|
233
|
+
ran = true;
|
|
234
|
+
this.frame = 0;
|
|
235
|
+
this.renderWindow(false);
|
|
236
|
+
this.paintSketch();
|
|
237
|
+
};
|
|
238
|
+
const id = typeof requestAnimationFrame === "function" ? requestAnimationFrame(run) : setTimeout(run, 16);
|
|
239
|
+
if (!ran) this.frame = id || -1;
|
|
210
240
|
}
|
|
211
|
-
|
|
212
|
-
|
|
241
|
+
visibleRange(scrollTop = this.host.scrollTop || 0) {
|
|
242
|
+
const o = this.opts;
|
|
243
|
+
if (!this.windowed) return [0, o.rowCount];
|
|
244
|
+
const m = this.style.metrics;
|
|
245
|
+
const header = this.headerRowCount * m.headerHeight;
|
|
246
|
+
const viewport = o.rect.height;
|
|
247
|
+
const top = Math.max(0, scrollTop - header);
|
|
248
|
+
const start = Math.max(0, Math.floor(top / m.rowHeight) - BUFFER_ROWS);
|
|
249
|
+
const end = Math.min(o.rowCount, Math.ceil((top + viewport) / m.rowHeight) + BUFFER_ROWS);
|
|
250
|
+
return [start, Math.max(start, end)];
|
|
213
251
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
252
|
+
renderWindow(force, scrollTop) {
|
|
253
|
+
const [start, end] = this.visibleRange(scrollTop);
|
|
254
|
+
if (!force && start === this.start && end === this.end) return;
|
|
255
|
+
this.start = start;
|
|
256
|
+
this.end = end;
|
|
257
|
+
const count = end - start;
|
|
258
|
+
while (this.pool.length < count) this.pool.push(this.createRow());
|
|
259
|
+
while (this.pool.length > count) this.pool.pop().tr.remove();
|
|
260
|
+
const rh = this.style.metrics.rowHeight;
|
|
261
|
+
const info = this.opts.rowInfo ?? defaultRowInfo;
|
|
262
|
+
for (let i = 0; i < count; i++) this.bindRow(this.pool[i], start + i, info(start + i));
|
|
263
|
+
this.setSpacer(this.topSpacer, start * rh, true);
|
|
264
|
+
this.setSpacer(this.bottomSpacer, (this.opts.rowCount - end) * rh, false);
|
|
265
|
+
}
|
|
266
|
+
/** Spacer rows stand in for windowed-out rows and exist only while they have height. */
|
|
267
|
+
setSpacer(tr, height, top) {
|
|
268
|
+
if (height <= 0) {
|
|
269
|
+
tr.remove();
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const td = tr.firstElementChild;
|
|
273
|
+
const h = `${height}px`;
|
|
274
|
+
if (td.style.height !== h) td.style.height = h;
|
|
275
|
+
if (tr.parentNode !== this.tbody) {
|
|
276
|
+
if (top) this.tbody.insertBefore(tr, this.tbody.firstChild);
|
|
277
|
+
else this.tbody.appendChild(tr);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
createRow() {
|
|
281
|
+
const tr = document.createElement("tr");
|
|
282
|
+
if (this.opts.onRowClick) tr.tabIndex = 0;
|
|
283
|
+
const cells = this.opts.columns.map((column) => {
|
|
284
|
+
const el = document.createElement(column.rowHeader ? "th" : "td");
|
|
285
|
+
if (column.rowHeader) el.scope = "row";
|
|
286
|
+
tr.appendChild(el);
|
|
287
|
+
return { el, kind: "text", styled: false, titled: false };
|
|
234
288
|
});
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
289
|
+
this.tbody.insertBefore(tr, this.bottomSpacer.parentNode === this.tbody ? this.bottomSpacer : null);
|
|
290
|
+
return { tr, cells, row: -1 };
|
|
291
|
+
}
|
|
292
|
+
bindRow(slot, row, info) {
|
|
293
|
+
const o = this.opts;
|
|
294
|
+
slot.row = row;
|
|
295
|
+
const tr = slot.tr;
|
|
296
|
+
let cls = "gtv-r";
|
|
297
|
+
if (info.kind === "group") cls += " k-group";
|
|
298
|
+
else if (info.kind === "subtotal") cls += " k-sub";
|
|
299
|
+
else if (info.kind === "grandtotal") cls += " k-grand";
|
|
300
|
+
else if (o.striped && row % 2 === 1) cls += " s";
|
|
301
|
+
if (o.highlighted?.(row)) cls += " hl";
|
|
302
|
+
if (tr.className !== cls) tr.className = cls;
|
|
303
|
+
tr.dataset.row = String(row);
|
|
304
|
+
if (this.windowed) tr.setAttribute("aria-rowindex", String(this.headerRowCount + row + 1));
|
|
305
|
+
for (let col = 0; col < slot.cells.length; col++) this.bindCell(slot.cells[col], row, col, info, o.getCell(row, col));
|
|
306
|
+
}
|
|
307
|
+
bindCell(slot, row, col, info, cell) {
|
|
308
|
+
const o = this.opts;
|
|
309
|
+
const column = o.columns[col];
|
|
310
|
+
const el = slot.el;
|
|
311
|
+
const formatter = o.rowFormatters ? row >= 0 ? o.rowFormatters(row)?.[col] ?? null : null : (o.formatKinds ?? DEFAULT_FORMAT_KINDS).includes(info.kind) ? this.formatters[col] : null;
|
|
312
|
+
const paint = formatter ? formatter(cell) : null;
|
|
313
|
+
const text = paint?.showValue === false ? "" : cellText(cell, column);
|
|
314
|
+
const className = this.baseClass[col];
|
|
315
|
+
if (el.className !== className) el.className = className;
|
|
316
|
+
if (slot.styled) {
|
|
317
|
+
el.style.cssText = "";
|
|
318
|
+
slot.styled = false;
|
|
241
319
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
320
|
+
const color = paint?.color ?? negativeTextColor(cell.value, column, "", this.style.color.negative);
|
|
321
|
+
if (paint?.background) this.setStyle(slot, "background", paint.background);
|
|
322
|
+
if (color) this.setStyle(slot, "color", color);
|
|
323
|
+
if (paint?.weight) this.setStyle(slot, "fontWeight", String(paint.weight));
|
|
324
|
+
if (column.rowHeader) this.bindRowHeader(slot, info, text, row);
|
|
325
|
+
else if (column.sparkline && Array.isArray(cell.value)) this.bindSpark(slot, cell.value, column);
|
|
326
|
+
else if (paint?.bar) this.bindBar(slot, paint, text, col, row);
|
|
327
|
+
else if (paint?.icon) this.bindIcon(slot, paint, text);
|
|
328
|
+
else {
|
|
329
|
+
slot.kind = "text";
|
|
330
|
+
if (el.firstChild?.nodeType !== 3 || el.childNodes.length !== 1 || el.firstChild.nodeValue !== text) el.textContent = text;
|
|
331
|
+
}
|
|
332
|
+
this.syncTitle(slot, text, col, info.kind !== "leaf" || Boolean(paint?.weight), info.depth);
|
|
333
|
+
}
|
|
334
|
+
setStyle(slot, key, value) {
|
|
335
|
+
slot.el.style[key] = value;
|
|
336
|
+
slot.styled = true;
|
|
337
|
+
}
|
|
338
|
+
bindRowHeader(slot, info, text, row) {
|
|
339
|
+
const m = this.style.metrics;
|
|
340
|
+
if (slot.kind !== "rh") {
|
|
341
|
+
slot.el.replaceChildren();
|
|
342
|
+
slot.toggle = document.createElement("button");
|
|
343
|
+
slot.toggle.type = "button";
|
|
344
|
+
slot.toggle.className = "gtv-tog";
|
|
345
|
+
slot.toggle.innerHTML = '<svg width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"><path d="M2 3.5 5 6.5 8 3.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
346
|
+
slot.pad = document.createElement("span");
|
|
347
|
+
slot.pad.className = "gtv-pad";
|
|
348
|
+
slot.val = document.createElement("span");
|
|
349
|
+
slot.el.append(slot.toggle, slot.pad, slot.val);
|
|
350
|
+
slot.kind = "rh";
|
|
351
|
+
}
|
|
352
|
+
const indent = m.paddingX + info.depth * m.indent;
|
|
353
|
+
if (indent !== m.paddingX) this.setStyle(slot, "paddingLeft", `${indent}px`);
|
|
354
|
+
const expandable = Boolean(info.expandable) && row >= 0 && Boolean(this.opts.onToggle);
|
|
355
|
+
slot.toggle.style.display = expandable ? "" : "none";
|
|
356
|
+
slot.pad.style.display = expandable || !this.hierarchy ? "none" : "";
|
|
357
|
+
if (expandable) {
|
|
358
|
+
slot.toggle.setAttribute("aria-expanded", String(info.expanded !== false));
|
|
359
|
+
slot.toggle.setAttribute("aria-label", `${info.expanded !== false ? "Collapse" : "Expand"} ${text}`);
|
|
360
|
+
}
|
|
361
|
+
if (slot.val.textContent !== text) slot.val.textContent = text;
|
|
362
|
+
}
|
|
363
|
+
hasHierarchy() {
|
|
364
|
+
const info = this.opts.measure?.rowInfo ?? this.opts.rowInfo;
|
|
365
|
+
if (!info) return false;
|
|
366
|
+
const count = this.opts.measure?.rowCount ?? this.opts.rowCount;
|
|
367
|
+
for (let i = 0; i < Math.min(count, 200); i++) if (info(i).expandable) return true;
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
bindBar(slot, paint, text, col, row) {
|
|
371
|
+
const o = this.opts;
|
|
372
|
+
const bar = paint.bar;
|
|
373
|
+
const column = o.columns[col];
|
|
374
|
+
const track = barTrack(this.widths[col] ?? 0, this.style.metrics.paddingX, this.layout.valueWidths[col] ?? 0, column.align, paint.showValue !== false);
|
|
375
|
+
const left = track.left + bar.from * track.width;
|
|
376
|
+
const width = Math.max(0, (bar.to - bar.from) * track.width);
|
|
377
|
+
const fill = barFill(bar.color, track.overlay ? BAR_OVERLAY_ALPHA : BAR_LANE_ALPHA);
|
|
378
|
+
if (slot.kind !== "bar") {
|
|
379
|
+
slot.el.replaceChildren();
|
|
380
|
+
slot.bar = document.createElement("div");
|
|
381
|
+
slot.zero = document.createElement("div");
|
|
382
|
+
slot.zero.className = "gtv-zero";
|
|
383
|
+
slot.val = document.createElement("span");
|
|
384
|
+
slot.val.className = "gtv-val";
|
|
385
|
+
slot.el.append(slot.bar, slot.zero, slot.val);
|
|
386
|
+
slot.kind = "bar";
|
|
387
|
+
}
|
|
388
|
+
if (o.sketch) {
|
|
389
|
+
const seed = (o.sketch.seed ^ Math.imul(row + 2, 374761393) ^ Math.imul(col + 1, 668265263)) >>> 0;
|
|
390
|
+
const m = this.style.metrics;
|
|
391
|
+
const next = buildSketchDataBar(o.sketch, fill, left, width, m.barHeight, seed) ?? document.createElement("div");
|
|
392
|
+
slot.bar.replaceWith(next);
|
|
393
|
+
slot.bar = next;
|
|
394
|
+
} else {
|
|
395
|
+
const s = slot.bar.style;
|
|
396
|
+
if (slot.bar.className !== "gtv-bar") slot.bar.className = "gtv-bar";
|
|
397
|
+
s.left = `${left}px`;
|
|
398
|
+
s.width = `${width}px`;
|
|
399
|
+
s.background = fill;
|
|
400
|
+
}
|
|
401
|
+
slot.zero.style.display = bar.zero === void 0 ? "none" : "";
|
|
402
|
+
if (bar.zero !== void 0) slot.zero.style.left = `${Math.round(track.left + bar.zero * track.width)}px`;
|
|
403
|
+
if (slot.val.textContent !== text) slot.val.textContent = text;
|
|
404
|
+
}
|
|
405
|
+
bindIcon(slot, paint, text) {
|
|
406
|
+
if (slot.kind !== "icon") {
|
|
407
|
+
slot.el.replaceChildren();
|
|
408
|
+
const wrap2 = document.createElement("span");
|
|
409
|
+
wrap2.className = "gtv-flex";
|
|
410
|
+
slot.icon = document.createElement("span");
|
|
411
|
+
slot.icon.className = "gtv-icon";
|
|
412
|
+
slot.icon.setAttribute("aria-hidden", "true");
|
|
413
|
+
slot.val = document.createElement("span");
|
|
414
|
+
slot.val.className = "gtv-val";
|
|
415
|
+
wrap2.append(slot.icon, slot.val);
|
|
416
|
+
slot.el.appendChild(wrap2);
|
|
417
|
+
slot.kind = "icon";
|
|
418
|
+
}
|
|
419
|
+
const wrap = slot.icon.parentElement;
|
|
420
|
+
if (paint.iconPosition === "right") {
|
|
421
|
+
if (wrap.firstChild !== slot.val) wrap.insertBefore(slot.val, slot.icon);
|
|
422
|
+
} else if (wrap.firstChild !== slot.icon) wrap.insertBefore(slot.icon, slot.val);
|
|
423
|
+
slot.icon.textContent = paint.icon ?? "";
|
|
424
|
+
slot.icon.style.color = paint.iconColor ?? "";
|
|
425
|
+
if (slot.val.textContent !== text) slot.val.textContent = text;
|
|
426
|
+
}
|
|
427
|
+
bindSpark(slot, values, column) {
|
|
428
|
+
const spark = column.sparkline;
|
|
429
|
+
if (slot.kind !== "spark") {
|
|
430
|
+
slot.el.replaceChildren();
|
|
431
|
+
slot.el.innerHTML = '<svg class="gtv-spark" viewBox="0 0 100 20" preserveAspectRatio="none" aria-hidden="true"><path vector-effect="non-scaling-stroke"/><path vector-effect="non-scaling-stroke"/></svg>';
|
|
432
|
+
slot.kind = "spark";
|
|
433
|
+
}
|
|
434
|
+
const color = spark.color ?? this.opts.tokens.color.accent;
|
|
435
|
+
const shape = sparklinePath(values, spark, 100, 20);
|
|
436
|
+
const [fillPath, linePath] = Array.from(slot.el.querySelectorAll("path"));
|
|
437
|
+
fillPath.setAttribute("d", shape.area);
|
|
438
|
+
fillPath.setAttribute("fill", spark.type === "line" ? "none" : barFill(color, spark.type === "bar" ? 0.85 : 0.18));
|
|
439
|
+
fillPath.setAttribute("stroke", "none");
|
|
440
|
+
linePath.setAttribute("d", shape.line);
|
|
441
|
+
linePath.setAttribute("fill", "none");
|
|
442
|
+
linePath.setAttribute("stroke", spark.type === "bar" ? "none" : color);
|
|
443
|
+
linePath.setAttribute("stroke-width", "1.5");
|
|
444
|
+
linePath.setAttribute("stroke-linejoin", "round");
|
|
445
|
+
slot.el.setAttribute("aria-label", shape.summary);
|
|
446
|
+
}
|
|
447
|
+
/** Full text on hover for anything the column width cuts short. */
|
|
448
|
+
syncTitle(slot, text, col, strong, depth) {
|
|
449
|
+
const column = this.opts.columns[col];
|
|
450
|
+
let clipped = false;
|
|
451
|
+
if (text && !column.wrap) {
|
|
452
|
+
const m = this.style.metrics;
|
|
453
|
+
const font = strong ? this.boldFont : this.bodyFont;
|
|
454
|
+
const key = `${strong ? "b" : "n"}${text}`;
|
|
455
|
+
let w = this.textWidths.get(key);
|
|
456
|
+
if (w === void 0) {
|
|
457
|
+
w = measureText(text, font).width;
|
|
458
|
+
if (this.textWidths.size < 8192) this.textWidths.set(key, w);
|
|
459
|
+
}
|
|
460
|
+
const budget = (this.widths[col] ?? 0) - m.paddingX * 2 - (column.rowHeader ? depth * m.indent + m.toggle + 4 : 0);
|
|
461
|
+
clipped = w > budget + 0.5;
|
|
462
|
+
}
|
|
463
|
+
if (clipped) {
|
|
464
|
+
if (slot.el.title !== text) slot.el.title = text;
|
|
465
|
+
slot.titled = true;
|
|
466
|
+
} else if (slot.titled) {
|
|
467
|
+
slot.el.removeAttribute("title");
|
|
468
|
+
slot.titled = false;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
onBodyClick(event) {
|
|
472
|
+
const target = event.target;
|
|
473
|
+
const tr = target?.closest("tr");
|
|
474
|
+
const row = tr?.dataset.row == null ? -1 : Number(tr.dataset.row);
|
|
475
|
+
if (row < 0 || !Number.isFinite(row)) return;
|
|
476
|
+
if (target?.closest(".gtv-tog")) {
|
|
477
|
+
this.opts.onToggle?.(row);
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
const cell = target?.closest("td,th");
|
|
481
|
+
if (cell && this.opts.onRowClick) this.opts.onRowClick(row, cell.cellIndex, event);
|
|
482
|
+
}
|
|
483
|
+
/** Selectable rows are focusable; Enter or Space selects like a click. */
|
|
484
|
+
onBodyKey(event) {
|
|
485
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
486
|
+
const tr = event.target;
|
|
487
|
+
if (!tr || tr.tagName !== "TR" || !this.opts.onRowClick) return;
|
|
488
|
+
const row = Number(tr.dataset.row);
|
|
489
|
+
if (!Number.isFinite(row) || row < 0) return;
|
|
490
|
+
event.preventDefault();
|
|
491
|
+
this.opts.onRowClick(row, 0, event);
|
|
492
|
+
}
|
|
493
|
+
mountSketch(height) {
|
|
494
|
+
const o = this.opts;
|
|
495
|
+
this.sketchCanvas?.canvas.remove();
|
|
496
|
+
this.sketchCanvas = null;
|
|
497
|
+
if (!o.sketch) return;
|
|
498
|
+
const overlay = createSketchGridCanvas({ ...o.rect, height });
|
|
499
|
+
o.container.appendChild(overlay.canvas);
|
|
500
|
+
this.sketchCanvas = overlay;
|
|
501
|
+
this.paintSketch();
|
|
502
|
+
}
|
|
503
|
+
paintSketch() {
|
|
504
|
+
const o = this.opts;
|
|
505
|
+
const canvas = this.sketchCanvas;
|
|
506
|
+
if (!o.sketch || !canvas?.ctx) return;
|
|
507
|
+
const height = parseFloat(canvas.canvas.style.height) || o.rect.height;
|
|
508
|
+
paintSketchGridOverlay(canvas.ctx, {
|
|
509
|
+
sketch: o.sketch,
|
|
510
|
+
tokens: o.tokens,
|
|
511
|
+
rect: { ...o.rect, height },
|
|
512
|
+
dpr: canvas.dpr,
|
|
513
|
+
columns: o.columns,
|
|
514
|
+
widths: this.widths,
|
|
515
|
+
rowCount: o.rowCount,
|
|
516
|
+
headerRowCount: this.headerRowCount,
|
|
517
|
+
hasFooter: Boolean(o.footerRow),
|
|
518
|
+
rowHeaderSpan: o.frozenColumns ?? 0,
|
|
519
|
+
metrics: this.style.metrics,
|
|
520
|
+
scrollLeft: this.host.scrollLeft || 0,
|
|
521
|
+
scrollTop: this.host.scrollTop || 0
|
|
267
522
|
});
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
523
|
+
}
|
|
524
|
+
recordEvidence() {
|
|
525
|
+
const o = this.opts;
|
|
526
|
+
const evidence = o.evidence;
|
|
527
|
+
if (!evidence) return;
|
|
528
|
+
const m = this.style.metrics;
|
|
529
|
+
const first = clampInt(this.start, 0, o.rowCount);
|
|
530
|
+
const last = clampInt(this.end, first, o.rowCount);
|
|
531
|
+
recordDataEvidence(o, first, last);
|
|
532
|
+
const host = this.host.getBoundingClientRect();
|
|
533
|
+
const origin = { x: host.left - o.rect.x, y: host.top - o.rect.y };
|
|
534
|
+
const headerHeight = this.headerRowCount * m.headerHeight;
|
|
535
|
+
const viewTop = this.host.scrollTop || 0;
|
|
536
|
+
const viewBottom = viewTop + (this.host.clientHeight || o.rect.height);
|
|
537
|
+
const info = o.rowInfo ?? defaultRowInfo;
|
|
538
|
+
for (const slot of this.pool) {
|
|
539
|
+
const row = slot.row;
|
|
540
|
+
if (row < first || row >= last) continue;
|
|
541
|
+
const kind = info(row).kind;
|
|
542
|
+
const y = headerHeight + row * m.rowHeight;
|
|
543
|
+
const inView = y + m.rowHeight >= viewTop - m.rowHeight && y <= viewBottom + m.rowHeight;
|
|
544
|
+
let x = o.rect.x - (this.host.scrollLeft || 0);
|
|
545
|
+
for (let col = 0; col < slot.cells.length; col++) {
|
|
546
|
+
const el = slot.cells[col].el;
|
|
547
|
+
const width = this.widths[col] ?? 0;
|
|
548
|
+
const cell = o.getCell(row, col);
|
|
549
|
+
const background = el.style.background || rowBackground(this.style, kind, o.striped === true && row % 2 === 1);
|
|
550
|
+
const color = el.style.color || this.style.color.text;
|
|
551
|
+
const actual = inView ? el.getBoundingClientRect() : null;
|
|
552
|
+
const measured = Boolean(actual && actual.width > 0 && actual.height > 0);
|
|
553
|
+
if (inView && !measured) evidence.partial("geometry", "text");
|
|
554
|
+
const box = measured && actual ? { x: actual.left - origin.x, y: actual.top - origin.y, width: actual.width, height: actual.height } : { x, y: o.rect.y + y - viewTop, width, height: m.rowHeight };
|
|
555
|
+
if (countsAsMark(o, col, cell)) evidence.mark("cell", box.x, box.y, box.width, box.height, color, 1, o.rect, 1, background);
|
|
556
|
+
if (measured) recordDomLabels(o.labels, el, origin, background, "data-label", void 0, o.rect);
|
|
557
|
+
x += width;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
for (const th of Array.from(this.table.tHead?.querySelectorAll("th") ?? [])) {
|
|
561
|
+
if (!recordDomLabels(o.labels, th, origin, this.style.color.headerBg, "axis-label", "/columns", o.rect)) evidence.partial("text");
|
|
562
|
+
}
|
|
563
|
+
const foot = this.table.tFoot?.rows[0];
|
|
564
|
+
if (foot) {
|
|
565
|
+
for (let col = 0; col < foot.cells.length; col++) {
|
|
566
|
+
const el = foot.cells[col];
|
|
567
|
+
const actual = el.getBoundingClientRect();
|
|
568
|
+
if (actual.width <= 0 || actual.height <= 0) continue;
|
|
569
|
+
if (o.dataRepresentation === "aggregate" && countsAsMark(o, col, o.footerRow?.cells[col] ?? { value: null, raw: null })) {
|
|
570
|
+
evidence.mark(
|
|
571
|
+
"cell",
|
|
572
|
+
actual.left - origin.x,
|
|
573
|
+
actual.top - origin.y,
|
|
574
|
+
actual.width,
|
|
575
|
+
actual.height,
|
|
576
|
+
el.style.color || this.style.color.text,
|
|
577
|
+
1,
|
|
578
|
+
o.rect,
|
|
579
|
+
1,
|
|
580
|
+
el.style.background || this.style.color.totalBg
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
recordDomLabels(o.labels, el, origin, el.style.background || this.style.color.totalBg, "data-label", void 0, o.rect);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
function countsAsMark(o, col, cell) {
|
|
589
|
+
if (o.dataRepresentation !== "aggregate") return true;
|
|
590
|
+
return !o.columns[col]?.rowHeader && typeof cell.raw === "number" && Number.isFinite(cell.raw);
|
|
591
|
+
}
|
|
592
|
+
function recordDataEvidence(o, first, last) {
|
|
593
|
+
const evidence = o.evidence;
|
|
594
|
+
if (!evidence) return;
|
|
595
|
+
const rendered = o.columns.length ? last - first : 0;
|
|
596
|
+
const deferred = o.columns.length ? Math.max(0, o.rowCount - rendered) : 0;
|
|
597
|
+
if (o.dataRepresentation === "rows") {
|
|
598
|
+
evidence.data(rendered, "rows", 0, deferred);
|
|
599
|
+
} else if (o.dataRepresentation === "aggregate") {
|
|
600
|
+
evidence.data(o.sourceRepresentedRows ?? Math.max(0, evidence.snapshot().data.inputRows - deferred), "aggregate", 0, deferred);
|
|
601
|
+
}
|
|
275
602
|
}
|
|
276
|
-
function
|
|
603
|
+
function columnClass(column, index, frozen, windowed) {
|
|
604
|
+
const classes = [];
|
|
605
|
+
if (column.align === "right") classes.push("a-r");
|
|
606
|
+
else if (column.align === "center") classes.push("a-c");
|
|
607
|
+
if (column.isMeasure || column.type === "quantitative") classes.push("num");
|
|
608
|
+
if (index < frozen) classes.push("fz", `fz${index}`);
|
|
609
|
+
if (index === frozen - 1) classes.push("fz-edge");
|
|
610
|
+
if (index > 0 && column.groupStart) classes.push("gs");
|
|
611
|
+
if (column.total) classes.push("tc");
|
|
612
|
+
if (column.wrap && !windowed) classes.push("wrap");
|
|
613
|
+
return classes.join(" ");
|
|
614
|
+
}
|
|
615
|
+
function spacerRow(columns) {
|
|
277
616
|
const tr = document.createElement("tr");
|
|
617
|
+
tr.className = "gtv-sp";
|
|
278
618
|
tr.setAttribute("aria-hidden", "true");
|
|
279
619
|
const td = document.createElement("td");
|
|
280
|
-
td.colSpan = Math.max(1,
|
|
281
|
-
setStyles(td, {
|
|
282
|
-
height: `${Math.max(0, height)}px`,
|
|
283
|
-
padding: "0",
|
|
284
|
-
border: "0",
|
|
285
|
-
background: opts.tokens.color.background
|
|
286
|
-
});
|
|
620
|
+
td.colSpan = Math.max(1, columns);
|
|
287
621
|
tr.appendChild(td);
|
|
288
622
|
return tr;
|
|
289
623
|
}
|
|
290
|
-
function
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
624
|
+
function scrollbarWidth() {
|
|
625
|
+
if (cachedScrollbarWidth != null) return cachedScrollbarWidth;
|
|
626
|
+
if (typeof document === "undefined" || !document.body) return 0;
|
|
627
|
+
const probe = document.createElement("div");
|
|
628
|
+
probe.style.cssText = "position:absolute;top:-9999px;width:100px;height:100px;overflow:scroll;visibility:hidden";
|
|
629
|
+
document.body.appendChild(probe);
|
|
630
|
+
cachedScrollbarWidth = probe.offsetWidth - probe.clientWidth;
|
|
631
|
+
probe.remove();
|
|
632
|
+
return cachedScrollbarWidth;
|
|
295
633
|
}
|
|
296
634
|
export {
|
|
297
|
-
|
|
635
|
+
RENDER_ALL_CELLS,
|
|
636
|
+
RENDER_ALL_ROWS,
|
|
637
|
+
mountTable
|
|
298
638
|
};
|
|
299
639
|
//# sourceMappingURL=dom.js.map
|