@pibbl/core 0.0.3-alpha.85.1 → 0.0.3-alpha.90.1
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/features/viz/index.d.ts +13 -0
- package/dist/features/viz/index.js +57 -0
- package/dist/features/viz/index.js.map +2 -2
- package/dist/features/viz/lib/graph/bipartite.d.ts +14 -0
- package/dist/features/viz/lib/graph/bipartite.js +250 -0
- package/dist/features/viz/lib/graph/bipartite.js.map +7 -0
- package/dist/features/viz/lib/graph/chord.d.ts +44 -0
- package/dist/features/viz/lib/graph/chord.js +348 -0
- package/dist/features/viz/lib/graph/chord.js.map +7 -0
- package/dist/features/viz/lib/graph/dependency.d.ts +26 -0
- package/dist/features/viz/lib/graph/dependency.js +141 -0
- package/dist/features/viz/lib/graph/dependency.js.map +7 -0
- package/dist/features/viz/lib/graph/force.d.ts +28 -0
- package/dist/features/viz/lib/graph/force.js +580 -0
- package/dist/features/viz/lib/graph/force.js.map +7 -0
- package/dist/features/viz/lib/graph/hierarchy.d.ts +21 -0
- package/dist/features/viz/lib/graph/hierarchy.js +112 -0
- package/dist/features/viz/lib/graph/hierarchy.js.map +7 -0
- package/dist/features/viz/lib/graph/icicle.d.ts +16 -0
- package/dist/features/viz/lib/graph/icicle.js +153 -0
- package/dist/features/viz/lib/graph/icicle.js.map +7 -0
- package/dist/features/viz/lib/graph/matrix.d.ts +30 -0
- package/dist/features/viz/lib/graph/matrix.js +243 -0
- package/dist/features/viz/lib/graph/matrix.js.map +7 -0
- package/dist/features/viz/lib/graph/neighborhood.d.ts +11 -0
- package/dist/features/viz/lib/graph/neighborhood.js +281 -0
- package/dist/features/viz/lib/graph/neighborhood.js.map +7 -0
- package/dist/features/viz/lib/graph/routes.d.ts +35 -0
- package/dist/features/viz/lib/graph/routes.js +102 -0
- package/dist/features/viz/lib/graph/routes.js.map +7 -0
- package/dist/features/viz/lib/graph/sankey.d.ts +44 -0
- package/dist/features/viz/lib/graph/sankey.js +341 -0
- package/dist/features/viz/lib/graph/sankey.js.map +7 -0
- package/dist/features/viz/lib/graph/shared.d.ts +59 -0
- package/dist/features/viz/lib/graph/shared.js +296 -0
- package/dist/features/viz/lib/graph/shared.js.map +7 -0
- package/dist/features/viz/lib/graph/tree.d.ts +11 -0
- package/dist/features/viz/lib/graph/tree.js +232 -0
- package/dist/features/viz/lib/graph/tree.js.map +7 -0
- package/dist/features/viz/lib/graph/treemap.d.ts +20 -0
- package/dist/features/viz/lib/graph/treemap.js +227 -0
- package/dist/features/viz/lib/graph/treemap.js.map +7 -0
- package/dist/features/viz/lib/graph/types.d.ts +1097 -0
- package/dist/filters/backdrop-contrast-gpu.d.ts +5 -0
- package/dist/filters/backdrop-contrast-gpu.js +33 -0
- package/dist/filters/backdrop-contrast-gpu.js.map +7 -0
- package/dist/filters/backdrop-contrast.d.ts +21 -0
- package/dist/filters/backdrop-contrast.js +61 -0
- package/dist/filters/backdrop-contrast.js.map +7 -0
- package/dist/filters/filter-executor.d.ts +11 -4
- package/dist/filters/filter-executor.js +104 -49
- package/dist/filters/filter-executor.js.map +2 -2
- package/dist/filters/render-backdrop-contrast-boundary.d.ts +31 -0
- package/dist/filters/render-backdrop-contrast-boundary.js +116 -0
- package/dist/filters/render-backdrop-contrast-boundary.js.map +7 -0
- package/dist/filters.d.ts +9 -7
- package/dist/filters.js +2 -0
- package/dist/filters.js.map +2 -2
- package/package.json +2 -2
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { jsx, jsxs } from "@pibbl/core/jsx-runtime";
|
|
2
|
+
import { Group, SvgPath, resolveSignalValue } from "@pibbl/core";
|
|
3
|
+
import {
|
|
4
|
+
defaultGraphLabelStyle,
|
|
5
|
+
GraphLabel,
|
|
6
|
+
GraphNode,
|
|
7
|
+
resolveMarkStyle,
|
|
8
|
+
useGraphFrame
|
|
9
|
+
} from "./shared.js";
|
|
10
|
+
function access(input, datum) {
|
|
11
|
+
return typeof input === "function" ? input(datum) : datum[input];
|
|
12
|
+
}
|
|
13
|
+
function finite(value, name, zero = false) {
|
|
14
|
+
if (!Number.isFinite(value) || zero && value < 0)
|
|
15
|
+
throw new RangeError(
|
|
16
|
+
`layoutSankey: ${name} must be finite${zero ? " and nonnegative" : ""}.`
|
|
17
|
+
);
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
function path(segments) {
|
|
21
|
+
return segments.map(
|
|
22
|
+
(segment) => segment.type === "move" ? `M ${segment.x} ${segment.y}` : segment.type === "line" ? `L ${segment.x} ${segment.y}` : segment.type === "cubic" ? `C ${segment.cp1x} ${segment.cp1y} ${segment.cp2x} ${segment.cp2y} ${segment.x} ${segment.y}` : segment.type === "close" ? "Z" : ""
|
|
23
|
+
).join(" ");
|
|
24
|
+
}
|
|
25
|
+
function layoutSankey(graph, options) {
|
|
26
|
+
const b = options.bounds;
|
|
27
|
+
finite(b.x, "bounds.x");
|
|
28
|
+
finite(b.y, "bounds.y");
|
|
29
|
+
finite(b.width, "bounds.width", true);
|
|
30
|
+
finite(b.height, "bounds.height", true);
|
|
31
|
+
const nodeWidth = finite(options.nodeWidth ?? 18, "nodeWidth", true), nodeGap = finite(options.nodeGap ?? 12, "nodeGap", true);
|
|
32
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
33
|
+
for (const node of graph.nodes) {
|
|
34
|
+
const key = access(options.nodeKey, node);
|
|
35
|
+
if (nodes.has(key))
|
|
36
|
+
throw new Error(`layoutSankey: duplicate node key ${String(key)}.`);
|
|
37
|
+
nodes.set(key, node);
|
|
38
|
+
}
|
|
39
|
+
const edges = graph.edges.map((edge) => {
|
|
40
|
+
const key = access(options.edgeKey, edge), sourceKey = access(options.source, edge), targetKey = access(options.target, edge), value = finite(access(options.value, edge), "edge value", true);
|
|
41
|
+
if (!nodes.has(sourceKey) || !nodes.has(targetKey))
|
|
42
|
+
throw new RangeError("layoutSankey: edge endpoint is not a node key.");
|
|
43
|
+
return { key, edge, sourceKey, targetKey, value };
|
|
44
|
+
});
|
|
45
|
+
const incoming = /* @__PURE__ */ new Map(), outgoing = /* @__PURE__ */ new Map(), targets = /* @__PURE__ */ new Map();
|
|
46
|
+
for (const key of nodes.keys()) {
|
|
47
|
+
incoming.set(key, 0);
|
|
48
|
+
outgoing.set(key, 0);
|
|
49
|
+
targets.set(key, []);
|
|
50
|
+
}
|
|
51
|
+
for (const edge of edges) {
|
|
52
|
+
incoming.set(
|
|
53
|
+
edge.targetKey,
|
|
54
|
+
finite(
|
|
55
|
+
incoming.get(edge.targetKey) + edge.value,
|
|
56
|
+
"incoming total",
|
|
57
|
+
true
|
|
58
|
+
)
|
|
59
|
+
);
|
|
60
|
+
outgoing.set(
|
|
61
|
+
edge.sourceKey,
|
|
62
|
+
finite(
|
|
63
|
+
outgoing.get(edge.sourceKey) + edge.value,
|
|
64
|
+
"outgoing total",
|
|
65
|
+
true
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
targets.get(edge.sourceKey).push(edge.targetKey);
|
|
69
|
+
}
|
|
70
|
+
const ranks = /* @__PURE__ */ new Map();
|
|
71
|
+
const visit = (key, visiting = /* @__PURE__ */ new Set()) => {
|
|
72
|
+
if (ranks.has(key)) return ranks.get(key);
|
|
73
|
+
if (visiting.has(key))
|
|
74
|
+
throw new RangeError("layoutSankey: flows must be acyclic.");
|
|
75
|
+
visiting.add(key);
|
|
76
|
+
let rank = 0;
|
|
77
|
+
for (const target of targets.get(key))
|
|
78
|
+
rank = Math.max(rank, visit(target, visiting) + 1);
|
|
79
|
+
visiting.delete(key);
|
|
80
|
+
ranks.set(key, rank);
|
|
81
|
+
return rank;
|
|
82
|
+
};
|
|
83
|
+
for (const key of nodes.keys()) visit(key);
|
|
84
|
+
const maxRank = Math.max(...ranks.values(), 0);
|
|
85
|
+
for (const [key, rank] of ranks) ranks.set(key, maxRank - rank);
|
|
86
|
+
const columns = Array.from({ length: maxRank + 1 }, () => []);
|
|
87
|
+
for (const key of nodes.keys()) columns[ranks.get(key)].push(key);
|
|
88
|
+
const candidateScale = Math.min(
|
|
89
|
+
...columns.map((column) => {
|
|
90
|
+
const sum = column.reduce(
|
|
91
|
+
(total, key) => total + Math.max(incoming.get(key), outgoing.get(key)),
|
|
92
|
+
0
|
|
93
|
+
);
|
|
94
|
+
finite(sum, "column total", true);
|
|
95
|
+
return sum > 0 ? Math.max(
|
|
96
|
+
0,
|
|
97
|
+
(b.height - Math.max(0, column.length - 1) * nodeGap) / sum
|
|
98
|
+
) : Infinity;
|
|
99
|
+
}).filter(Number.isFinite)
|
|
100
|
+
);
|
|
101
|
+
const scale = Number.isFinite(candidateScale) ? candidateScale : 0;
|
|
102
|
+
const geometry = /* @__PURE__ */ new Map();
|
|
103
|
+
columns.forEach((column, rank) => {
|
|
104
|
+
let y = b.y;
|
|
105
|
+
for (const key of column) {
|
|
106
|
+
const datum = nodes.get(key);
|
|
107
|
+
const size = Math.max(incoming.get(key), outgoing.get(key)) * scale;
|
|
108
|
+
const bounds = Object.freeze({
|
|
109
|
+
x: b.x + rank * (maxRank === 0 ? 0 : (b.width - nodeWidth) / maxRank),
|
|
110
|
+
y,
|
|
111
|
+
width: nodeWidth,
|
|
112
|
+
height: size
|
|
113
|
+
});
|
|
114
|
+
const name = options.label ? access(options.label, datum) : String(key);
|
|
115
|
+
const quantity = Math.max(incoming.get(key), outgoing.get(key));
|
|
116
|
+
const labelBounds = Object.freeze({
|
|
117
|
+
x: bounds.x + bounds.width + 8,
|
|
118
|
+
y: bounds.y + Math.max(0, bounds.height / 2 - 14),
|
|
119
|
+
width: 132,
|
|
120
|
+
height: 16
|
|
121
|
+
});
|
|
122
|
+
const detailBounds = Object.freeze({
|
|
123
|
+
x: labelBounds.x,
|
|
124
|
+
y: labelBounds.y + 16,
|
|
125
|
+
width: labelBounds.width,
|
|
126
|
+
height: 16
|
|
127
|
+
});
|
|
128
|
+
const detailText = options.detail ? access(options.detail, datum) : options.formatValue ? options.formatValue(quantity) : `${quantity} ${options.unit}`;
|
|
129
|
+
geometry.set(
|
|
130
|
+
key,
|
|
131
|
+
Object.freeze({
|
|
132
|
+
key,
|
|
133
|
+
datum,
|
|
134
|
+
bounds,
|
|
135
|
+
incomingValue: incoming.get(key),
|
|
136
|
+
outgoingValue: outgoing.get(key),
|
|
137
|
+
netValue: outgoing.get(key) - incoming.get(key),
|
|
138
|
+
label: Object.freeze({
|
|
139
|
+
text: name,
|
|
140
|
+
bounds: labelBounds,
|
|
141
|
+
rotationDegrees: 0
|
|
142
|
+
}),
|
|
143
|
+
detail: Object.freeze({
|
|
144
|
+
text: detailText,
|
|
145
|
+
bounds: detailBounds,
|
|
146
|
+
rotationDegrees: 0
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
y += size + nodeGap;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
const sourceOffsets = /* @__PURE__ */ new Map(), targetOffsets = /* @__PURE__ */ new Map();
|
|
154
|
+
for (const key of nodes.keys()) {
|
|
155
|
+
sourceOffsets.set(key, 0);
|
|
156
|
+
targetOffsets.set(key, 0);
|
|
157
|
+
}
|
|
158
|
+
const flows = edges.map(
|
|
159
|
+
({ key, edge, sourceKey, targetKey, value }) => {
|
|
160
|
+
const source = geometry.get(sourceKey), target = geometry.get(targetKey), thickness = value * scale;
|
|
161
|
+
const sourceTop = source.bounds.y + sourceOffsets.get(sourceKey);
|
|
162
|
+
const targetTop = target.bounds.y + targetOffsets.get(targetKey);
|
|
163
|
+
sourceOffsets.set(sourceKey, sourceOffsets.get(sourceKey) + thickness);
|
|
164
|
+
targetOffsets.set(targetKey, targetOffsets.get(targetKey) + thickness);
|
|
165
|
+
const sourceSpan = Object.freeze({
|
|
166
|
+
top: Object.freeze({
|
|
167
|
+
x: source.bounds.x + source.bounds.width,
|
|
168
|
+
y: sourceTop
|
|
169
|
+
}),
|
|
170
|
+
bottom: Object.freeze({
|
|
171
|
+
x: source.bounds.x + source.bounds.width,
|
|
172
|
+
y: sourceTop + thickness
|
|
173
|
+
})
|
|
174
|
+
});
|
|
175
|
+
const targetSpan = Object.freeze({
|
|
176
|
+
top: Object.freeze({ x: target.bounds.x, y: targetTop }),
|
|
177
|
+
bottom: Object.freeze({ x: target.bounds.x, y: targetTop + thickness })
|
|
178
|
+
});
|
|
179
|
+
const middle = (sourceSpan.top.x + targetSpan.top.x) / 2;
|
|
180
|
+
const segments = Object.freeze([
|
|
181
|
+
{ type: "move", x: sourceSpan.top.x, y: sourceSpan.top.y },
|
|
182
|
+
{
|
|
183
|
+
type: "cubic",
|
|
184
|
+
cp1x: middle,
|
|
185
|
+
cp1y: sourceSpan.top.y,
|
|
186
|
+
cp2x: middle,
|
|
187
|
+
cp2y: targetSpan.top.y,
|
|
188
|
+
x: targetSpan.top.x,
|
|
189
|
+
y: targetSpan.top.y
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
type: "line",
|
|
193
|
+
x: targetSpan.bottom.x,
|
|
194
|
+
y: targetSpan.bottom.y
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
type: "cubic",
|
|
198
|
+
cp1x: middle,
|
|
199
|
+
cp1y: targetSpan.bottom.y,
|
|
200
|
+
cp2x: middle,
|
|
201
|
+
cp2y: sourceSpan.bottom.y,
|
|
202
|
+
x: sourceSpan.bottom.x,
|
|
203
|
+
y: sourceSpan.bottom.y
|
|
204
|
+
},
|
|
205
|
+
{ type: "close" }
|
|
206
|
+
]);
|
|
207
|
+
return Object.freeze({
|
|
208
|
+
key,
|
|
209
|
+
datum: edge,
|
|
210
|
+
sourceKey,
|
|
211
|
+
targetKey,
|
|
212
|
+
value,
|
|
213
|
+
unit: options.unit,
|
|
214
|
+
thickness,
|
|
215
|
+
sourceSpan,
|
|
216
|
+
targetSpan,
|
|
217
|
+
route: Object.freeze({
|
|
218
|
+
sourceAnchor: sourceSpan.top,
|
|
219
|
+
targetAnchor: targetSpan.top,
|
|
220
|
+
segments,
|
|
221
|
+
arrowSegments: null
|
|
222
|
+
}),
|
|
223
|
+
segments,
|
|
224
|
+
path: path(segments),
|
|
225
|
+
arrowPath: null
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
return Object.freeze({
|
|
230
|
+
bounds: Object.freeze({ ...b }),
|
|
231
|
+
unit: options.unit,
|
|
232
|
+
nodes: Object.freeze(Array.from(geometry.values())),
|
|
233
|
+
flows: Object.freeze(flows)
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function defaultSankeyNodeStyle(_node) {
|
|
237
|
+
return { fill: "#0f766e", cornerRadius: 3 };
|
|
238
|
+
}
|
|
239
|
+
function defaultSankeyFlowStyle(_flow) {
|
|
240
|
+
return { fill: "rgba(15, 118, 110, 0.34)" };
|
|
241
|
+
}
|
|
242
|
+
function SankeyNode({
|
|
243
|
+
node,
|
|
244
|
+
style: input,
|
|
245
|
+
children,
|
|
246
|
+
...events
|
|
247
|
+
}) {
|
|
248
|
+
return /* @__PURE__ */ jsx(GraphNode, { node, style: input, ...events, children });
|
|
249
|
+
}
|
|
250
|
+
function SankeyFlow({
|
|
251
|
+
flow,
|
|
252
|
+
style: input,
|
|
253
|
+
...events
|
|
254
|
+
}) {
|
|
255
|
+
return /* @__PURE__ */ jsx(
|
|
256
|
+
SvgPath,
|
|
257
|
+
{
|
|
258
|
+
...events,
|
|
259
|
+
style: { ...resolveSignalValue(input) ?? {}, d: flow.path }
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
function Sankey(props) {
|
|
264
|
+
const frame = useGraphFrame(props.style), style = frame.style;
|
|
265
|
+
if (!frame.bounds.width || !frame.bounds.height)
|
|
266
|
+
return /* @__PURE__ */ jsx(Group, { style: frame.groupStyle, children: null });
|
|
267
|
+
const layout = layoutSankey(resolveSignalValue(props.graph), {
|
|
268
|
+
...props,
|
|
269
|
+
bounds: frame.bounds,
|
|
270
|
+
nodeWidth: style.nodeWidth,
|
|
271
|
+
nodeGap: style.nodeGap
|
|
272
|
+
});
|
|
273
|
+
return /* @__PURE__ */ jsxs(Group, { style: frame.groupStyle, children: [
|
|
274
|
+
layout.flows.map((flow) => /* @__PURE__ */ jsx(
|
|
275
|
+
Group,
|
|
276
|
+
{
|
|
277
|
+
onClick: (event) => props.onFlowClick?.(flow, event),
|
|
278
|
+
children: props.renderFlow ? props.renderFlow(flow) : /* @__PURE__ */ jsx(
|
|
279
|
+
SankeyFlow,
|
|
280
|
+
{
|
|
281
|
+
flow,
|
|
282
|
+
style: {
|
|
283
|
+
...defaultSankeyFlowStyle(flow),
|
|
284
|
+
...resolveMarkStyle(flow, props.flowStyle)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
)
|
|
288
|
+
},
|
|
289
|
+
String(flow.key)
|
|
290
|
+
)),
|
|
291
|
+
layout.nodes.map((node) => /* @__PURE__ */ jsx(
|
|
292
|
+
Group,
|
|
293
|
+
{
|
|
294
|
+
onClick: (event) => props.onNodeClick?.(node, event),
|
|
295
|
+
children: props.renderNode ? props.renderNode(node) : /* @__PURE__ */ jsxs(Group, { children: [
|
|
296
|
+
/* @__PURE__ */ jsx(
|
|
297
|
+
SankeyNode,
|
|
298
|
+
{
|
|
299
|
+
node,
|
|
300
|
+
style: {
|
|
301
|
+
...defaultSankeyNodeStyle(node),
|
|
302
|
+
...resolveMarkStyle(node, props.nodeStyle)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
),
|
|
306
|
+
/* @__PURE__ */ jsx(
|
|
307
|
+
GraphLabel,
|
|
308
|
+
{
|
|
309
|
+
label: node.label,
|
|
310
|
+
style: {
|
|
311
|
+
...defaultGraphLabelStyle(node.label),
|
|
312
|
+
...resolveSignalValue(props.labelStyle)
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
),
|
|
316
|
+
/* @__PURE__ */ jsx(
|
|
317
|
+
GraphLabel,
|
|
318
|
+
{
|
|
319
|
+
label: node.detail,
|
|
320
|
+
style: {
|
|
321
|
+
...defaultGraphLabelStyle(node.detail),
|
|
322
|
+
font: "11px sans-serif",
|
|
323
|
+
...resolveSignalValue(props.labelStyle)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
)
|
|
327
|
+
] })
|
|
328
|
+
},
|
|
329
|
+
String(node.key)
|
|
330
|
+
))
|
|
331
|
+
] });
|
|
332
|
+
}
|
|
333
|
+
export {
|
|
334
|
+
Sankey,
|
|
335
|
+
SankeyFlow,
|
|
336
|
+
SankeyNode,
|
|
337
|
+
defaultSankeyFlowStyle,
|
|
338
|
+
defaultSankeyNodeStyle,
|
|
339
|
+
layoutSankey
|
|
340
|
+
};
|
|
341
|
+
//# sourceMappingURL=sankey.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/features/viz/lib/graph/sankey.tsx"],
|
|
4
|
+
"sourcesContent": ["import type { NodeStyle } from \"./types.js\";\nimport { Group, SvgPath, resolveSignalValue } from \"@pibbl/core\";\nimport type { PibblNode, PathSegment } from \"@pibbl/core\";\nimport type {\n Accessor,\n GraphData,\n GraphNodeProps,\n MarkInteraction,\n SankeyFlowGeometry,\n SankeyLayout,\n SankeyNodeGeometry,\n SankeyOptions,\n SankeyProps,\n Style,\n EdgeStyle,\n VizKey,\n} from \"./types.js\";\nimport {\n defaultGraphLabelStyle,\n GraphLabel,\n GraphNode,\n resolveMarkStyle,\n useGraphFrame,\n} from \"./shared.js\";\n\nfunction access<D, V>(input: Accessor<D, V>, datum: D): V {\n return typeof input === \"function\"\n ? input(datum)\n : (datum as Record<PropertyKey, V>)[input];\n}\nfunction finite(value: number, name: string, zero = false) {\n if (!Number.isFinite(value) || (zero && value < 0))\n throw new RangeError(\n `layoutSankey: ${name} must be finite${zero ? \" and nonnegative\" : \"\"}.`,\n );\n return value;\n}\nfunction path(segments: readonly PathSegment[]) {\n return segments\n .map((segment) =>\n segment.type === \"move\"\n ? `M ${segment.x} ${segment.y}`\n : segment.type === \"line\"\n ? `L ${segment.x} ${segment.y}`\n : segment.type === \"cubic\"\n ? `C ${segment.cp1x} ${segment.cp1y} ${segment.cp2x} ${segment.cp2y} ${segment.x} ${segment.y}`\n : segment.type === \"close\"\n ? \"Z\"\n : \"\",\n )\n .join(\" \");\n}\n\n/** Places an acyclic weighted flow graph in deterministic left-to-right ranks.\n * @param graph - Nodes and acyclic weighted edges. See {@link GraphData}.\n * @param options - Accessors, bounds, and display unit. See {@link SankeyOptions}.\n * @returns Immutable nodes and proportional flow geometry. See {@link SankeyLayout}.\n */\nexport function layoutSankey<N, E>(\n graph: GraphData<N, E>,\n options: SankeyOptions<N, E>,\n): SankeyLayout<N, E> {\n const b = options.bounds;\n finite(b.x, \"bounds.x\");\n finite(b.y, \"bounds.y\");\n finite(b.width, \"bounds.width\", true);\n finite(b.height, \"bounds.height\", true);\n const nodeWidth = finite(options.nodeWidth ?? 18, \"nodeWidth\", true),\n nodeGap = finite(options.nodeGap ?? 12, \"nodeGap\", true);\n const nodes = new Map<VizKey, N>();\n for (const node of graph.nodes) {\n const key = access(options.nodeKey, node);\n if (nodes.has(key))\n throw new Error(`layoutSankey: duplicate node key ${String(key)}.`);\n nodes.set(key, node);\n }\n const edges = graph.edges.map((edge) => {\n const key = access(options.edgeKey, edge),\n sourceKey = access(options.source, edge),\n targetKey = access(options.target, edge),\n value = finite(access(options.value, edge), \"edge value\", true);\n if (!nodes.has(sourceKey) || !nodes.has(targetKey))\n throw new RangeError(\"layoutSankey: edge endpoint is not a node key.\");\n return { key, edge, sourceKey, targetKey, value };\n });\n const incoming = new Map<VizKey, number>(),\n outgoing = new Map<VizKey, number>(),\n targets = new Map<VizKey, VizKey[]>();\n for (const key of nodes.keys()) {\n incoming.set(key, 0);\n outgoing.set(key, 0);\n targets.set(key, []);\n }\n for (const edge of edges) {\n incoming.set(\n edge.targetKey,\n finite(\n incoming.get(edge.targetKey)! + edge.value,\n \"incoming total\",\n true,\n ),\n );\n outgoing.set(\n edge.sourceKey,\n finite(\n outgoing.get(edge.sourceKey)! + edge.value,\n \"outgoing total\",\n true,\n ),\n );\n targets.get(edge.sourceKey)!.push(edge.targetKey);\n }\n const ranks = new Map<VizKey, number>();\n const visit = (key: VizKey, visiting = new Set<VizKey>()): number => {\n if (ranks.has(key)) return ranks.get(key)!;\n if (visiting.has(key))\n throw new RangeError(\"layoutSankey: flows must be acyclic.\");\n visiting.add(key);\n let rank = 0;\n for (const target of targets.get(key)!)\n rank = Math.max(rank, visit(target, visiting) + 1);\n visiting.delete(key);\n ranks.set(key, rank);\n return rank;\n };\n for (const key of nodes.keys()) visit(key);\n const maxRank = Math.max(...ranks.values(), 0);\n for (const [key, rank] of ranks) ranks.set(key, maxRank - rank);\n const columns = Array.from({ length: maxRank + 1 }, () => [] as VizKey[]);\n for (const key of nodes.keys()) columns[ranks.get(key)!].push(key);\n const candidateScale = Math.min(\n ...columns\n .map((column) => {\n const sum = column.reduce<number>(\n (total, key) =>\n total + Math.max(incoming.get(key)!, outgoing.get(key)!),\n 0,\n );\n finite(sum, \"column total\", true);\n return sum > 0\n ? Math.max(\n 0,\n (b.height - Math.max(0, column.length - 1) * nodeGap) / sum,\n )\n : Infinity;\n })\n .filter(Number.isFinite),\n );\n const scale = Number.isFinite(candidateScale) ? candidateScale : 0;\n const geometry = new Map<VizKey, SankeyNodeGeometry<N>>();\n columns.forEach((column, rank) => {\n let y = b.y;\n for (const key of column) {\n const datum = nodes.get(key)!;\n const size = Math.max(incoming.get(key)!, outgoing.get(key)!) * scale;\n const bounds = Object.freeze({\n x: b.x + rank * (maxRank === 0 ? 0 : (b.width - nodeWidth) / maxRank),\n y,\n width: nodeWidth,\n height: size,\n });\n const name = options.label ? access(options.label, datum) : String(key);\n const quantity = Math.max(incoming.get(key)!, outgoing.get(key)!);\n const labelBounds = Object.freeze({\n x: bounds.x + bounds.width + 8,\n y: bounds.y + Math.max(0, bounds.height / 2 - 14),\n width: 132,\n height: 16,\n });\n const detailBounds = Object.freeze({\n x: labelBounds.x,\n y: labelBounds.y + 16,\n width: labelBounds.width,\n height: 16,\n });\n const detailText = options.detail\n ? access(options.detail, datum)\n : options.formatValue\n ? options.formatValue(quantity)\n : `${quantity} ${options.unit}`;\n geometry.set(\n key,\n Object.freeze({\n key,\n datum,\n bounds,\n incomingValue: incoming.get(key)!,\n outgoingValue: outgoing.get(key)!,\n netValue: outgoing.get(key)! - incoming.get(key)!,\n label: Object.freeze({\n text: name,\n bounds: labelBounds,\n rotationDegrees: 0,\n }),\n detail: Object.freeze({\n text: detailText,\n bounds: detailBounds,\n rotationDegrees: 0,\n }),\n }),\n );\n y += size + nodeGap;\n }\n });\n const sourceOffsets = new Map<VizKey, number>(),\n targetOffsets = new Map<VizKey, number>();\n for (const key of nodes.keys()) {\n sourceOffsets.set(key, 0);\n targetOffsets.set(key, 0);\n }\n const flows: SankeyFlowGeometry<E>[] = edges.map(\n ({ key, edge, sourceKey, targetKey, value }) => {\n const source = geometry.get(sourceKey)!,\n target = geometry.get(targetKey)!,\n thickness = value * scale;\n const sourceTop = source.bounds.y + sourceOffsets.get(sourceKey)!;\n const targetTop = target.bounds.y + targetOffsets.get(targetKey)!;\n sourceOffsets.set(sourceKey, sourceOffsets.get(sourceKey)! + thickness);\n targetOffsets.set(targetKey, targetOffsets.get(targetKey)! + thickness);\n const sourceSpan = Object.freeze({\n top: Object.freeze({\n x: source.bounds.x + source.bounds.width,\n y: sourceTop,\n }),\n bottom: Object.freeze({\n x: source.bounds.x + source.bounds.width,\n y: sourceTop + thickness,\n }),\n });\n const targetSpan = Object.freeze({\n top: Object.freeze({ x: target.bounds.x, y: targetTop }),\n bottom: Object.freeze({ x: target.bounds.x, y: targetTop + thickness }),\n });\n const middle = (sourceSpan.top.x + targetSpan.top.x) / 2;\n const segments = Object.freeze([\n { type: \"move\" as const, x: sourceSpan.top.x, y: sourceSpan.top.y },\n {\n type: \"cubic\" as const,\n cp1x: middle,\n cp1y: sourceSpan.top.y,\n cp2x: middle,\n cp2y: targetSpan.top.y,\n x: targetSpan.top.x,\n y: targetSpan.top.y,\n },\n {\n type: \"line\" as const,\n x: targetSpan.bottom.x,\n y: targetSpan.bottom.y,\n },\n {\n type: \"cubic\" as const,\n cp1x: middle,\n cp1y: targetSpan.bottom.y,\n cp2x: middle,\n cp2y: sourceSpan.bottom.y,\n x: sourceSpan.bottom.x,\n y: sourceSpan.bottom.y,\n },\n { type: \"close\" as const },\n ]);\n return Object.freeze({\n key,\n datum: edge,\n sourceKey,\n targetKey,\n value,\n unit: options.unit,\n thickness,\n sourceSpan,\n targetSpan,\n route: Object.freeze({\n sourceAnchor: sourceSpan.top,\n targetAnchor: targetSpan.top,\n segments,\n arrowSegments: null,\n }),\n segments,\n path: path(segments),\n arrowPath: null,\n });\n },\n );\n return Object.freeze({\n bounds: Object.freeze({ ...b }),\n unit: options.unit,\n nodes: Object.freeze(Array.from(geometry.values())),\n flows: Object.freeze(flows),\n });\n}\n\n/** Default node paint for custom Sankey compositions.\n * @param _node - Node geometry.\n * @returns Resolved node paint.\n * @see {@link SankeyNode}\n */\nexport function defaultSankeyNodeStyle<N>(\n _node: SankeyNodeGeometry<N>,\n): NodeStyle {\n return { fill: \"#0f766e\", cornerRadius: 3 };\n}\n/** Default flow paint for custom Sankey compositions.\n * @param _flow - Flow geometry.\n * @returns Resolved flow paint.\n * @see {@link SankeyFlow}\n */\nexport function defaultSankeyFlowStyle<E>(\n _flow: SankeyFlowGeometry<E>,\n): EdgeStyle {\n return { fill: \"rgba(15, 118, 110, 0.34)\" };\n}\n/** Draw one supplied Sankey node.\n * @param argument - Node props.\n * @returns Canvas node.\n * @see {@link SankeyNodeGeometry}\n */\nexport function SankeyNode<N>({\n node,\n style: input,\n children,\n ...events\n}: GraphNodeProps<N> & { readonly node: SankeyNodeGeometry<N> }): PibblNode {\n return (\n <GraphNode node={node} style={input} {...events}>\n {children}\n </GraphNode>\n );\n}\n/** Draw one supplied Sankey flow.\n * @param argument - Flow props.\n * @returns Canvas node.\n * @see {@link SankeyFlowGeometry}\n */\nexport function SankeyFlow<E>({\n flow,\n style: input,\n ...events\n}: MarkInteraction & {\n readonly flow: SankeyFlowGeometry<E>;\n readonly style?: Style<EdgeStyle>;\n}): PibblNode {\n return (\n <SvgPath\n {...events}\n style={{ ...(resolveSignalValue(input) ?? {}), d: flow.path }}\n />\n );\n}\n/** Render a weighted acyclic flow graph.\n * @param props - Graph data and presentation.\n * @returns Canvas node.\n * @see {@link layoutSankey}\n */\nexport function Sankey<N, E>(props: SankeyProps<N, E>): PibblNode {\n const frame = useGraphFrame(props.style),\n style = frame.style;\n if (!frame.bounds.width || !frame.bounds.height)\n return <Group style={frame.groupStyle}>{null}</Group>;\n const layout = layoutSankey(resolveSignalValue(props.graph), {\n ...props,\n bounds: frame.bounds,\n nodeWidth: style.nodeWidth,\n nodeGap: style.nodeGap,\n });\n return (\n <Group style={frame.groupStyle}>\n {layout.flows.map((flow) => (\n <Group\n key={String(flow.key)}\n onClick={(event) => props.onFlowClick?.(flow, event)}\n >\n {props.renderFlow ? (\n props.renderFlow(flow)\n ) : (\n <SankeyFlow\n flow={flow}\n style={{\n ...defaultSankeyFlowStyle(flow),\n ...resolveMarkStyle(flow, props.flowStyle),\n }}\n />\n )}\n </Group>\n ))}\n {layout.nodes.map((node) => (\n <Group\n key={String(node.key)}\n onClick={(event) => props.onNodeClick?.(node, event)}\n >\n {props.renderNode ? (\n props.renderNode(node)\n ) : (\n <Group>\n <SankeyNode\n node={node}\n style={{\n ...defaultSankeyNodeStyle(node),\n ...resolveMarkStyle(node, props.nodeStyle),\n }}\n />\n <GraphLabel\n label={node.label}\n style={{\n ...defaultGraphLabelStyle(node.label),\n ...resolveSignalValue(props.labelStyle),\n }}\n />\n <GraphLabel\n label={node.detail!}\n style={{\n ...defaultGraphLabelStyle(node.detail!),\n font: \"11px sans-serif\",\n ...resolveSignalValue(props.labelStyle),\n }}\n />\n </Group>\n )}\n </Group>\n ))}\n </Group>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { GStyle, SystemStyle, PibblResponsiveStyle, PibblNode } from "@pibbl/core";
|
|
2
|
+
import type { Accessor, Bounds, Style, MarkStyle, GraphNodeGeometry, GraphNodeProps, GraphEdgeGeometry, GraphEdgeProps, GraphLabelProps, GraphViewProps, LabelGeometry, NodeStyle, EdgeStyle, LabelStyle, VizKey } from "./types.js";
|
|
3
|
+
/** Read an application's typed property or accessor without normalizing away its record. */
|
|
4
|
+
export declare function readAccessor<D, V>(datum: D, accessor: Accessor<D, V>): V;
|
|
5
|
+
/** Validate a finite rectangle in local logical units. */
|
|
6
|
+
export declare function validateBounds(bounds: Bounds): Bounds;
|
|
7
|
+
export declare function validKey(key: VizKey): VizKey;
|
|
8
|
+
/** Resolve ordinary responsive frame style through public sizing and allocation. */
|
|
9
|
+
export declare function useGraphFrame<S extends GStyle>(input?: Style<S>): {
|
|
10
|
+
bounds: Bounds;
|
|
11
|
+
style: S;
|
|
12
|
+
groupStyle: GStyle;
|
|
13
|
+
};
|
|
14
|
+
/** Resolve a per-item paint callback without hiding its signal reads. */
|
|
15
|
+
export declare function resolveMarkStyle<G, S extends SystemStyle>(geometry: G, input?: MarkStyle<G, S>): PibblResponsiveStyle<S> | undefined;
|
|
16
|
+
/** Build inspectable label regions and original-record node geometry. */
|
|
17
|
+
export declare function graphNodeGeometry<N>(datum: N, key: VizKey, bounds: Bounds, label?: string, detail?: string): GraphNodeGeometry<N>;
|
|
18
|
+
/**
|
|
19
|
+
* Return the built-in node paint as an ordinary reusable style.
|
|
20
|
+
* @param _node - The node being painted. See {@link GraphNodeGeometry}.
|
|
21
|
+
* @returns Default fill, stroke and corner radius. See {@link NodeStyle}.
|
|
22
|
+
*/
|
|
23
|
+
export declare function defaultGraphNodeStyle<N>(_node: GraphNodeGeometry<N>): NodeStyle;
|
|
24
|
+
/**
|
|
25
|
+
* Return the built-in edge paint as an ordinary reusable style.
|
|
26
|
+
* @param _edge - The edge being painted. See {@link GraphEdgeGeometry}.
|
|
27
|
+
* @returns Default stroke and logical stroke width. See {@link EdgeStyle}.
|
|
28
|
+
*/
|
|
29
|
+
export declare function defaultGraphEdgeStyle<E>(_edge: GraphEdgeGeometry<E>): EdgeStyle;
|
|
30
|
+
/**
|
|
31
|
+
* Return the built-in label paint as an ordinary reusable style.
|
|
32
|
+
* @param _label - The label being painted. See {@link LabelGeometry}.
|
|
33
|
+
* @returns Default Canvas font, fill and middle baseline. See {@link LabelStyle}.
|
|
34
|
+
*/
|
|
35
|
+
export declare function defaultGraphLabelStyle(_label: LabelGeometry): LabelStyle;
|
|
36
|
+
/**
|
|
37
|
+
* Draw a node box; children use node-local coordinates and ordinary Pibbl events.
|
|
38
|
+
* @param props - Box geometry, paint and event handlers. See {@link GraphNodeProps}.
|
|
39
|
+
* @returns A group containing the box and authored children. See {@link GraphNodeProps}.
|
|
40
|
+
*/
|
|
41
|
+
export declare function GraphNode<N>({ node, style, children, ...events }: GraphNodeProps<N>): PibblNode;
|
|
42
|
+
/**
|
|
43
|
+
* Draw an edge path and optional arrow with ordinary path targeting.
|
|
44
|
+
* @param props - Edge geometry, paint and event handlers. See {@link GraphEdgeProps}.
|
|
45
|
+
* @returns Path content in diagram-local coordinates. See {@link GraphEdgeProps}.
|
|
46
|
+
*/
|
|
47
|
+
export declare function GraphEdge<E>({ edge, style, ...events }: GraphEdgeProps<E>): PibblNode;
|
|
48
|
+
/**
|
|
49
|
+
* Draw decorative label text at its supplied box and rotation.
|
|
50
|
+
* @param props - Text geometry and optional text paint. See {@link GraphLabelProps}.
|
|
51
|
+
* @returns A transformed decorative Text component. See {@link GraphLabelProps}.
|
|
52
|
+
*/
|
|
53
|
+
export declare function GraphLabel({ label, style }: GraphLabelProps): PibblNode;
|
|
54
|
+
/**
|
|
55
|
+
* Render supplied graph geometry without layout, fitting, or simulation.
|
|
56
|
+
* @param props - A snapshot or signal, item overrides and events. See {@link GraphViewProps}.
|
|
57
|
+
* @returns An ordinary Pibbl composition preserving source paint order. See {@link GraphViewProps}.
|
|
58
|
+
*/
|
|
59
|
+
export declare function GraphView<N, E>(props: GraphViewProps<N, E>): PibblNode;
|