@weasel-js/diagram 1.13.0 → 1.14.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/README.md +122 -17
- package/dist/{chunk-Y72FK3Y7.js → chunk-5VNPLOIX.js} +94 -6
- package/dist/chunk-5VNPLOIX.js.map +1 -0
- package/dist/{chunk-ESFIS7BB.js → chunk-62SMY45E.js} +918 -574
- package/dist/chunk-62SMY45E.js.map +1 -0
- package/dist/{chunk-FAQXYGMX.js → chunk-TBG6DFB2.js} +3 -3
- package/dist/{chunk-FAQXYGMX.js.map → chunk-TBG6DFB2.js.map} +1 -1
- package/dist/{chunk-L4H444QI.js → chunk-VB6HUKNG.js} +659 -185
- package/dist/chunk-VB6HUKNG.js.map +1 -0
- package/dist/{chunk-QU4QZUC6.js → chunk-ZWXM5F4I.js} +141 -39
- package/dist/chunk-ZWXM5F4I.js.map +1 -0
- package/dist/{dataTypes-DW-MljuN.d.ts → dataTypes-BIkhAOc4.d.ts} +13 -2
- package/dist/effect-audio.d.ts +2 -1
- package/dist/effect-audio.js +6 -5
- package/dist/effect-audio.js.map +1 -1
- package/dist/effect.d.ts +46 -16
- package/dist/effect.js +257 -102
- package/dist/effect.js.map +1 -1
- package/dist/icons.table.js +262 -0
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +262 -0
- package/dist/index.d.ts +491 -167
- package/dist/index.js +586 -36
- package/dist/index.js.map +1 -1
- package/dist/labelTrait-BBjRgxbz.d.ts +44 -0
- package/dist/layout.d.ts +4 -3
- package/dist/{layout.entry-CQoPNfzA.d.ts → layout.entry-Ca6pVvqo.d.ts} +23 -2
- package/dist/layout.js +2 -2
- package/dist/{stageTypes-DvnR8cKQ.d.ts → stageTypes-UiO25hcn.d.ts} +7 -0
- package/dist/{types-vbW21fHm.d.ts → types-B0n2CNTW.d.ts} +108 -81
- package/package.json +11 -9
- package/dist/chunk-ESFIS7BB.js.map +0 -1
- package/dist/chunk-L4H444QI.js.map +0 -1
- package/dist/chunk-QU4QZUC6.js.map +0 -1
- package/dist/chunk-Y72FK3Y7.js.map +0 -1
package/README.md
CHANGED
|
@@ -73,7 +73,8 @@ return <SceneCanvas ref={canvasRef} scene={scene} ambient={[contribution]} />;
|
|
|
73
73
|
|
|
74
74
|
Dragging one port onto another authors an edge. Which pairs may be joined is
|
|
75
75
|
`canConnect`, which defaults to "a port may not join itself, and two ports that
|
|
76
|
-
both declare a `type` must declare the same one".
|
|
76
|
+
both declare a `type` must declare the same one". It answers a `DropVerdict`
|
|
77
|
+
(see "Refusing a drop with a reason").
|
|
77
78
|
|
|
78
79
|
A port may name other places it can sit, in `sites`. An edge meeting it takes
|
|
79
80
|
whichever place faces the edge's next point — its first waypoint, or the other
|
|
@@ -378,7 +379,33 @@ pointer moves onto an overlay. Edges answer only with `pickEdges`. For DOM
|
|
|
378
379
|
the view does not hold, `rectOf(id)` on the ref gives a target's client rect
|
|
379
380
|
and `subscribeFrame` says when to read it again.
|
|
380
381
|
|
|
381
|
-
###
|
|
382
|
+
### Refusing a drop with a reason
|
|
383
|
+
|
|
384
|
+
Every "may this land here?" check answers a `DropVerdict`, the one shape core
|
|
385
|
+
uses too: `true` lands, `false` is a silent no, and `{ refuse: string }` is a
|
|
386
|
+
no the user is told about.
|
|
387
|
+
|
|
388
|
+
| Check | Asked about |
|
|
389
|
+
|---|---|
|
|
390
|
+
| `canConnect(from, to, moving?)` | a new edge's end, or a selected edge's end being moved (`moving` names it) |
|
|
391
|
+
| `canReparent(ids, container)` | nodes dragged into a container or lane they are not already in, once the diagram's own rules allow it |
|
|
392
|
+
| `canDropItem(item, target)` | an item carried in from a palette (see "Dropping items from a palette") |
|
|
393
|
+
|
|
394
|
+
Over a `false` the drag behaves as if the target were not there: a port is
|
|
395
|
+
never snapped to, and a container is passed over for the one around it. Over a
|
|
396
|
+
refusal the canvas outlines the target in the `refused` overlay role and shows
|
|
397
|
+
the reason beside the pointer; a release there reports nothing, and a moved
|
|
398
|
+
node goes back where it was.
|
|
399
|
+
|
|
400
|
+
```tsx
|
|
401
|
+
<DiagramView
|
|
402
|
+
specs={specs}
|
|
403
|
+
canConnect={(from, to) => (to.nodeId === 'source' ? { refuse: 'The source takes no inputs' } : true)}
|
|
404
|
+
canReparent={(_ids, into) => (into === 'shelf' ? { refuse: 'The shelf is locked' } : true)}
|
|
405
|
+
/>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Reordering a group's or a container's members
|
|
382
409
|
|
|
383
410
|
A group with `reorder: 'x' | 'y'` lets `onReorder` drag any of its members
|
|
384
411
|
along that axis; a member that is a group carries everything inside it. The
|
|
@@ -389,9 +416,51 @@ order given across every rank, so writing the order back is all it takes.
|
|
|
389
416
|
|
|
390
417
|
```tsx
|
|
391
418
|
const data = { nodes, edges, groups: [...rows, { id: 'layers', members: order, reorder: 'y' }] };
|
|
392
|
-
<DiagramView specs={diagramScene(data)} onReorder={({ order }) => setOrder(order)} />
|
|
419
|
+
<DiagramView specs={diagramScene(data)} onReorder={({ parent, order }) => setOrder(order)} />
|
|
393
420
|
```
|
|
394
421
|
|
|
422
|
+
A `DataContainer` takes `reorder` the same way, with the same drag, the same
|
|
423
|
+
Alt and arrow key, and the same report: `parent` is the container's id and
|
|
424
|
+
`order` its members in their new order. Nothing moves until the data does, so
|
|
425
|
+
place the members by their order and write it to `members`. A body drag on a
|
|
426
|
+
member of a reorderable container reorders it until the pointer leaves the
|
|
427
|
+
container's box; from there it is a move, reported to `onMove` with the
|
|
428
|
+
`parent` it lands in, as any shape dragged out of a container is.
|
|
429
|
+
|
|
430
|
+
### Dropping items from a palette
|
|
431
|
+
|
|
432
|
+
A list the host renders outside the canvas becomes a palette with
|
|
433
|
+
`dragItemProps(item)`, spread on each entry: a press carries `item`, any value
|
|
434
|
+
of the host's own, over the page. While it is over the diagram, the shape or
|
|
435
|
+
container it would land on is outlined, and in a container marked `reorder` a
|
|
436
|
+
bar marks its place. Release reports an `ItemDrop` to `onDropItem` and adds
|
|
437
|
+
nothing.
|
|
438
|
+
|
|
439
|
+
| Field | What it holds |
|
|
440
|
+
|---|---|
|
|
441
|
+
| `item` | the value `dragItemProps` was given |
|
|
442
|
+
| `target` | the shape or the container it was dropped on, or `null` for the bare canvas |
|
|
443
|
+
| `container` | the container or lane that would hold it: the target when that is one, else the one around the pointer; `null` at the top level |
|
|
444
|
+
| `index` | its place among `container`'s members, along the container's `reorder` axis, else in reading order (top to bottom, then left to right); `null` with no container |
|
|
445
|
+
| `at` | the pointer, in world units |
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
<li {...dragItemProps({ kind: 'blur' })}>Blur</li>
|
|
449
|
+
<DiagramView
|
|
450
|
+
specs={specs}
|
|
451
|
+
onDropItem={({ item, container, index }) => insert(item, container, index)}
|
|
452
|
+
canDropItem={(item, { container }) => (container === 'shelf' ? { refuse: 'The shelf is locked' } : true)}
|
|
453
|
+
/>
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Give each entry `touch-action: none` so a touch drag is a carry, not a scroll.
|
|
457
|
+
`startItemDrag(event, item)` starts one from a pointer event of your own, and
|
|
458
|
+
`createItemDropAction` (or `itemDropContribution`, to pass as `ambient`) is the
|
|
459
|
+
canvas half for a `SceneCanvas` of your own; the carry travels as
|
|
460
|
+
`DIAGRAM_ITEM_CARRY`. There its `report` gets the canvas's deps as well as the
|
|
461
|
+
drop, and `requires` names the ones it reads, so it can add the item itself
|
|
462
|
+
through `insert`. A `ToolPalette` carries from its buttons with `carryTool`.
|
|
463
|
+
|
|
395
464
|
### Stencils
|
|
396
465
|
|
|
397
466
|
A `DiagramStencil` is a palette entry: an id, a label, an outline and a default
|
|
@@ -439,7 +508,7 @@ drawn inside a container or a lane becomes its member (`diagramDropParentAt`).
|
|
|
439
508
|
`containerBuild` returns the ops on their own, and `addLane` and
|
|
440
509
|
`releaseMembers` are the edits as functions.
|
|
441
510
|
|
|
442
|
-
What a region admits is the `canDropInto` dep's call, and `diagramCanDropInto(scene)`
|
|
511
|
+
What a region admits is the `canDropInto` dep's call, and `diagramCanDropInto(scene, canReparent?)`
|
|
443
512
|
is the one for a diagram: containers and lanes take shapes and containers, a
|
|
444
513
|
pool takes only lanes, and a stencil body, an edge, or a label takes nothing.
|
|
445
514
|
`diagramContainers` returns the lane layer to register and the contribution to
|
|
@@ -517,7 +586,7 @@ dragged undoes in one step; `scene.history.seal()` ends the run. `parseDiagramTh
|
|
|
517
586
|
|
|
518
587
|
### Laying it out
|
|
519
588
|
|
|
520
|
-
`layered`, `tree`, `force` and `
|
|
589
|
+
`layered`, `tree`, `force`, `chain`, and `radial` are plain functions of the graph. Each
|
|
521
590
|
hands back the new top-left for every node that **moves** — a node already
|
|
522
591
|
standing where the layout wants it is absent, so re-running a layout on an
|
|
523
592
|
unchanged diagram writes nothing at all.
|
|
@@ -601,6 +670,14 @@ naming ports that face each other, runs on a track of its own in the gap
|
|
|
601
670
|
between them, so a fan of them never crosses; the gap grows to keep tracks 12
|
|
602
671
|
apart. Groups are ignored.
|
|
603
672
|
|
|
673
|
+
`radial` is the mind-map layout. The first root `tree` would find sits in the middle, and its
|
|
674
|
+
children are dealt to its right and its left, in graph order, each to whichever side holds fewer
|
|
675
|
+
nodes so far. Each side grows away from the root as a horizontal `tree`, one band per depth
|
|
676
|
+
`rankGap` apart, its subtrees packed as blocks `nodeGap` apart and centered on the root. Because
|
|
677
|
+
sides are dealt in graph order and each side keeps the order its branches stand in, a second run
|
|
678
|
+
moves nothing. Further trees lay out the same way, stacked below the first. `direction` and groups
|
|
679
|
+
are ignored.
|
|
680
|
+
|
|
604
681
|
### From data
|
|
605
682
|
|
|
606
683
|
`diagramScene` turns plain `{ nodes, edges }` into a laid-out scene, and
|
|
@@ -611,6 +688,11 @@ const specs = useMemo(() => diagramScene(data, { nodeStyle }), [data]);
|
|
|
611
688
|
return <DiagramView specs={specs} width={360} height={600} selected={id} onSelect={setId} />;
|
|
612
689
|
```
|
|
613
690
|
|
|
691
|
+
`onSelect(id, ids)` reports the latest pick and every id picked. With
|
|
692
|
+
`selectionMode="multiple"`, Shift-click adds a node, group or edge to the pick
|
|
693
|
+
or takes it out; `selected` takes one id or an array, and handing back the
|
|
694
|
+
reported `id` leaves the rest picked.
|
|
695
|
+
|
|
614
696
|
Every box is a `buildBody` body, so a data node takes the same knobs a body
|
|
615
697
|
does — `outline`, `rows`, `padding`, `gap`, `verticalAlign`, `ports` — plus `pinned`, a
|
|
616
698
|
starting `at`, and a minimum `width`/`height`; `lines` is shorthand for one
|
|
@@ -628,12 +710,24 @@ give the style an item is drawn in, for a writer that needs it without drawing;
|
|
|
628
710
|
no width, `NODE_STROKE_WIDTH`, `LANE_STROKE_WIDTH`, and `EDGE_STROKE_WIDTH` are what is drawn. `layer` puts every
|
|
629
711
|
spec on a layer other than `'main'`.
|
|
630
712
|
|
|
631
|
-
`outline` is
|
|
632
|
-
`
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
713
|
+
`outline` is a name from the outline table, or a `Path` drawn in a unit square
|
|
714
|
+
— `(0, 0)` the box's top-left, `(1, 1)` its bottom-right — which is stretched
|
|
715
|
+
over the box, so it follows its node as marks do. The built-in names are the
|
|
716
|
+
flowchart shapes `'rect'`, `'diamond'`, `'stadium'`, `'ellipse'`, `'parallelogram'`,
|
|
717
|
+
`'trapezoid'` (a demultiplexer: tall at the right, short at the left), and
|
|
718
|
+
`'hexagon'` (pointed at the left and right, its rows kept between the points);
|
|
719
|
+
`'roundRect'`, `'triangle'`, `'octagon'`, `'cloud'`, `'doubleEllipse'`, and
|
|
720
|
+
`'actor'` (a stick figure, its label in the strip beneath it); and `'cylinder'`,
|
|
721
|
+
`'document'`, `'note'`, `'folder'`, and `'cube'`. Each keeps its rows inside the
|
|
722
|
+
visible shape, clear of a cylinder's cap or a note's fold. Some draw a detail,
|
|
723
|
+
stroked over the fill: a cylinder's rim, a note's fold, a cube's front edges.
|
|
724
|
+
|
|
725
|
+
`registerOutline(name, def)` adds a name, or shadows a built-in until its
|
|
726
|
+
disposer runs. An `OutlineDef` builds `path` in a node's bounds, and optionally
|
|
727
|
+
`detail`, `content` (the box rows lay out in), and `boxForContent` (its inverse,
|
|
728
|
+
for sizing a node to its rows). `outlineFromD(d, { detail, content })` builds one
|
|
729
|
+
from SVG path data in a unit square. A saved name that is not registered paints
|
|
730
|
+
as `'rect'` and warns once.
|
|
637
731
|
|
|
638
732
|
`marks` draws more over a box than its rows. A mark with `d` is SVG path data
|
|
639
733
|
in a unit square, stretched over the node's box; it takes `fill`, `stroke`,
|
|
@@ -720,7 +814,8 @@ A pool always has a box: 600 across and 120 along per lane when it gives none
|
|
|
720
814
|
(`'y'`, rows, by default) at their `size`, and lanes giving none share what
|
|
721
815
|
the pool's box leaves. An edge with an end inside a boxed region ranks against
|
|
722
816
|
the outermost one holding it, and keeps none of layout's route. `pinned`
|
|
723
|
-
leaves a box where it is.
|
|
817
|
+
leaves a box where it is. A container's `reorder` lets `onReorder` drag its
|
|
818
|
+
members along that axis (see "Reordering a group's or a container's members"). Under `theme`, a region naming a `style` role takes
|
|
724
819
|
that role's colors; otherwise a container takes the theme's `container`, a
|
|
725
820
|
pool its `lane.header`, and lanes the `lane.bodies` in turn; titles are set in
|
|
726
821
|
the diagram's face, the theme's when `font` is unset. `router="avoid"`
|
|
@@ -977,7 +1072,7 @@ and a `color(type)` for the ports. `EFFECT_LOOKS` holds `nodeGraph`, `rack`, `la
|
|
|
977
1072
|
| Look | Draws | Options |
|
|
978
1073
|
| --- | --- | --- |
|
|
979
1074
|
| `nodeGraph` (default) | Every port a named row on its stage, a wire from port to port, flowing left to right. | `router` (default `'bezier'`), `nodeGap`, `rankGap`, `colors`, `showParams`, `showValues`, `showPreviews`, `previewSize`, `branch` |
|
|
980
|
-
| `rack` | The main signal on one straight line, and everything else hung beside the stage on the line it is nearest to, whichever way the wire runs. | `chain`, `side`, `nodeGap`, `rankGap`, `colors`, `showParams`, `showValues`, `showPreviews`, `previewSize`, `branch`, `collapseSkips` |
|
|
1075
|
+
| `rack` | The main signal on one straight line, and everything else hung beside the stage on the line it is nearest to, whichever way the wire runs. | `chain`, `direction`, `side`, `nodeGap`, `rankGap`, `colors`, `showParams`, `showValues`, `showPreviews`, `previewSize`, `branch`, `collapseSkips` |
|
|
981
1076
|
| `lanes` | A horizontal lane per value type, and each stage standing across the lanes of the types it reads and writes, as tall as they are, its ports in their own lanes. | `lanes`, `laneHeight`, `rankGap`, `router`, `colors`, `showParams`, `showValues`, `showPreviews`, `previewSize`, `branch`, `measure` |
|
|
982
1077
|
| `compact` | Each stage one line, its title alone, no ports drawn, and one line between two stages however many wires join them. For a pipeline too big to read as a node graph. | `router`, `nodeGap`, `rankGap`, `colors`, `branch` |
|
|
983
1078
|
|
|
@@ -986,8 +1081,16 @@ true) shows the `params` of ordinary stages, sources and sinks; `showValues`
|
|
|
986
1081
|
(default false) keeps a row per output on those stages for a run's values, and
|
|
987
1082
|
`showPreviews` (default false) a slot per output for its previews. `rack` runs
|
|
988
1083
|
along `chain`, a list of stage ids that defaults to the longest path over data
|
|
989
|
-
wires (`mainChain(pipeline)` returns it)
|
|
990
|
-
`'
|
|
1084
|
+
wires (`mainChain(pipeline)` returns it). Its `direction` is `'right'`
|
|
1085
|
+
(default), the line running left to right, or `'down'`, a column the main
|
|
1086
|
+
signal enters at each stage's top and leaves at its bottom, which a reorder
|
|
1087
|
+
drags along vertically. `side` is `'below'` (default) or `'above'`; in a
|
|
1088
|
+
column, `'below'` hangs the side stages on the column's right and `'above'`
|
|
1089
|
+
on its left, and a collapsed skip's arc runs down the other edge. A wire from
|
|
1090
|
+
a stage's main output into the side input of a stage further down the line,
|
|
1091
|
+
past at least one stage, leaves from a tap on the side stages' edge (a port
|
|
1092
|
+
named `~tap:<output>`), so it runs beside the stages between rather than
|
|
1093
|
+
through them; the editor and a run read it as the output it taps.
|
|
991
1094
|
|
|
992
1095
|
`lanes` puts the lanes top down in the order their types first appear on the
|
|
993
1096
|
pipeline's ports, after any it is given in `lanes`. A stage stands
|
|
@@ -1200,7 +1303,9 @@ reports, so the editor gathers them and reports one edit once the drag is done
|
|
|
1200
1303
|
reporting, a microtask later.
|
|
1201
1304
|
|
|
1202
1305
|
`selectedGroup` and `onSelectGroup` are the group pick, beside `selected` and
|
|
1203
|
-
`onSelect`, under every look.
|
|
1306
|
+
`onSelect`, under every look. Shift-click adds a stage or group to the pick or
|
|
1307
|
+
takes it out, and `onSelect`'s second argument lists every stage and group
|
|
1308
|
+
picked, ready for `group(ids)`. The ref's `group(ids)` and `ungroup(id)` report
|
|
1204
1309
|
`'Group'` and `'Ungroup'`, and `renameGroup(id)` opens the title field. The
|
|
1205
1310
|
edits are plain functions too:
|
|
1206
1311
|
|
|
@@ -1317,7 +1422,7 @@ resize; `rayHit` moves it onto the shape. Don't store outline-relative anchors.
|
|
|
1317
1422
|
connect is routing, and lives in the binding's `target`. Which ports a live
|
|
1318
1423
|
connect may land on cannot be routing — the dispatcher never re-reads the
|
|
1319
1424
|
affordance under a moving pointer — so `canConnect` filters the candidate set
|
|
1320
|
-
instead. Neither is an action body inspecting a hit and bailing.
|
|
1425
|
+
instead, and a refusal stays a candidate so it can be drawn refused. Neither is an action body inspecting a hit and bailing.
|
|
1321
1426
|
|
|
1322
1427
|
**A live run does not re-anchor; the one-shot layouts do.** The anchor
|
|
1323
1428
|
translation keeps a single 300-tick jump from moving the diagram off where the
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { labelCenter, samePoints } from './chunk-
|
|
1
|
+
import { labelCenter, DEFAULT_NODE_GAP, DEFAULT_RANK_GAP, forestOf, subtreeBlocks, graphOrder, translated, pinnedSet, samePoints } from './chunk-VB6HUKNG.js';
|
|
2
2
|
import { polylineFromPoints } from '@weasel-js/core/math';
|
|
3
3
|
|
|
4
4
|
// src/hops/types.ts
|
|
@@ -1342,7 +1342,7 @@ function candidatesOf(label, route, tries, spacing) {
|
|
|
1342
1342
|
const length = route.length;
|
|
1343
1343
|
if (length === 0) return out;
|
|
1344
1344
|
const start = typeof at === "object" ? arcNearest(route.points, at.near) : (typeof at === "number" ? at : NAMED[at] ?? 0.5) * length;
|
|
1345
|
-
const
|
|
1345
|
+
const sides2 = offset === 0 ? [0] : [offset, -offset];
|
|
1346
1346
|
const push = (s, side) => {
|
|
1347
1347
|
const spot = { at: s / length, offset: side };
|
|
1348
1348
|
out.push({ placement: { at: spot.at, offset: side }, spot });
|
|
@@ -1353,7 +1353,7 @@ function candidatesOf(label, route, tries, spacing) {
|
|
|
1353
1353
|
for (const dir of [1, -1]) {
|
|
1354
1354
|
const s = start + dir * k * step;
|
|
1355
1355
|
if (s < 0 || s > length) continue;
|
|
1356
|
-
for (const side of
|
|
1356
|
+
for (const side of sides2) push(s, side);
|
|
1357
1357
|
}
|
|
1358
1358
|
}
|
|
1359
1359
|
return out;
|
|
@@ -1426,6 +1426,94 @@ function placeLabels(input, opts = {}) {
|
|
|
1426
1426
|
return out;
|
|
1427
1427
|
}
|
|
1428
1428
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1429
|
+
// src/radial.ts
|
|
1430
|
+
var radial = (graph, opts = {}) => {
|
|
1431
|
+
const nodeGap = opts.nodeGap ?? DEFAULT_NODE_GAP;
|
|
1432
|
+
const rankGap = opts.rankGap ?? DEFAULT_RANK_GAP;
|
|
1433
|
+
const { roots, children } = forestOf(graph, "y");
|
|
1434
|
+
const blocks2 = subtreeBlocks(children, "y", nodeGap);
|
|
1435
|
+
const order2 = graphOrder(graph);
|
|
1436
|
+
const placed = /* @__PURE__ */ new Map();
|
|
1437
|
+
let top = 0;
|
|
1438
|
+
for (const root of roots) {
|
|
1439
|
+
const tree = mindMap(root, children, order2, blocks2, nodeGap, rankGap);
|
|
1440
|
+
for (const [id, p] of tree.at) placed.set(id, { x: p.x, y: p.y - tree.top + top });
|
|
1441
|
+
top += tree.bottom - tree.top + nodeGap;
|
|
1442
|
+
}
|
|
1443
|
+
return translated(graph, placed, pinnedSet(graph, opts), opts.tolerance);
|
|
1444
|
+
};
|
|
1445
|
+
function mindMap(root, children, order2, blocks2, nodeGap, rankGap) {
|
|
1446
|
+
const at = /* @__PURE__ */ new Map([[root.id, { x: -root.bounds.width / 2, y: -root.bounds.height / 2 }]]);
|
|
1447
|
+
let top = -root.bounds.height / 2;
|
|
1448
|
+
let bottom = root.bounds.height / 2;
|
|
1449
|
+
const [right, left] = sides(root, children, order2);
|
|
1450
|
+
for (const [sign2, branches] of [[1, right], [-1, left]]) {
|
|
1451
|
+
if (branches.length === 0) continue;
|
|
1452
|
+
const span = branches.reduce((sum, b) => sum + blocks2.span(b), 0) + (branches.length - 1) * nodeGap;
|
|
1453
|
+
const ys = /* @__PURE__ */ new Map();
|
|
1454
|
+
let cursor = -span / 2;
|
|
1455
|
+
for (const branch of branches) {
|
|
1456
|
+
blocks2.lay(branch, cursor, ys);
|
|
1457
|
+
cursor += blocks2.span(branch) + nodeGap;
|
|
1458
|
+
}
|
|
1459
|
+
top = Math.min(top, -span / 2);
|
|
1460
|
+
bottom = Math.max(bottom, span / 2);
|
|
1461
|
+
for (const [id, x] of sideColumns(branches, children, root.bounds.width / 2 + rankGap, rankGap, sign2)) {
|
|
1462
|
+
at.set(id, { x, y: ys.get(id) });
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
return { at, top, bottom };
|
|
1466
|
+
}
|
|
1467
|
+
function sides(root, children, order2) {
|
|
1468
|
+
const weight = (node) => 1 + (children.get(node.id) ?? []).reduce((sum, k) => sum + weight(k), 0);
|
|
1469
|
+
const kids = children.get(root.id) ?? [];
|
|
1470
|
+
const half = root.bounds.width / 2;
|
|
1471
|
+
const mid = root.bounds.x + half;
|
|
1472
|
+
const standing = (k) => {
|
|
1473
|
+
const c = k.bounds.x + k.bounds.width / 2 - mid;
|
|
1474
|
+
return c > half ? 1 : c < -half ? -1 : 0;
|
|
1475
|
+
};
|
|
1476
|
+
const stands = new Map(kids.map((k) => [k, standing(k)]));
|
|
1477
|
+
const arranged = [...stands.values()].includes(1) && [...stands.values()].includes(-1);
|
|
1478
|
+
const right = /* @__PURE__ */ new Set();
|
|
1479
|
+
let r = 0;
|
|
1480
|
+
let l = 0;
|
|
1481
|
+
const dealt = arranged ? kids.filter((k) => stands.get(k) !== 0) : [];
|
|
1482
|
+
for (const k of dealt) {
|
|
1483
|
+
if (stands.get(k) === 1) {
|
|
1484
|
+
right.add(k);
|
|
1485
|
+
r += weight(k);
|
|
1486
|
+
} else l += weight(k);
|
|
1487
|
+
}
|
|
1488
|
+
for (const child of kids.filter((k) => !dealt.includes(k)).sort((a, b) => order2(a.id) - order2(b.id))) {
|
|
1489
|
+
const w = weight(child);
|
|
1490
|
+
if (r <= l) {
|
|
1491
|
+
right.add(child);
|
|
1492
|
+
r += w;
|
|
1493
|
+
} else l += w;
|
|
1494
|
+
}
|
|
1495
|
+
return [kids.filter((k) => right.has(k)), kids.filter((k) => !right.has(k))];
|
|
1496
|
+
}
|
|
1497
|
+
function sideColumns(branches, children, from, rankGap, sign2) {
|
|
1498
|
+
const rows = [];
|
|
1499
|
+
const visit = (node, depth) => {
|
|
1500
|
+
(rows[depth] ??= []).push(node);
|
|
1501
|
+
for (const kid of children.get(node.id) ?? []) visit(kid, depth + 1);
|
|
1502
|
+
};
|
|
1503
|
+
for (const branch of branches) visit(branch, 0);
|
|
1504
|
+
const xs = /* @__PURE__ */ new Map();
|
|
1505
|
+
let start = from;
|
|
1506
|
+
for (const row of rows) {
|
|
1507
|
+
const band = Math.max(...row.map((n) => n.bounds.width));
|
|
1508
|
+
for (const node of row) {
|
|
1509
|
+
const near = start + (band - node.bounds.width) / 2;
|
|
1510
|
+
xs.set(node.id, sign2 === 1 ? near : -near - node.bounds.width);
|
|
1511
|
+
}
|
|
1512
|
+
start += band + rankGap;
|
|
1513
|
+
}
|
|
1514
|
+
return xs;
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
export { AVOID_DEFAULTS, DEFAULT_HOP_SIZE, HOPS_DOC_KEY, createAvoidRouter, edgeHops, placeLabels, radial, simplifyStops };
|
|
1518
|
+
//# sourceMappingURL=chunk-5VNPLOIX.js.map
|
|
1519
|
+
//# sourceMappingURL=chunk-5VNPLOIX.js.map
|