@juspay/svelte-ui-components 2.81.1 → 2.81.2
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/_chart/geometry.js +62 -24
- package/package.json +1 -1
package/dist/_chart/geometry.js
CHANGED
|
@@ -94,25 +94,37 @@ export function computeSankeyLayout(nodes, links, width, height, nodeWidth = 16,
|
|
|
94
94
|
columnGroups.get(col).push(n.id);
|
|
95
95
|
}
|
|
96
96
|
const colWidth = maxCol === 0 ? 0 : (width - nodeWidth) / maxCol;
|
|
97
|
+
const columnPadding = new Map();
|
|
97
98
|
// Initialize y positions
|
|
98
99
|
const nodeY = new Map();
|
|
99
100
|
const nodeH = new Map();
|
|
100
|
-
for (const [, ids] of columnGroups) {
|
|
101
|
+
for (const [col, ids] of columnGroups) {
|
|
101
102
|
const totalValue = ids.reduce((s, id) => s + (nodeValues.get(id) ?? 0), 0);
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
const gapCount = ids.length - 1;
|
|
104
|
+
const availableHeight = height - gapCount * nodePadding;
|
|
105
|
+
const renderedHeights = ids.map((id) => {
|
|
105
106
|
const val = nodeValues.get(id) ?? 0;
|
|
106
107
|
const h = totalValue > 0 ? (val / totalValue) * availableHeight : availableHeight / ids.length;
|
|
107
|
-
|
|
108
|
+
return Math.max(minLinkWidth, h);
|
|
109
|
+
});
|
|
110
|
+
const sumRendered = renderedHeights.reduce((s, h) => s + h, 0);
|
|
111
|
+
const paddingBudget = gapCount > 0 ? (height - sumRendered) / gapCount : 0;
|
|
112
|
+
const effectivePadding = Math.max(0, Math.min(nodePadding, paddingBudget));
|
|
113
|
+
const scale = sumRendered > height && sumRendered > 0 ? height / sumRendered : 1;
|
|
114
|
+
columnPadding.set(col, effectivePadding);
|
|
115
|
+
let y = 0;
|
|
116
|
+
for (let index = 0; index < ids.length; index++) {
|
|
117
|
+
const id = ids[index];
|
|
118
|
+
const renderedH = renderedHeights[index] * scale;
|
|
108
119
|
nodeY.set(id, y);
|
|
109
120
|
nodeH.set(id, renderedH);
|
|
110
|
-
y += renderedH +
|
|
121
|
+
y += renderedH + effectivePadding;
|
|
111
122
|
}
|
|
112
123
|
}
|
|
113
124
|
// Iterative relaxation (upstream pass)
|
|
114
125
|
for (let iter = 0; iter < iterations; iter++) {
|
|
115
|
-
for (const [, ids] of columnGroups) {
|
|
126
|
+
for (const [col, ids] of columnGroups) {
|
|
127
|
+
const padding = columnPadding.get(col) ?? nodePadding;
|
|
116
128
|
for (const id of ids) {
|
|
117
129
|
const deps = incoming.get(id) ?? [];
|
|
118
130
|
const totalDepValue = deps.reduce((s, d) => s + d.value, 0);
|
|
@@ -128,15 +140,13 @@ export function computeSankeyLayout(nodes, links, width, height, nodeWidth = 16,
|
|
|
128
140
|
nodeY.set(id, Math.max(0, weightedY - (nodeH.get(id) ?? 0) / 2));
|
|
129
141
|
}
|
|
130
142
|
}
|
|
131
|
-
// Resolve overlaps: push down from the top.
|
|
132
|
-
ids.sort((a, b) => (nodeY.get(a) ?? 0) - (nodeY.get(b) ?? 0));
|
|
133
143
|
let y = 0;
|
|
134
144
|
for (const id of ids) {
|
|
135
145
|
const cy = nodeY.get(id) ?? 0;
|
|
136
146
|
if (cy < y) {
|
|
137
147
|
nodeY.set(id, y);
|
|
138
148
|
}
|
|
139
|
-
y = (nodeY.get(id) ?? 0) + (nodeH.get(id) ?? 0) +
|
|
149
|
+
y = (nodeY.get(id) ?? 0) + (nodeH.get(id) ?? 0) + padding;
|
|
140
150
|
}
|
|
141
151
|
// Resolve overlaps: pull back up from the bottom. The push-down pass
|
|
142
152
|
// above only ever grows a column's block downward, so a fan-out whose
|
|
@@ -151,7 +161,7 @@ export function computeSankeyLayout(nodes, links, width, height, nodeWidth = 16,
|
|
|
151
161
|
if (nodeBottom > bottomBoundary) {
|
|
152
162
|
nodeY.set(id, bottomBoundary - (nodeH.get(id) ?? 0));
|
|
153
163
|
}
|
|
154
|
-
bottomBoundary = (nodeY.get(id) ?? 0) -
|
|
164
|
+
bottomBoundary = (nodeY.get(id) ?? 0) - padding;
|
|
155
165
|
}
|
|
156
166
|
// Re-centre the column's node group within [0, height]: once overlaps
|
|
157
167
|
// are resolved, anchor the block at the midpoint of its remaining
|
|
@@ -184,25 +194,53 @@ export function computeSankeyLayout(nodes, links, width, height, nodeWidth = 16,
|
|
|
184
194
|
column: columns.get(n.id) ?? 0
|
|
185
195
|
}));
|
|
186
196
|
const nodeById = new Map(computedNodes.map((n) => [n.id, n]));
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
197
|
+
const linkKey = (l) => `${l.source}${l.target}`;
|
|
198
|
+
const linkWidths = new Map();
|
|
199
|
+
for (const l of links) {
|
|
200
|
+
const sVal = nodeValues.get(l.source) ?? 1;
|
|
201
|
+
const sourceH = nodeH.get(l.source) ?? 0;
|
|
202
|
+
linkWidths.set(linkKey(l), Math.max(minLinkWidth, (l.value / Math.max(sVal, 1)) * sourceH));
|
|
203
|
+
}
|
|
204
|
+
const linkSy = new Map();
|
|
205
|
+
const linkTy = new Map();
|
|
206
|
+
const bySource = new Map();
|
|
207
|
+
const byTarget = new Map();
|
|
208
|
+
for (const l of links) {
|
|
209
|
+
if (!bySource.has(l.source)) {
|
|
210
|
+
bySource.set(l.source, []);
|
|
211
|
+
}
|
|
212
|
+
bySource.get(l.source).push(l);
|
|
213
|
+
if (!byTarget.has(l.target)) {
|
|
214
|
+
byTarget.set(l.target, []);
|
|
215
|
+
}
|
|
216
|
+
byTarget.get(l.target).push(l);
|
|
217
|
+
}
|
|
218
|
+
for (const [source, group] of bySource) {
|
|
219
|
+
group.sort((a, b) => (nodeY.get(a.target) ?? 0) - (nodeY.get(b.target) ?? 0));
|
|
220
|
+
let offset = nodeY.get(source) ?? 0;
|
|
221
|
+
for (const l of group) {
|
|
222
|
+
const w = linkWidths.get(linkKey(l)) ?? 0;
|
|
223
|
+
linkSy.set(linkKey(l), offset + w / 2);
|
|
224
|
+
offset += w;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
for (const [target, group] of byTarget) {
|
|
228
|
+
group.sort((a, b) => (nodeY.get(a.source) ?? 0) - (nodeY.get(b.source) ?? 0));
|
|
229
|
+
let offset = nodeY.get(target) ?? 0;
|
|
230
|
+
for (const l of group) {
|
|
231
|
+
const w = linkWidths.get(linkKey(l)) ?? 0;
|
|
232
|
+
linkTy.set(linkKey(l), offset + w / 2);
|
|
233
|
+
offset += w;
|
|
234
|
+
}
|
|
193
235
|
}
|
|
194
236
|
const computedLinks = links.map((l) => {
|
|
195
237
|
const sourceNode = nodeById.get(l.source);
|
|
196
238
|
const targetNode = nodeById.get(l.target);
|
|
197
|
-
const
|
|
198
|
-
const sourceH = nodeH.get(l.source) ?? 0;
|
|
199
|
-
const linkWidth = Math.max(minLinkWidth, (l.value / Math.max(sVal, 1)) * sourceH);
|
|
239
|
+
const linkWidth = linkWidths.get(linkKey(l)) ?? minLinkWidth;
|
|
200
240
|
const sx = (sourceNode?.x ?? 0) + nodeWidth;
|
|
201
|
-
const sy =
|
|
241
|
+
const sy = linkSy.get(linkKey(l)) ?? 0;
|
|
202
242
|
const tx = targetNode?.x ?? 0;
|
|
203
|
-
const ty =
|
|
204
|
-
sourceOffsets.set(l.source, (sourceOffsets.get(l.source) ?? 0) + linkWidth);
|
|
205
|
-
targetOffsets.set(l.target, (targetOffsets.get(l.target) ?? 0) + linkWidth);
|
|
243
|
+
const ty = linkTy.get(linkKey(l)) ?? 0;
|
|
206
244
|
const midX = (sx + tx) / 2;
|
|
207
245
|
const path = `M ${sx} ${sy} C ${midX} ${sy}, ${midX} ${ty}, ${tx} ${ty}`;
|
|
208
246
|
return {
|