@opendata-ai/openchart-vanilla 8.3.0 → 8.4.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/{chunk-PEIX32S3.js → chunk-45XZOWYC.js} +497 -52
- package/dist/chunk-45XZOWYC.js.map +1 -0
- package/dist/{chunk-DCODCLWI.js → chunk-FETYAVTZ.js} +3 -3
- package/dist/{chunk-RM5XS6NR.js → chunk-HGRNXLDF.js} +16 -11
- package/dist/chunk-HGRNXLDF.js.map +1 -0
- package/dist/{chunk-737VNBU6.js → chunk-LNPRDSK3.js} +37 -5
- package/dist/chunk-LNPRDSK3.js.map +1 -0
- package/dist/{chunk-T32UHMZA.js → chunk-UOB422LY.js} +2 -2
- package/dist/{chunk-P32LUJFK.js → chunk-YGYMB7KB.js} +118 -16
- package/dist/chunk-YGYMB7KB.js.map +1 -0
- package/dist/export-gif.js +3 -3
- package/dist/index.d.ts +6 -1
- package/dist/index.js +306 -103
- package/dist/index.js.map +1 -1
- package/dist/simulation-worker.js +67 -67
- package/dist/static.js +3 -3
- package/dist/story/index.js +4 -4
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-737VNBU6.js.map +0 -1
- package/dist/chunk-P32LUJFK.js.map +0 -1
- package/dist/chunk-PEIX32S3.js.map +0 -1
- package/dist/chunk-RM5XS6NR.js.map +0 -1
- /package/dist/{chunk-DCODCLWI.js.map → chunk-FETYAVTZ.js.map} +0 -0
- /package/dist/{chunk-T32UHMZA.js.map → chunk-UOB422LY.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
paletteFromCanvas,
|
|
4
4
|
readCanvasSRGB,
|
|
5
5
|
resolveRepeat
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-FETYAVTZ.js";
|
|
7
7
|
import {
|
|
8
8
|
renderTileMapSVG
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LNPRDSK3.js";
|
|
10
10
|
import {
|
|
11
11
|
AnimationScheduler,
|
|
12
12
|
CANVAS_DEFAULT_UPDATE_MAX_MARKS,
|
|
@@ -28,10 +28,11 @@ import {
|
|
|
28
28
|
resolveDarkMode,
|
|
29
29
|
resolveEase,
|
|
30
30
|
resolveFontFamily,
|
|
31
|
+
resolvedSurface,
|
|
31
32
|
scheduleFontReload,
|
|
32
33
|
setupAnimationCleanup,
|
|
33
34
|
setupTableAnimationCleanup
|
|
34
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-45XZOWYC.js";
|
|
35
36
|
import {
|
|
36
37
|
embedFonts,
|
|
37
38
|
ensureSVGDimensions,
|
|
@@ -43,16 +44,16 @@ import {
|
|
|
43
44
|
getSVGBackgroundColor,
|
|
44
45
|
getSVGDimensions,
|
|
45
46
|
rasterizeSVGToCanvas
|
|
46
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-UOB422LY.js";
|
|
47
48
|
import {
|
|
48
49
|
rectPathWithCorners,
|
|
49
50
|
registerMarkRenderer,
|
|
50
51
|
renderChartSVG,
|
|
51
52
|
stampAnimationVars
|
|
52
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-YGYMB7KB.js";
|
|
53
54
|
import {
|
|
54
55
|
injectThemeStyleBlock
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-HGRNXLDF.js";
|
|
56
57
|
|
|
57
58
|
// src/barlist-mount.ts
|
|
58
59
|
import { compileBarList } from "@opendata-ai/openchart-engine";
|
|
@@ -714,8 +715,8 @@ var ZoomTransform = class _ZoomTransform {
|
|
|
714
715
|
// src/graph/camera.ts
|
|
715
716
|
var K_MIN = 0.05;
|
|
716
717
|
var K_MAX = 15;
|
|
717
|
-
var AUTO_MIN_MS =
|
|
718
|
-
var AUTO_MAX_MS =
|
|
718
|
+
var AUTO_MIN_MS = 400;
|
|
719
|
+
var AUTO_MAX_MS = 600;
|
|
719
720
|
var AUTO_SCALE = 0.6;
|
|
720
721
|
function transformToView(t, viewport) {
|
|
721
722
|
const cx = (viewport.width / 2 - t.x) / t.k;
|
|
@@ -884,12 +885,16 @@ function driftFactor(t) {
|
|
|
884
885
|
}
|
|
885
886
|
|
|
886
887
|
// src/graph/canvas-renderer.ts
|
|
887
|
-
var LABEL_FONT_MIN =
|
|
888
|
+
var LABEL_FONT_MIN = 9;
|
|
888
889
|
var LABEL_FONT_MAX = 12;
|
|
889
|
-
var
|
|
890
|
+
var EDGE_ALPHA_DEFAULT_LIGHT = 0.3;
|
|
891
|
+
var EDGE_ALPHA_DEFAULT_DARK = 0.25;
|
|
890
892
|
var EDGE_ALPHA_CONNECTED = 1;
|
|
891
|
-
var SEARCH_NON_MATCH_ALPHA = 0.
|
|
892
|
-
var DEFAULT_DIM_OPACITY = 0.
|
|
893
|
+
var SEARCH_NON_MATCH_ALPHA = 0.25;
|
|
894
|
+
var DEFAULT_DIM_OPACITY = 0.3;
|
|
895
|
+
var LABEL_BUDGET_MIN = 12;
|
|
896
|
+
var LABEL_BUDGET_MAX = 80;
|
|
897
|
+
var LABEL_BUDGET_PER_ZOOM = 30;
|
|
893
898
|
var CROSSFADE_MAX_EDGES = 2e4;
|
|
894
899
|
function edgeTier(edge, focus) {
|
|
895
900
|
if (!focus.hasActive) return "default";
|
|
@@ -900,14 +905,14 @@ function nodeTier(node, focus, exemptIds) {
|
|
|
900
905
|
if (exemptIds?.has(node.id)) return "connected";
|
|
901
906
|
return focus.connected.has(node.id) ? "connected" : "dimmed";
|
|
902
907
|
}
|
|
903
|
-
function edgeTierAlpha(tier, dimOpacity) {
|
|
908
|
+
function edgeTierAlpha(tier, dimOpacity, defaultAlpha) {
|
|
904
909
|
switch (tier) {
|
|
905
910
|
case "connected":
|
|
906
911
|
return EDGE_ALPHA_CONNECTED;
|
|
907
912
|
case "dimmed":
|
|
908
913
|
return dimOpacity / 3;
|
|
909
914
|
default:
|
|
910
|
-
return
|
|
915
|
+
return defaultAlpha;
|
|
911
916
|
}
|
|
912
917
|
}
|
|
913
918
|
function nodeTierAlpha(tier, dimOpacity) {
|
|
@@ -960,13 +965,16 @@ function deriveFocus(hoveredNodeId, selectedNodeIds, adjacencyMap) {
|
|
|
960
965
|
}
|
|
961
966
|
var GLOW_NODE_THRESHOLD = 2e3;
|
|
962
967
|
var GLOW_RADIUS_MULTIPLIER = 1.3;
|
|
963
|
-
var GLOW_ALPHA = 0.
|
|
968
|
+
var GLOW_ALPHA = 0.1;
|
|
964
969
|
var CULL_MARGIN = 50;
|
|
965
970
|
var TWO_PI = Math.PI * 2;
|
|
966
971
|
var MIN_SCREEN_RADIUS = 2.5;
|
|
967
|
-
function
|
|
968
|
-
const
|
|
969
|
-
return
|
|
972
|
+
function labelBudget(zoom) {
|
|
973
|
+
const raw = Math.round(zoom * LABEL_BUDGET_PER_ZOOM);
|
|
974
|
+
return Math.max(LABEL_BUDGET_MIN, Math.min(LABEL_BUDGET_MAX, raw));
|
|
975
|
+
}
|
|
976
|
+
function boxesOverlap(a, b) {
|
|
977
|
+
return a.x0 < b.x1 && b.x0 < a.x1 && a.y0 < b.y1 && b.y0 < a.y1;
|
|
970
978
|
}
|
|
971
979
|
function visibleRect(canvasWidth, canvasHeight, transform, margin = CULL_MARGIN) {
|
|
972
980
|
const { x, y, k } = transform;
|
|
@@ -1034,8 +1042,8 @@ var GraphCanvasRenderer = class {
|
|
|
1034
1042
|
const visibleNodes = nodes.filter((n) => nodeInView(n, rect));
|
|
1035
1043
|
const visibleEdges = edges.filter((e) => edgeInView(e, rect));
|
|
1036
1044
|
const isDark = theme.isDark;
|
|
1045
|
+
const edgeAlphaDefault = isDark ? EDGE_ALPHA_DEFAULT_DARK : EDGE_ALPHA_DEFAULT_LIGHT;
|
|
1037
1046
|
const showGlow = isDark && !isGesturing && visibleNodes.length < GLOW_NODE_THRESHOLD;
|
|
1038
|
-
const threshold = labelThreshold(transform.k);
|
|
1039
1047
|
const minRadius = MIN_SCREEN_RADIUS / transform.k;
|
|
1040
1048
|
ctx.save();
|
|
1041
1049
|
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
@@ -1047,7 +1055,7 @@ var GraphCanvasRenderer = class {
|
|
|
1047
1055
|
ctx.translate(transform.x, transform.y);
|
|
1048
1056
|
ctx.scale(transform.k, transform.k);
|
|
1049
1057
|
if (state.exiting && state.exiting.alpha > 0) {
|
|
1050
|
-
this.drawGhosts(ctx, state.exiting, rect);
|
|
1058
|
+
this.drawGhosts(ctx, state.exiting, rect, edgeAlphaDefault);
|
|
1051
1059
|
}
|
|
1052
1060
|
if (crossfade && visibleEdges.length <= CROSSFADE_MAX_EDGES) {
|
|
1053
1061
|
this.drawEdgesCrossfade(
|
|
@@ -1057,6 +1065,7 @@ var GraphCanvasRenderer = class {
|
|
|
1057
1065
|
crossfade.next,
|
|
1058
1066
|
crossfade.t,
|
|
1059
1067
|
dimOpacity,
|
|
1068
|
+
edgeAlphaDefault,
|
|
1060
1069
|
isGesturing ? null : searchMatches,
|
|
1061
1070
|
hoveredEdgeId,
|
|
1062
1071
|
entrance,
|
|
@@ -1068,6 +1077,7 @@ var GraphCanvasRenderer = class {
|
|
|
1068
1077
|
visibleEdges,
|
|
1069
1078
|
nextFocus,
|
|
1070
1079
|
dimOpacity,
|
|
1080
|
+
edgeAlphaDefault,
|
|
1071
1081
|
isGesturing ? null : searchMatches,
|
|
1072
1082
|
hoveredEdgeId,
|
|
1073
1083
|
entrance,
|
|
@@ -1095,7 +1105,6 @@ var GraphCanvasRenderer = class {
|
|
|
1095
1105
|
this.drawLabels(
|
|
1096
1106
|
ctx,
|
|
1097
1107
|
visibleNodes,
|
|
1098
|
-
threshold,
|
|
1099
1108
|
hoveredNodeId,
|
|
1100
1109
|
selectedNodeIds,
|
|
1101
1110
|
searchMatches,
|
|
@@ -1132,7 +1141,7 @@ var GraphCanvasRenderer = class {
|
|
|
1132
1141
|
// -------------------------------------------------------------------------
|
|
1133
1142
|
// Batched edge drawing
|
|
1134
1143
|
// -------------------------------------------------------------------------
|
|
1135
|
-
drawEdgesBatched(ctx, edges, focus, dimOpacity, searchMatches, hoveredEdgeId, entrance, enterAlphaFor) {
|
|
1144
|
+
drawEdgesBatched(ctx, edges, focus, dimOpacity, edgeAlphaDefault, searchMatches, hoveredEdgeId, entrance, enterAlphaFor) {
|
|
1136
1145
|
const buckets = {
|
|
1137
1146
|
dimmed: [],
|
|
1138
1147
|
default: [],
|
|
@@ -1151,14 +1160,14 @@ var GraphCanvasRenderer = class {
|
|
|
1151
1160
|
this.drawEdgeGroupBatched(
|
|
1152
1161
|
ctx,
|
|
1153
1162
|
buckets.dimmed,
|
|
1154
|
-
edgeTierAlpha("dimmed", dimOpacity) * ea,
|
|
1163
|
+
edgeTierAlpha("dimmed", dimOpacity, edgeAlphaDefault) * ea,
|
|
1155
1164
|
searchMatches,
|
|
1156
1165
|
enterAlphaFor
|
|
1157
1166
|
);
|
|
1158
1167
|
this.drawEdgeGroupBatched(
|
|
1159
1168
|
ctx,
|
|
1160
1169
|
buckets.default,
|
|
1161
|
-
|
|
1170
|
+
edgeAlphaDefault * ea,
|
|
1162
1171
|
searchMatches,
|
|
1163
1172
|
enterAlphaFor
|
|
1164
1173
|
);
|
|
@@ -1177,7 +1186,7 @@ var GraphCanvasRenderer = class {
|
|
|
1177
1186
|
* batched at `lerp(edgeTierAlpha[prev], edgeTierAlpha[next], t)`. Preserves the
|
|
1178
1187
|
* per-group style batching within each bucket.
|
|
1179
1188
|
*/
|
|
1180
|
-
drawEdgesCrossfade(ctx, edges, prev, next, t, dimOpacity, searchMatches, hoveredEdgeId, entrance, enterAlphaFor) {
|
|
1189
|
+
drawEdgesCrossfade(ctx, edges, prev, next, t, dimOpacity, edgeAlphaDefault, searchMatches, hoveredEdgeId, entrance, enterAlphaFor) {
|
|
1181
1190
|
const ea = entrance ? entrance.edgeAlpha : 1;
|
|
1182
1191
|
const buckets = /* @__PURE__ */ new Map();
|
|
1183
1192
|
let hoveredEdge = null;
|
|
@@ -1197,7 +1206,11 @@ var GraphCanvasRenderer = class {
|
|
|
1197
1206
|
}
|
|
1198
1207
|
const ordered = [...buckets.entries()].map(([key, bucket]) => {
|
|
1199
1208
|
const [prevTier, nextTier] = key.split("|");
|
|
1200
|
-
const alpha = lerp(
|
|
1209
|
+
const alpha = lerp(
|
|
1210
|
+
edgeTierAlpha(prevTier, dimOpacity, edgeAlphaDefault),
|
|
1211
|
+
edgeTierAlpha(nextTier, dimOpacity, edgeAlphaDefault),
|
|
1212
|
+
t
|
|
1213
|
+
) * ea;
|
|
1201
1214
|
return { alpha, bucket };
|
|
1202
1215
|
}).sort((a, b) => a.alpha - b.alpha);
|
|
1203
1216
|
for (const { alpha, bucket } of ordered) {
|
|
@@ -1431,34 +1444,71 @@ var GraphCanvasRenderer = class {
|
|
|
1431
1444
|
// -------------------------------------------------------------------------
|
|
1432
1445
|
// Labels (drawn individually, skipped during gestures)
|
|
1433
1446
|
// -------------------------------------------------------------------------
|
|
1434
|
-
drawLabels(ctx, nodes,
|
|
1447
|
+
drawLabels(ctx, nodes, hoveredNodeId, selectedNodeIds, searchMatches, zoom, theme, entrance, enterAlphaFor) {
|
|
1435
1448
|
const la = entrance ? entrance.labelAlpha : 1;
|
|
1436
1449
|
const rawSize = 10 / zoom;
|
|
1437
1450
|
const fontSize = Math.max(LABEL_FONT_MIN, Math.min(LABEL_FONT_MAX, rawSize));
|
|
1438
1451
|
ctx.font = `${fontSize}px ${theme.fonts.family}`;
|
|
1439
1452
|
ctx.textAlign = "center";
|
|
1440
1453
|
ctx.textBaseline = "top";
|
|
1454
|
+
const haloColor = theme.colors.background !== "transparent" ? theme.colors.background : theme.isDark ? "rgba(0, 0, 0, 0.7)" : "rgba(255, 255, 255, 0.85)";
|
|
1455
|
+
const forced = [];
|
|
1456
|
+
const rest = [];
|
|
1441
1457
|
for (const node of nodes) {
|
|
1442
1458
|
if (!node.label) continue;
|
|
1443
|
-
const
|
|
1444
|
-
|
|
1445
|
-
|
|
1459
|
+
const isForced = node.id === hoveredNodeId || selectedNodeIds.has(node.id) || node.labelPriority === Infinity || (searchMatches?.has(node.id) ?? false);
|
|
1460
|
+
if (isForced) forced.push(node);
|
|
1461
|
+
else rest.push(node);
|
|
1462
|
+
}
|
|
1463
|
+
rest.sort((a, b) => b.labelPriority - a.labelPriority);
|
|
1464
|
+
const budget = labelBudget(zoom);
|
|
1465
|
+
const candidates = rest.slice(0, budget * 4);
|
|
1466
|
+
const placed = [];
|
|
1467
|
+
const pad = fontSize * 0.15;
|
|
1468
|
+
const lineHeight = fontSize * 1.2;
|
|
1469
|
+
const textWidth = (text) => ctx.measureText?.(text)?.width ?? text.length * fontSize * 0.55;
|
|
1470
|
+
const boxFor = (node) => {
|
|
1471
|
+
const w = textWidth(node.label);
|
|
1472
|
+
const y0 = node.y + node.radius + 3;
|
|
1473
|
+
return {
|
|
1474
|
+
x0: node.x - w / 2 - pad,
|
|
1475
|
+
x1: node.x + w / 2 + pad,
|
|
1476
|
+
y0: y0 - pad,
|
|
1477
|
+
y1: y0 + lineHeight + pad
|
|
1478
|
+
};
|
|
1479
|
+
};
|
|
1480
|
+
const drawOne = (node, isForced) => {
|
|
1446
1481
|
const dimmed = searchMatches !== null && !searchMatches.has(node.id);
|
|
1447
|
-
if (!forced && node.labelPriority < threshold) continue;
|
|
1448
1482
|
ctx.globalAlpha = (dimmed ? SEARCH_NON_MATCH_ALPHA : 1) * la * enterAlphaFor(node.id);
|
|
1449
1483
|
const labelY = node.y + node.radius + 3;
|
|
1450
|
-
if (
|
|
1451
|
-
ctx.strokeStyle =
|
|
1452
|
-
|
|
1453
|
-
ctx.
|
|
1484
|
+
if (isForced) {
|
|
1485
|
+
ctx.strokeStyle = haloColor;
|
|
1486
|
+
ctx.lineWidth = 3;
|
|
1487
|
+
ctx.lineJoin = "round";
|
|
1488
|
+
ctx.miterLimit = 2;
|
|
1489
|
+
ctx.strokeText(node.label, node.x, labelY);
|
|
1454
1490
|
}
|
|
1455
|
-
ctx.
|
|
1456
|
-
ctx.lineJoin = "round";
|
|
1457
|
-
ctx.miterLimit = 2;
|
|
1458
|
-
ctx.strokeText(node.label, node.x, labelY);
|
|
1459
|
-
ctx.fillStyle = theme.colors.text;
|
|
1491
|
+
ctx.fillStyle = isForced ? theme.colors.text : theme.colors.axis;
|
|
1460
1492
|
ctx.fillText(node.label, node.x, labelY);
|
|
1493
|
+
};
|
|
1494
|
+
for (const node of forced) placed.push(boxFor(node));
|
|
1495
|
+
let drawn = 0;
|
|
1496
|
+
for (const node of candidates) {
|
|
1497
|
+
if (drawn >= budget) break;
|
|
1498
|
+
const box = boxFor(node);
|
|
1499
|
+
let collides = false;
|
|
1500
|
+
for (const other of placed) {
|
|
1501
|
+
if (boxesOverlap(box, other)) {
|
|
1502
|
+
collides = true;
|
|
1503
|
+
break;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
if (collides) continue;
|
|
1507
|
+
placed.push(box);
|
|
1508
|
+
drawOne(node, false);
|
|
1509
|
+
drawn++;
|
|
1461
1510
|
}
|
|
1511
|
+
for (const node of forced) drawOne(node, true);
|
|
1462
1512
|
ctx.globalAlpha = 1;
|
|
1463
1513
|
}
|
|
1464
1514
|
// -------------------------------------------------------------------------
|
|
@@ -1470,7 +1520,7 @@ var GraphCanvasRenderer = class {
|
|
|
1470
1520
|
* they're on their way out. Batched by (stroke/style) for edges and (fill) for
|
|
1471
1521
|
* nodes, culled to the visible rect.
|
|
1472
1522
|
*/
|
|
1473
|
-
drawGhosts(ctx, exiting, rect) {
|
|
1523
|
+
drawGhosts(ctx, exiting, rect, edgeAlphaDefault) {
|
|
1474
1524
|
const alpha = exiting.alpha;
|
|
1475
1525
|
const edgeGroups = /* @__PURE__ */ new Map();
|
|
1476
1526
|
for (const edge of exiting.edges) {
|
|
@@ -1486,7 +1536,7 @@ var GraphCanvasRenderer = class {
|
|
|
1486
1536
|
ctx.setLineDash(dash);
|
|
1487
1537
|
ctx.strokeStyle = sample.stroke;
|
|
1488
1538
|
ctx.lineWidth = sample.strokeWidth;
|
|
1489
|
-
ctx.globalAlpha =
|
|
1539
|
+
ctx.globalAlpha = edgeAlphaDefault * alpha;
|
|
1490
1540
|
ctx.beginPath();
|
|
1491
1541
|
for (const edge of group) {
|
|
1492
1542
|
ctx.moveTo(edge.sourceX, edge.sourceY);
|
|
@@ -2929,9 +2979,11 @@ function createGraph(container, spec, options) {
|
|
|
2929
2979
|
const resolvedTheme = compilation.theme;
|
|
2930
2980
|
if (resolvedTheme) {
|
|
2931
2981
|
const s = wrapper.style;
|
|
2932
|
-
s.setProperty("--oc-bg", resolvedTheme
|
|
2982
|
+
s.setProperty("--oc-bg", resolvedSurface(resolvedTheme));
|
|
2933
2983
|
s.setProperty("--oc-text", resolvedTheme.colors.text);
|
|
2934
|
-
s.setProperty("--oc-text-secondary", resolvedTheme.colors.
|
|
2984
|
+
s.setProperty("--oc-text-secondary", resolvedTheme.colors.neutral.secondary);
|
|
2985
|
+
s.setProperty("--oc-text-muted", resolvedTheme.colors.axis);
|
|
2986
|
+
s.setProperty("--oc-border", resolvedTheme.colors.neutral.border);
|
|
2935
2987
|
s.setProperty("--oc-font-family", resolvedTheme.fonts.family);
|
|
2936
2988
|
s.fontFamily = resolvedTheme.fonts.family;
|
|
2937
2989
|
}
|
|
@@ -4113,8 +4165,18 @@ function renderHeatmapCell(cell) {
|
|
|
4113
4165
|
function renderCategoryCell(cell) {
|
|
4114
4166
|
const td = document.createElement("td");
|
|
4115
4167
|
td.className = "oc-table-category";
|
|
4116
|
-
|
|
4117
|
-
|
|
4168
|
+
const chip = document.createElement("span");
|
|
4169
|
+
chip.className = "oc-table-chip";
|
|
4170
|
+
if (cell.style.backgroundColor) chip.style.background = cell.style.backgroundColor;
|
|
4171
|
+
if (cell.style.color) chip.style.color = cell.style.color;
|
|
4172
|
+
if (cell.style.accent) {
|
|
4173
|
+
const dot = document.createElement("span");
|
|
4174
|
+
dot.className = "oc-table-chip-dot";
|
|
4175
|
+
dot.style.background = cell.style.accent;
|
|
4176
|
+
chip.appendChild(dot);
|
|
4177
|
+
}
|
|
4178
|
+
chip.appendChild(document.createTextNode(cell.formattedValue));
|
|
4179
|
+
td.appendChild(chip);
|
|
4118
4180
|
return td;
|
|
4119
4181
|
}
|
|
4120
4182
|
function renderBarCell(cell) {
|
|
@@ -4178,7 +4240,7 @@ function renderSparklineCell(cell) {
|
|
|
4178
4240
|
polyline.setAttribute("points", scaledPointsStr);
|
|
4179
4241
|
polyline.setAttribute("fill", "none");
|
|
4180
4242
|
polyline.setAttribute("stroke", sparklineData.color);
|
|
4181
|
-
polyline.setAttribute("stroke-width", "1.
|
|
4243
|
+
polyline.setAttribute("stroke-width", "1.25");
|
|
4182
4244
|
polyline.setAttribute("stroke-linejoin", "round");
|
|
4183
4245
|
polyline.setAttribute("vector-effect", "non-scaling-stroke");
|
|
4184
4246
|
svg.appendChild(polyline);
|
|
@@ -4272,6 +4334,27 @@ function renderSparklineCell(cell) {
|
|
|
4272
4334
|
td.appendChild(wrapper);
|
|
4273
4335
|
return td;
|
|
4274
4336
|
}
|
|
4337
|
+
var DELTA_GLYPH = {
|
|
4338
|
+
up: "\u25B2",
|
|
4339
|
+
down: "\u25BC",
|
|
4340
|
+
flat: "\u2013"
|
|
4341
|
+
};
|
|
4342
|
+
function renderDeltaCell(cell) {
|
|
4343
|
+
const td = document.createElement("td");
|
|
4344
|
+
applyCellStyle(td, cell);
|
|
4345
|
+
const chip = document.createElement("span");
|
|
4346
|
+
chip.className = `oc-table-delta oc-table-delta--${cell.tone}`;
|
|
4347
|
+
const arrow = document.createElement("span");
|
|
4348
|
+
arrow.className = "oc-table-delta-arrow";
|
|
4349
|
+
arrow.setAttribute("aria-hidden", "true");
|
|
4350
|
+
arrow.textContent = DELTA_GLYPH[cell.direction];
|
|
4351
|
+
chip.appendChild(arrow);
|
|
4352
|
+
const value = document.createElement("span");
|
|
4353
|
+
value.textContent = cell.formattedValue;
|
|
4354
|
+
chip.appendChild(value);
|
|
4355
|
+
td.appendChild(chip);
|
|
4356
|
+
return td;
|
|
4357
|
+
}
|
|
4275
4358
|
function renderImageCell(cell) {
|
|
4276
4359
|
const td = document.createElement("td");
|
|
4277
4360
|
applyCellStyle(td, cell);
|
|
@@ -4316,6 +4399,8 @@ function renderCell(cell) {
|
|
|
4316
4399
|
return renderBarCell(cell);
|
|
4317
4400
|
case "sparkline":
|
|
4318
4401
|
return renderSparklineCell(cell);
|
|
4402
|
+
case "delta":
|
|
4403
|
+
return renderDeltaCell(cell);
|
|
4319
4404
|
case "image":
|
|
4320
4405
|
return renderImageCell(cell);
|
|
4321
4406
|
case "flag":
|
|
@@ -4662,26 +4747,41 @@ function renderLabels(parent, nodes, measureText) {
|
|
|
4662
4747
|
const text = createSVGElement2("text");
|
|
4663
4748
|
setAttrs2(text, { x: label.x, y: label.y });
|
|
4664
4749
|
applyTextStyle(text, label.style);
|
|
4750
|
+
text.setAttribute("class", "oc-sankey-label");
|
|
4751
|
+
text.setAttribute("data-node-id", node.nodeId);
|
|
4752
|
+
const fontSize = label.style.fontSize ?? 12;
|
|
4753
|
+
const fontWeight = label.style.fontWeight ?? 400;
|
|
4754
|
+
let lines = [label.text];
|
|
4665
4755
|
if (label.maxWidth !== void 0 && label.maxWidth > 0) {
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
text.appendChild(tspan);
|
|
4679
|
-
}
|
|
4680
|
-
} else {
|
|
4681
|
-
text.textContent = label.text;
|
|
4756
|
+
lines = wrapText(label.text, fontSize, fontWeight, label.maxWidth, measureText);
|
|
4757
|
+
}
|
|
4758
|
+
if (lines.length > 1) {
|
|
4759
|
+
const lineHeight = fontSize * (label.style.lineHeight ?? 1.3);
|
|
4760
|
+
const totalHeight = (lines.length - 1) * lineHeight;
|
|
4761
|
+
const startY = label.y - totalHeight / 2;
|
|
4762
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4763
|
+
const tspan = createSVGElement2("tspan");
|
|
4764
|
+
tspan.setAttribute("x", String(label.x));
|
|
4765
|
+
tspan.setAttribute("y", String(startY + i * lineHeight));
|
|
4766
|
+
tspan.textContent = lines[i];
|
|
4767
|
+
text.appendChild(tspan);
|
|
4682
4768
|
}
|
|
4683
4769
|
} else {
|
|
4684
|
-
text.textContent =
|
|
4770
|
+
text.textContent = lines[0];
|
|
4771
|
+
}
|
|
4772
|
+
if (node.valueLabel) {
|
|
4773
|
+
if (text.childNodes.length === 0) {
|
|
4774
|
+
const nameSpan = createSVGElement2("tspan");
|
|
4775
|
+
nameSpan.textContent = text.textContent;
|
|
4776
|
+
text.textContent = "";
|
|
4777
|
+
text.appendChild(nameSpan);
|
|
4778
|
+
}
|
|
4779
|
+
const valueSpan = createSVGElement2("tspan");
|
|
4780
|
+
valueSpan.setAttribute("class", "oc-sankey-label-value");
|
|
4781
|
+
valueSpan.setAttribute("dx", "5");
|
|
4782
|
+
applyTextStyle(valueSpan, node.valueLabel.style);
|
|
4783
|
+
valueSpan.textContent = node.valueLabel.text;
|
|
4784
|
+
text.appendChild(valueSpan);
|
|
4685
4785
|
}
|
|
4686
4786
|
g.appendChild(text);
|
|
4687
4787
|
}
|
|
@@ -4739,8 +4839,8 @@ function renderSankeySVG(layout, animation) {
|
|
|
4739
4839
|
|
|
4740
4840
|
// src/sankey-mount.ts
|
|
4741
4841
|
var HIGHLIGHT_OPACITY = 0.7;
|
|
4742
|
-
var DIM_OPACITY = 0.
|
|
4743
|
-
var NODE_DIM_OPACITY = 0.
|
|
4842
|
+
var DIM_OPACITY = 0.12;
|
|
4843
|
+
var NODE_DIM_OPACITY = 0.3;
|
|
4744
4844
|
function createSankey(container, spec, options) {
|
|
4745
4845
|
let currentSpec = spec;
|
|
4746
4846
|
let currentLayout;
|
|
@@ -4802,7 +4902,7 @@ function createSankey(container, spec, options) {
|
|
|
4802
4902
|
tooltipManager.show(content, x, y);
|
|
4803
4903
|
}
|
|
4804
4904
|
options?.onNodeHover?.(nodeData);
|
|
4805
|
-
if (nodeId)
|
|
4905
|
+
if (nodeId) highlightPath(svg, { up: [nodeId], down: [nodeId] }, layout);
|
|
4806
4906
|
};
|
|
4807
4907
|
const handleMouseMove = (e) => {
|
|
4808
4908
|
if (content && tooltipManager) {
|
|
@@ -4849,6 +4949,13 @@ function createSankey(container, spec, options) {
|
|
|
4849
4949
|
tooltipManager.show(content, x, y);
|
|
4850
4950
|
}
|
|
4851
4951
|
options?.onLinkHover?.(linkData);
|
|
4952
|
+
if (sourceId && targetId) {
|
|
4953
|
+
highlightPath(
|
|
4954
|
+
svg,
|
|
4955
|
+
{ up: [sourceId], down: [targetId], links: [`${sourceId}->${targetId}`] },
|
|
4956
|
+
layout
|
|
4957
|
+
);
|
|
4958
|
+
}
|
|
4852
4959
|
};
|
|
4853
4960
|
const handleMouseMove = (e) => {
|
|
4854
4961
|
if (content && tooltipManager) {
|
|
@@ -4862,6 +4969,7 @@ function createSankey(container, spec, options) {
|
|
|
4862
4969
|
const handleMouseLeave = () => {
|
|
4863
4970
|
tooltipManager?.hide();
|
|
4864
4971
|
options?.onLinkHover?.(null);
|
|
4972
|
+
resetLinkOpacity(svg, layout);
|
|
4865
4973
|
};
|
|
4866
4974
|
const handleClick = () => {
|
|
4867
4975
|
options?.onLinkClick?.(linkData);
|
|
@@ -4888,27 +4996,53 @@ function createSankey(container, spec, options) {
|
|
|
4888
4996
|
const link = layout.links.find((l) => l.sourceId === sourceId && l.targetId === targetId);
|
|
4889
4997
|
return link?.data ?? {};
|
|
4890
4998
|
}
|
|
4891
|
-
function
|
|
4892
|
-
const
|
|
4893
|
-
const
|
|
4894
|
-
for (const
|
|
4895
|
-
const
|
|
4896
|
-
|
|
4999
|
+
function tracePath(layout, seeds) {
|
|
5000
|
+
const out = /* @__PURE__ */ new Map();
|
|
5001
|
+
const inn = /* @__PURE__ */ new Map();
|
|
5002
|
+
for (const link of layout.links) {
|
|
5003
|
+
const o = out.get(link.sourceId);
|
|
5004
|
+
if (o) o.push(link);
|
|
5005
|
+
else out.set(link.sourceId, [link]);
|
|
5006
|
+
const i = inn.get(link.targetId);
|
|
5007
|
+
if (i) i.push(link);
|
|
5008
|
+
else inn.set(link.targetId, [link]);
|
|
5009
|
+
}
|
|
5010
|
+
const nodes = /* @__PURE__ */ new Set([...seeds.up, ...seeds.down]);
|
|
5011
|
+
const links = new Set(seeds.links ?? []);
|
|
5012
|
+
const walk = (adjacency, seedIds, nextId) => {
|
|
5013
|
+
const queue = [...seedIds];
|
|
5014
|
+
const seen = new Set(seedIds);
|
|
5015
|
+
while (queue.length > 0) {
|
|
5016
|
+
const id = queue.shift();
|
|
5017
|
+
for (const link of adjacency.get(id) ?? []) {
|
|
5018
|
+
links.add(`${link.sourceId}->${link.targetId}`);
|
|
5019
|
+
const next = nextId(link);
|
|
5020
|
+
nodes.add(next);
|
|
5021
|
+
if (!seen.has(next)) {
|
|
5022
|
+
seen.add(next);
|
|
5023
|
+
queue.push(next);
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
5026
|
+
}
|
|
5027
|
+
};
|
|
5028
|
+
walk(out, seeds.down, (l) => l.targetId);
|
|
5029
|
+
walk(inn, seeds.up, (l) => l.sourceId);
|
|
5030
|
+
return { nodes, links };
|
|
5031
|
+
}
|
|
5032
|
+
function highlightPath(svg, seeds, layout) {
|
|
5033
|
+
const { nodes: onNodes, links: onLinks } = tracePath(layout, seeds);
|
|
5034
|
+
for (const el of svg.querySelectorAll(".oc-sankey-link")) {
|
|
4897
5035
|
const path = el.querySelector("path");
|
|
4898
5036
|
if (!path) continue;
|
|
4899
|
-
const
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
if (target) connectedNodeIds.add(target);
|
|
4904
|
-
}
|
|
5037
|
+
const source = el.getAttribute("data-source");
|
|
5038
|
+
const target = el.getAttribute("data-target");
|
|
5039
|
+
const onPath = onLinks.has(`${source}->${target}`);
|
|
5040
|
+
path.setAttribute("fill-opacity", String(onPath ? HIGHLIGHT_OPACITY : DIM_OPACITY));
|
|
4905
5041
|
}
|
|
4906
|
-
const
|
|
4907
|
-
for (const el of nodeElements) {
|
|
5042
|
+
for (const el of svg.querySelectorAll(".oc-sankey-node, .oc-sankey-label")) {
|
|
4908
5043
|
const nid = el.getAttribute("data-node-id");
|
|
4909
5044
|
if (!nid) continue;
|
|
4910
|
-
|
|
4911
|
-
el.style.opacity = isConnected ? "1" : String(NODE_DIM_OPACITY);
|
|
5045
|
+
el.style.opacity = onNodes.has(nid) ? "1" : String(NODE_DIM_OPACITY);
|
|
4912
5046
|
}
|
|
4913
5047
|
}
|
|
4914
5048
|
function resetLinkOpacity(svg, layout) {
|
|
@@ -4921,8 +5055,7 @@ function createSankey(container, spec, options) {
|
|
|
4921
5055
|
const link = layout.links.find((l) => l.sourceId === source && l.targetId === target);
|
|
4922
5056
|
path.setAttribute("fill-opacity", String(link?.fillOpacity ?? 0.5));
|
|
4923
5057
|
}
|
|
4924
|
-
const
|
|
4925
|
-
for (const el of nodeElements) {
|
|
5058
|
+
for (const el of svg.querySelectorAll(".oc-sankey-node, .oc-sankey-label")) {
|
|
4926
5059
|
el.style.opacity = "1";
|
|
4927
5060
|
}
|
|
4928
5061
|
}
|
|
@@ -5287,11 +5420,11 @@ function attachKeyboardNav(options) {
|
|
|
5287
5420
|
}
|
|
5288
5421
|
|
|
5289
5422
|
// src/table-mount.ts
|
|
5290
|
-
import {
|
|
5423
|
+
import { BREAKPOINT_COMPACT_MAX } from "@opendata-ai/openchart-core";
|
|
5291
5424
|
import { compileTable } from "@opendata-ai/openchart-engine";
|
|
5292
5425
|
|
|
5293
5426
|
// src/table-renderer.ts
|
|
5294
|
-
import { BRAND_FONT_SIZE as BRAND_FONT_SIZE3 } from "@opendata-ai/openchart-core";
|
|
5427
|
+
import { BRAND_FONT_SIZE as BRAND_FONT_SIZE3, cssTokenDefault } from "@opendata-ai/openchart-core";
|
|
5295
5428
|
import { clampStaggerDelay as clampStaggerDelay2 } from "@opendata-ai/openchart-engine";
|
|
5296
5429
|
var BRAND_URL3 = "https://tryopendata.ai";
|
|
5297
5430
|
function renderChromeBlock(layout, position) {
|
|
@@ -5333,6 +5466,7 @@ function renderChromeBlock(layout, position) {
|
|
|
5333
5466
|
}
|
|
5334
5467
|
function renderThead(columns, sort) {
|
|
5335
5468
|
const thead = document.createElement("thead");
|
|
5469
|
+
thead.setAttribute("role", "rowgroup");
|
|
5336
5470
|
const tr = document.createElement("tr");
|
|
5337
5471
|
tr.setAttribute("role", "row");
|
|
5338
5472
|
for (const col of columns) {
|
|
@@ -5364,6 +5498,7 @@ function renderThead(columns, sort) {
|
|
|
5364
5498
|
}
|
|
5365
5499
|
function renderTbody(rows, columns) {
|
|
5366
5500
|
const tbody = document.createElement("tbody");
|
|
5501
|
+
tbody.setAttribute("role", "rowgroup");
|
|
5367
5502
|
for (let r = 0; r < rows.length; r++) {
|
|
5368
5503
|
const row = rows[r];
|
|
5369
5504
|
const tr = document.createElement("tr");
|
|
@@ -5376,12 +5511,35 @@ function renderTbody(rows, columns) {
|
|
|
5376
5511
|
const td = renderCell(cell);
|
|
5377
5512
|
td.setAttribute("role", "gridcell");
|
|
5378
5513
|
td.style.textAlign = columns[c].align;
|
|
5514
|
+
td.setAttribute("data-label", columns[c].label);
|
|
5515
|
+
td.setAttribute("data-priority", String(columns[c].priority));
|
|
5379
5516
|
tr.appendChild(td);
|
|
5380
5517
|
}
|
|
5381
5518
|
tbody.appendChild(tr);
|
|
5382
5519
|
}
|
|
5383
5520
|
return tbody;
|
|
5384
5521
|
}
|
|
5522
|
+
function renderTfoot(totalRow, columns) {
|
|
5523
|
+
const tfoot = document.createElement("tfoot");
|
|
5524
|
+
tfoot.className = "oc-table-total";
|
|
5525
|
+
tfoot.setAttribute("role", "rowgroup");
|
|
5526
|
+
const tr = document.createElement("tr");
|
|
5527
|
+
tr.setAttribute("role", "row");
|
|
5528
|
+
for (let c = 0; c < columns.length; c++) {
|
|
5529
|
+
const cell = totalRow.cells[c];
|
|
5530
|
+
const td = cell ? renderCell(cell) : document.createElement("td");
|
|
5531
|
+
td.setAttribute("role", "gridcell");
|
|
5532
|
+
td.style.textAlign = columns[c].align;
|
|
5533
|
+
td.setAttribute("data-label", columns[c].label);
|
|
5534
|
+
td.setAttribute("data-priority", String(columns[c].priority));
|
|
5535
|
+
if (c === 0 && !td.textContent) {
|
|
5536
|
+
td.textContent = totalRow.label;
|
|
5537
|
+
}
|
|
5538
|
+
tr.appendChild(td);
|
|
5539
|
+
}
|
|
5540
|
+
tfoot.appendChild(tr);
|
|
5541
|
+
return tfoot;
|
|
5542
|
+
}
|
|
5385
5543
|
function renderSearchBar(layout) {
|
|
5386
5544
|
if (!layout.search.enabled) return null;
|
|
5387
5545
|
const div = document.createElement("div");
|
|
@@ -5439,12 +5597,23 @@ function renderTable(layout, container, opts) {
|
|
|
5439
5597
|
const { theme, chrome } = layout;
|
|
5440
5598
|
if (theme) {
|
|
5441
5599
|
const s = wrapper.style;
|
|
5442
|
-
|
|
5600
|
+
const n = theme.colors.neutral;
|
|
5601
|
+
s.setProperty("--oc-bg", resolvedSurface(theme));
|
|
5443
5602
|
s.setProperty("--oc-text", theme.colors.text);
|
|
5444
|
-
s.setProperty("--oc-text-secondary",
|
|
5445
|
-
s.setProperty("--oc-text-muted",
|
|
5603
|
+
s.setProperty("--oc-text-secondary", n.secondary);
|
|
5604
|
+
s.setProperty("--oc-text-muted", n[600]);
|
|
5605
|
+
s.setProperty("--oc-text-faint", n.faint);
|
|
5606
|
+
s.setProperty("--oc-gray-100", n[100]);
|
|
5607
|
+
s.setProperty("--oc-gray-200", n[200]);
|
|
5608
|
+
s.setProperty("--oc-gray-300", n[300]);
|
|
5609
|
+
s.setProperty("--oc-gray-400", n[400]);
|
|
5446
5610
|
s.setProperty("--oc-gridline", theme.colors.gridline);
|
|
5447
|
-
|
|
5611
|
+
const stripWs = (c) => c.replace(/\s+/g, "");
|
|
5612
|
+
const defaultGridline = cssTokenDefault("--oc-gridline", theme.isDark ? "dark" : "light");
|
|
5613
|
+
const gridlineOverridden = stripWs(theme.colors.gridline) !== stripWs(defaultGridline);
|
|
5614
|
+
s.setProperty("--oc-border", gridlineOverridden ? theme.colors.gridline : n.border);
|
|
5615
|
+
s.setProperty("--oc-positive", theme.colors.positive);
|
|
5616
|
+
s.setProperty("--oc-negative", theme.colors.negative);
|
|
5448
5617
|
s.setProperty("--oc-font-family", theme.fonts.family);
|
|
5449
5618
|
s.fontFamily = theme.fonts.family;
|
|
5450
5619
|
}
|
|
@@ -5469,9 +5638,13 @@ function renderTable(layout, container, opts) {
|
|
|
5469
5638
|
s.setProperty("--oc-footer-computed-color", chrome.footer.style.fill);
|
|
5470
5639
|
}
|
|
5471
5640
|
}
|
|
5472
|
-
|
|
5641
|
+
wrapper.classList.add(`oc-table--${layout.density}`);
|
|
5642
|
+
if (layout.density === "condensed") {
|
|
5473
5643
|
wrapper.classList.add("oc-table--compact");
|
|
5474
5644
|
}
|
|
5645
|
+
if (layout.striped) {
|
|
5646
|
+
wrapper.classList.add("oc-table--striped");
|
|
5647
|
+
}
|
|
5475
5648
|
const headerChrome = renderChromeBlock(layout, "header");
|
|
5476
5649
|
if (headerChrome) {
|
|
5477
5650
|
wrapper.appendChild(headerChrome);
|
|
@@ -5499,6 +5672,9 @@ function renderTable(layout, container, opts) {
|
|
|
5499
5672
|
table.appendChild(caption);
|
|
5500
5673
|
table.appendChild(renderThead(layout.columns, layout.sort));
|
|
5501
5674
|
table.appendChild(renderTbody(layout.rows, layout.columns));
|
|
5675
|
+
if (layout.totalRow) {
|
|
5676
|
+
table.appendChild(renderTfoot(layout.totalRow, layout.columns));
|
|
5677
|
+
}
|
|
5502
5678
|
scroll.appendChild(table);
|
|
5503
5679
|
wrapper.appendChild(scroll);
|
|
5504
5680
|
}
|
|
@@ -5551,6 +5727,8 @@ function renderTable(layout, container, opts) {
|
|
|
5551
5727
|
}
|
|
5552
5728
|
|
|
5553
5729
|
// src/table-mount.ts
|
|
5730
|
+
var MIN_READABLE_COLUMN_WIDTH = 96;
|
|
5731
|
+
var AUTO_CONDENSE_MAX_WIDTH = 560;
|
|
5554
5732
|
function csvEscape(value) {
|
|
5555
5733
|
if (value.includes(",") || value.includes('"') || value.includes("\n") || value.includes("\r")) {
|
|
5556
5734
|
return `"${value.replace(/"/g, '""')}"`;
|
|
@@ -5575,6 +5753,7 @@ function createTable(container, spec, options) {
|
|
|
5575
5753
|
let cleanupAnimations = null;
|
|
5576
5754
|
let isFirstRender = true;
|
|
5577
5755
|
let destroyed = false;
|
|
5756
|
+
let sortTouched = false;
|
|
5578
5757
|
const internalState = {
|
|
5579
5758
|
sort: null,
|
|
5580
5759
|
search: "",
|
|
@@ -5601,9 +5780,13 @@ function createTable(container, spec, options) {
|
|
|
5601
5780
|
search: partial.search !== void 0 ? partial.search : current.search,
|
|
5602
5781
|
page: partial.page !== void 0 ? partial.page : current.page
|
|
5603
5782
|
};
|
|
5783
|
+
if (partial.sort !== void 0) sortTouched = true;
|
|
5604
5784
|
options?.onStateChange?.(next);
|
|
5605
5785
|
} else {
|
|
5606
|
-
if (partial.sort !== void 0)
|
|
5786
|
+
if (partial.sort !== void 0) {
|
|
5787
|
+
internalState.sort = partial.sort;
|
|
5788
|
+
sortTouched = true;
|
|
5789
|
+
}
|
|
5607
5790
|
if (partial.search !== void 0) internalState.search = partial.search;
|
|
5608
5791
|
if (partial.page !== void 0) internalState.page = partial.page;
|
|
5609
5792
|
options?.onStateChange?.({ ...internalState });
|
|
@@ -5619,12 +5802,23 @@ function createTable(container, spec, options) {
|
|
|
5619
5802
|
theme: options?.theme,
|
|
5620
5803
|
darkMode,
|
|
5621
5804
|
watermark: options?.watermark,
|
|
5622
|
-
|
|
5805
|
+
// undefined = "no opinion, apply the spec default"; null = the user
|
|
5806
|
+
// cycled sorting off and expects the original row order back. A
|
|
5807
|
+
// controlled caller's natural initial `sort: null` means "no opinion"
|
|
5808
|
+
// until the user has actually touched sorting.
|
|
5809
|
+
sort: resolveEffectiveSort(state),
|
|
5623
5810
|
search: state.search || void 0,
|
|
5624
5811
|
page: state.page
|
|
5625
5812
|
};
|
|
5626
5813
|
return compileTable(currentSpec, compileOpts);
|
|
5627
5814
|
}
|
|
5815
|
+
function sameSort(a, b) {
|
|
5816
|
+
if (a === null || b === null) return a === b;
|
|
5817
|
+
return a.column === b.column && a.direction === b.direction;
|
|
5818
|
+
}
|
|
5819
|
+
function resolveEffectiveSort(state) {
|
|
5820
|
+
return sortTouched ? state.sort : state.sort ?? void 0;
|
|
5821
|
+
}
|
|
5628
5822
|
function getContainerDimensions() {
|
|
5629
5823
|
const rect = container.getBoundingClientRect();
|
|
5630
5824
|
return {
|
|
@@ -5642,12 +5836,13 @@ function createTable(container, spec, options) {
|
|
|
5642
5836
|
function applyBreakpointClass() {
|
|
5643
5837
|
if (!wrapperElement) return;
|
|
5644
5838
|
const { width } = getContainerDimensions();
|
|
5645
|
-
|
|
5646
|
-
if (
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5839
|
+
wrapperElement.classList.toggle("oc-table--cards", width < BREAKPOINT_COMPACT_MAX);
|
|
5840
|
+
if (currentSpec.density !== void 0 || currentSpec.compact === true) return;
|
|
5841
|
+
const columns = currentLayout?.columns.length ?? 0;
|
|
5842
|
+
const condensed = columns * MIN_READABLE_COLUMN_WIDTH > width || width < AUTO_CONDENSE_MAX_WIDTH;
|
|
5843
|
+
wrapperElement.classList.toggle("oc-table--condensed", condensed);
|
|
5844
|
+
wrapperElement.classList.toggle("oc-table--compact", condensed);
|
|
5845
|
+
wrapperElement.classList.toggle("oc-table--regular", !condensed);
|
|
5651
5846
|
}
|
|
5652
5847
|
function render() {
|
|
5653
5848
|
if (destroyed) return;
|
|
@@ -5835,7 +6030,7 @@ function createTable(container, spec, options) {
|
|
|
5835
6030
|
height: 600,
|
|
5836
6031
|
theme: options?.theme,
|
|
5837
6032
|
darkMode,
|
|
5838
|
-
sort: state
|
|
6033
|
+
sort: resolveEffectiveSort(state),
|
|
5839
6034
|
search: state.search || void 0
|
|
5840
6035
|
// No page/pageSize: get all rows
|
|
5841
6036
|
});
|
|
@@ -5849,6 +6044,9 @@ function createTable(container, spec, options) {
|
|
|
5849
6044
|
}
|
|
5850
6045
|
function setState(partial) {
|
|
5851
6046
|
if (destroyed) return;
|
|
6047
|
+
if (partial.sort !== void 0 && !sameSort(partial.sort, getState().sort)) {
|
|
6048
|
+
sortTouched = true;
|
|
6049
|
+
}
|
|
5852
6050
|
if (isControlled && options?.externalState) {
|
|
5853
6051
|
if (partial.sort !== void 0) options.externalState.sort = partial.sort;
|
|
5854
6052
|
if (partial.search !== void 0) options.externalState.search = partial.search;
|
|
@@ -5913,13 +6111,13 @@ function createTable(container, spec, options) {
|
|
|
5913
6111
|
}
|
|
5914
6112
|
|
|
5915
6113
|
// src/tilemap-mount.ts
|
|
5916
|
-
import { BREAKPOINT_COMPACT_MAX, BREAKPOINT_MEDIUM_MAX } from "@opendata-ai/openchart-core";
|
|
6114
|
+
import { BREAKPOINT_COMPACT_MAX as BREAKPOINT_COMPACT_MAX2, BREAKPOINT_MEDIUM_MAX } from "@opendata-ai/openchart-core";
|
|
5917
6115
|
import { compileTileMap } from "@opendata-ai/openchart-engine";
|
|
5918
6116
|
var TILEMAP_GRID_ROWS = 8;
|
|
5919
6117
|
var TILEMAP_TILE_GAP = 5;
|
|
5920
6118
|
var TILEMAP_CHROME_RESERVE = 180;
|
|
5921
6119
|
function pickTargetTileSize(width) {
|
|
5922
|
-
if (width <
|
|
6120
|
+
if (width < BREAKPOINT_COMPACT_MAX2) return 34;
|
|
5923
6121
|
return 40;
|
|
5924
6122
|
}
|
|
5925
6123
|
function createTileMap(container, spec, options) {
|
|
@@ -5976,6 +6174,7 @@ function createTileMap(container, spec, options) {
|
|
|
5976
6174
|
for (const t of layout.tiles) {
|
|
5977
6175
|
if (!tilesByStateCode.has(t.stateCode)) tilesByStateCode.set(t.stateCode, t);
|
|
5978
6176
|
}
|
|
6177
|
+
const tilesGroup = svg.querySelector(".oc-tilemap-tiles");
|
|
5979
6178
|
const tileElements = svg.querySelectorAll(".oc-tilemap-tile");
|
|
5980
6179
|
for (const el of tileElements) {
|
|
5981
6180
|
const stateCode = el.getAttribute("data-state");
|
|
@@ -5984,6 +6183,8 @@ function createTileMap(container, spec, options) {
|
|
|
5984
6183
|
const tile = tilesByStateCode.get(stateCode);
|
|
5985
6184
|
const handleMouseEnter = (e) => {
|
|
5986
6185
|
const mouseEvent = e;
|
|
6186
|
+
tilesGroup?.classList.add("oc-hover-active");
|
|
6187
|
+
el.classList.add("oc-tilemap-tile--hover");
|
|
5987
6188
|
if (content && tooltipManager && options?.tooltip !== false) {
|
|
5988
6189
|
const svgRect = svg.getBoundingClientRect();
|
|
5989
6190
|
const x = mouseEvent.clientX - svgRect.left;
|
|
@@ -6009,6 +6210,8 @@ function createTileMap(container, spec, options) {
|
|
|
6009
6210
|
}
|
|
6010
6211
|
};
|
|
6011
6212
|
const handleMouseLeave = () => {
|
|
6213
|
+
tilesGroup?.classList.remove("oc-hover-active");
|
|
6214
|
+
el.classList.remove("oc-tilemap-tile--hover");
|
|
6012
6215
|
tooltipManager?.hide();
|
|
6013
6216
|
options?.onTileHover?.(null);
|
|
6014
6217
|
};
|