@leavepulse/ui 0.22.10 → 0.22.12
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/chunks/{LpTopologyCanvas-D_EsMgCg.js → LpTopologyCanvas-ebP67CLx.js} +6 -1
- package/dist/chunks/LpWaypointEdge-D8yHlQiw.js +67 -0
- package/dist/component-names.d.ts +1 -1
- package/dist/components/LpTopologyCanvas.vue.d.ts +15 -0
- package/dist/components/LpTopologyCanvas.vue.js +1 -1
- package/dist/components/LpWaypointEdge.vue.d.ts +21 -0
- package/dist/components/LpWaypointEdge.vue.js +4 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/component-names.ts +2 -1
- package/src/components/LpTopologyCanvas.vue +19 -1
- package/src/components/LpWaypointEdge.vue +77 -0
|
@@ -6,6 +6,7 @@ import { MiniMap } from "@vue-flow/minimap";
|
|
|
6
6
|
import { _ as _sfc_main$3 } from "./LpInfraNode-qIL3l7IO.js";
|
|
7
7
|
import { _ as _sfc_main$1 } from "./LpLaneNode-HtnQf2FF.js";
|
|
8
8
|
import { _ as _sfc_main$2 } from "./LpServiceNode-D8uJ8sGk.js";
|
|
9
|
+
import { _ as _sfc_main$4 } from "./LpWaypointEdge-D8yHlQiw.js";
|
|
9
10
|
const _hoisted_1 = { class: "flex flex-col gap-1.5 rounded-card border border-line bg-surface-overlay/90 px-3 py-2 text-[11px] backdrop-blur" };
|
|
10
11
|
const _hoisted_2 = {
|
|
11
12
|
width: "22",
|
|
@@ -23,6 +24,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
23
24
|
selectable: { type: Boolean, default: false },
|
|
24
25
|
legend: { type: Boolean, default: true },
|
|
25
26
|
legendPosition: { default: "bottom-left" },
|
|
27
|
+
edgeType: {},
|
|
26
28
|
legendLabels: {},
|
|
27
29
|
lanes: { default: () => [] },
|
|
28
30
|
minimap: { type: Boolean, default: true },
|
|
@@ -37,6 +39,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
37
39
|
service: markRaw(_sfc_main$2),
|
|
38
40
|
lane: markRaw(_sfc_main$1)
|
|
39
41
|
};
|
|
42
|
+
const edgeTypes = { waypoints: markRaw(_sfc_main$4) };
|
|
40
43
|
const laneNodes = computed(
|
|
41
44
|
() => props.lanes.map(
|
|
42
45
|
(l) => ({
|
|
@@ -105,7 +108,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
105
108
|
id: e.id,
|
|
106
109
|
source: e.source,
|
|
107
110
|
target: e.target,
|
|
108
|
-
type: "default",
|
|
111
|
+
type: props.edgeType ?? "default",
|
|
112
|
+
data: { waypoints: e.waypoints },
|
|
109
113
|
animated: obs !== "applied" && !e.dimmed,
|
|
110
114
|
label: e.kind,
|
|
111
115
|
labelBgStyle: { fill: "var(--color-surface)" },
|
|
@@ -188,6 +192,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
188
192
|
nodes: flowNodes.value,
|
|
189
193
|
edges: flowEdges.value,
|
|
190
194
|
"node-types": nodeTypes,
|
|
195
|
+
"edge-types": edgeTypes,
|
|
191
196
|
"nodes-connectable": __props.connectable,
|
|
192
197
|
"selection-on-drag": __props.selectable,
|
|
193
198
|
"pan-on-drag": __props.selectable ? [1, 2] : true,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { defineComponent, computed, openBlock, createBlock, unref, normalizeStyle } from "vue";
|
|
2
|
+
import { getBezierPath, Position, BaseEdge } from "@vue-flow/core";
|
|
3
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
4
|
+
__name: "LpWaypointEdge",
|
|
5
|
+
props: {
|
|
6
|
+
id: {},
|
|
7
|
+
sourceX: {},
|
|
8
|
+
sourceY: {},
|
|
9
|
+
targetX: {},
|
|
10
|
+
targetY: {},
|
|
11
|
+
sourcePosition: {},
|
|
12
|
+
targetPosition: {},
|
|
13
|
+
data: {},
|
|
14
|
+
markerEnd: {},
|
|
15
|
+
style: {}
|
|
16
|
+
},
|
|
17
|
+
setup(__props) {
|
|
18
|
+
const props = __props;
|
|
19
|
+
function splineThrough(points) {
|
|
20
|
+
if (points.length < 2) return "";
|
|
21
|
+
const p = [points[0], ...points, points[points.length - 1]];
|
|
22
|
+
let d = `M${points[0].x},${points[0].y}`;
|
|
23
|
+
for (let i = 1; i < p.length - 2; i++) {
|
|
24
|
+
const p0 = p[i - 1];
|
|
25
|
+
const p1 = p[i];
|
|
26
|
+
const p2 = p[i + 1];
|
|
27
|
+
const p3 = p[i + 2];
|
|
28
|
+
const c1x = p1.x + (p2.x - p0.x) / 6;
|
|
29
|
+
const c1y = p1.y + (p2.y - p0.y) / 6;
|
|
30
|
+
const c2x = p2.x - (p3.x - p1.x) / 6;
|
|
31
|
+
const c2y = p2.y - (p3.y - p1.y) / 6;
|
|
32
|
+
d += ` C${c1x},${c1y} ${c2x},${c2y} ${p2.x},${p2.y}`;
|
|
33
|
+
}
|
|
34
|
+
return d;
|
|
35
|
+
}
|
|
36
|
+
const path = computed(() => {
|
|
37
|
+
const via = props.data?.waypoints ?? [];
|
|
38
|
+
if (!via.length) {
|
|
39
|
+
const [d] = getBezierPath({
|
|
40
|
+
sourceX: props.sourceX,
|
|
41
|
+
sourceY: props.sourceY,
|
|
42
|
+
targetX: props.targetX,
|
|
43
|
+
targetY: props.targetY,
|
|
44
|
+
sourcePosition: props.sourcePosition ?? Position.Right,
|
|
45
|
+
targetPosition: props.targetPosition ?? Position.Left
|
|
46
|
+
});
|
|
47
|
+
return d;
|
|
48
|
+
}
|
|
49
|
+
return splineThrough([
|
|
50
|
+
{ x: props.sourceX, y: props.sourceY },
|
|
51
|
+
...via,
|
|
52
|
+
{ x: props.targetX, y: props.targetY }
|
|
53
|
+
]);
|
|
54
|
+
});
|
|
55
|
+
return (_ctx, _cache) => {
|
|
56
|
+
return openBlock(), createBlock(unref(BaseEdge), {
|
|
57
|
+
id: __props.id,
|
|
58
|
+
path: path.value,
|
|
59
|
+
"marker-end": __props.markerEnd,
|
|
60
|
+
style: normalizeStyle(__props.style)
|
|
61
|
+
}, null, 8, ["id", "path", "marker-end", "style"]);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
export {
|
|
66
|
+
_sfc_main as _
|
|
67
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const COMPONENT_NAMES: readonly ["LayoutCanvas", "LayoutNode", "LpAddressInput", "LpAlert", "LpAppShell", "LpAutocomplete", "LpAvatar", "LpBadge", "LpBreadcrumbs", "LpButton", "LpCalendar", "LpCard", "LpCheckbox", "LpCodeBlock", "LpCommandPalette", "LpConfirmDialog", "LpContextMenu", "LpDatePicker", "LpDisclosure", "LpDivider", "LpDrawer", "LpDropdownMenu", "LpEmptyState", "LpFileTree", "LpFileTreeNode", "LpFormField", "LpIcon", "LpInfraNode", "LpInput", "LpLaneNode", "LpLightbox", "LpLink", "LpLogViewer", "LpMapPicker", "LpModal", "LpNotificationBell", "LpNumberField", "LpOtpInput", "LpPagination", "LpPasswordInput", "LpPhoneInput", "LpPopover", "LpProgress", "LpRadio", "LpRadioGroup", "LpScrollArea", "LpSegmented", "LpSelect", "LpServiceNode", "LpShortcutsDialog", "LpSidebar", "LpSidebarNav", "LpSkeleton", "LpSlider", "LpStat", "LpStepper", "LpSwitch", "LpTable", "LpTableOfContents", "LpTabs", "LpTextarea", "LpThemeSwitcher", "LpTilt", "LpToaster", "LpTooltip", "LpTopologyCanvas", "LpUptimeBar"];
|
|
1
|
+
export declare const COMPONENT_NAMES: readonly ["LayoutCanvas", "LayoutNode", "LpAddressInput", "LpAlert", "LpAppShell", "LpAutocomplete", "LpAvatar", "LpBadge", "LpBreadcrumbs", "LpButton", "LpCalendar", "LpCard", "LpCheckbox", "LpCodeBlock", "LpCommandPalette", "LpConfirmDialog", "LpContextMenu", "LpDatePicker", "LpDisclosure", "LpDivider", "LpDrawer", "LpDropdownMenu", "LpEmptyState", "LpFileTree", "LpFileTreeNode", "LpFormField", "LpIcon", "LpInfraNode", "LpInput", "LpLaneNode", "LpLightbox", "LpLink", "LpLogViewer", "LpMapPicker", "LpModal", "LpNotificationBell", "LpNumberField", "LpOtpInput", "LpPagination", "LpPasswordInput", "LpPhoneInput", "LpPopover", "LpProgress", "LpRadio", "LpRadioGroup", "LpScrollArea", "LpSegmented", "LpSelect", "LpServiceNode", "LpShortcutsDialog", "LpSidebar", "LpSidebarNav", "LpSkeleton", "LpSlider", "LpStat", "LpStepper", "LpSwitch", "LpTable", "LpTableOfContents", "LpTabs", "LpTextarea", "LpThemeSwitcher", "LpTilt", "LpToaster", "LpTooltip", "LpTopologyCanvas", "LpUptimeBar", "LpWaypointEdge"];
|
|
@@ -46,6 +46,14 @@ export interface TopologyEdge {
|
|
|
46
46
|
* every unrelated line at full strength.
|
|
47
47
|
*/
|
|
48
48
|
dimmed?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Points the edge should curve through, when the host's layout knows where
|
|
51
|
+
* the gaps are. Requires `edgeType: "waypoints"`; ignored otherwise.
|
|
52
|
+
*/
|
|
53
|
+
waypoints?: {
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
}[];
|
|
49
57
|
}
|
|
50
58
|
/**
|
|
51
59
|
* A background swimlane: a sized zone (one per project / overlay network) drawn
|
|
@@ -90,6 +98,13 @@ type __VLS_Props = {
|
|
|
90
98
|
* minimap owns the bottom-right.
|
|
91
99
|
*/
|
|
92
100
|
legendPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
101
|
+
/**
|
|
102
|
+
* Edge shape. The default bezier bulges away from the straight line between
|
|
103
|
+
* its ends, which suits a free-form graph and cuts through everything in a
|
|
104
|
+
* LAYERED one — a long edge crosses the cards standing between its columns.
|
|
105
|
+
* `smoothstep` routes orthogonally through the gaps instead.
|
|
106
|
+
*/
|
|
107
|
+
edgeType?: "default" | "smoothstep" | "step" | "straight" | "waypoints";
|
|
93
108
|
/** Rename legend rows to match what this graph's edges actually mean. */
|
|
94
109
|
legendLabels?: Partial<Record<"network" | "structural" | "pending" | "drift", string>>;
|
|
95
110
|
/**
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Position } from '@vue-flow/core';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
id: string;
|
|
4
|
+
sourceX: number;
|
|
5
|
+
sourceY: number;
|
|
6
|
+
targetX: number;
|
|
7
|
+
targetY: number;
|
|
8
|
+
sourcePosition?: Position;
|
|
9
|
+
targetPosition?: Position;
|
|
10
|
+
data?: {
|
|
11
|
+
waypoints?: {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
}[];
|
|
15
|
+
};
|
|
16
|
+
markerEnd?: string;
|
|
17
|
+
style?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
package/dist/index.js
CHANGED
|
@@ -64,7 +64,7 @@ import { D, _ as _56, N, T, b, c, d, e, f, g, i, l, h, j, n, r, t, k, m, u, v }
|
|
|
64
64
|
import { _ as _57 } from "./chunks/LpTilt-DuyKbpkA.js";
|
|
65
65
|
import { _ as _58 } from "./chunks/LpToaster-gDB1EaU3.js";
|
|
66
66
|
import { _ as _59 } from "./chunks/LpTooltip-D1hbjQWG.js";
|
|
67
|
-
import { _ as _60 } from "./chunks/LpTopologyCanvas-
|
|
67
|
+
import { _ as _60 } from "./chunks/LpTopologyCanvas-ebP67CLx.js";
|
|
68
68
|
import { _ as _61 } from "./chunks/LpUptimeBar-CB366k0O.js";
|
|
69
69
|
import { deserializeLayout, serializeLayout } from "./layout/tree.js";
|
|
70
70
|
import { addLeaf, addTab, countBlocks, countLeaves, makeLayout, moveLeaf, removeBlock, removeLeaf, reorderTab, resizeAt, setActiveTab } from "./layout/tree.js";
|
package/package.json
CHANGED
package/src/component-names.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { computed, markRaw, watch, type Component } from "vue"
|
|
|
26
26
|
import LpInfraNode, { type InfraNodeData } from "./LpInfraNode.vue"
|
|
27
27
|
import LpLaneNode from "./LpLaneNode.vue"
|
|
28
28
|
import LpServiceNode, { type ServiceNodeData } from "./LpServiceNode.vue"
|
|
29
|
+
import LpWaypointEdge from "./LpWaypointEdge.vue"
|
|
29
30
|
|
|
30
31
|
// Vue Flow base CSS + canvas chrome theming is shipped via the kit's
|
|
31
32
|
// "@leavepulse/ui/canvas.css" export (a plain CSS file). Component-local CSS
|
|
@@ -77,6 +78,11 @@ export interface TopologyEdge {
|
|
|
77
78
|
* every unrelated line at full strength.
|
|
78
79
|
*/
|
|
79
80
|
dimmed?: boolean
|
|
81
|
+
/**
|
|
82
|
+
* Points the edge should curve through, when the host's layout knows where
|
|
83
|
+
* the gaps are. Requires `edgeType: "waypoints"`; ignored otherwise.
|
|
84
|
+
*/
|
|
85
|
+
waypoints?: { x: number; y: number }[]
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
/**
|
|
@@ -125,6 +131,13 @@ const props = withDefaults(
|
|
|
125
131
|
* minimap owns the bottom-right.
|
|
126
132
|
*/
|
|
127
133
|
legendPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right"
|
|
134
|
+
/**
|
|
135
|
+
* Edge shape. The default bezier bulges away from the straight line between
|
|
136
|
+
* its ends, which suits a free-form graph and cuts through everything in a
|
|
137
|
+
* LAYERED one — a long edge crosses the cards standing between its columns.
|
|
138
|
+
* `smoothstep` routes orthogonally through the gaps instead.
|
|
139
|
+
*/
|
|
140
|
+
edgeType?: "default" | "smoothstep" | "step" | "straight" | "waypoints"
|
|
128
141
|
/** Rename legend rows to match what this graph's edges actually mean. */
|
|
129
142
|
legendLabels?: Partial<
|
|
130
143
|
Record<"network" | "structural" | "pending" | "drift", string>
|
|
@@ -185,6 +198,9 @@ const nodeTypes: NodeTypesObject = {
|
|
|
185
198
|
service: markRaw(LpServiceNode) as Component,
|
|
186
199
|
lane: markRaw(LpLaneNode) as Component,
|
|
187
200
|
}
|
|
201
|
+
// `waypoints` curves through the points an edge carries, for layouts that know
|
|
202
|
+
// where the gaps are; with none it falls back to the plain bezier.
|
|
203
|
+
const edgeTypes = { waypoints: markRaw(LpWaypointEdge) as Component }
|
|
188
204
|
|
|
189
205
|
// Lanes render as non-interactive Vue Flow nodes BENEATH the graph: prepended
|
|
190
206
|
// so they paint first, with selecting/dragging/connecting off and a low z so
|
|
@@ -268,7 +284,8 @@ const flowEdges = computed(() =>
|
|
|
268
284
|
id: e.id,
|
|
269
285
|
source: e.source,
|
|
270
286
|
target: e.target,
|
|
271
|
-
type: "default",
|
|
287
|
+
type: props.edgeType ?? "default",
|
|
288
|
+
data: { waypoints: e.waypoints },
|
|
272
289
|
animated: obs !== "applied" && !e.dimmed,
|
|
273
290
|
label: e.kind,
|
|
274
291
|
labelBgStyle: { fill: "var(--color-surface)" },
|
|
@@ -375,6 +392,7 @@ defineExpose({ fitView, setViewport: applyViewport })
|
|
|
375
392
|
:nodes="flowNodes"
|
|
376
393
|
:edges="flowEdges"
|
|
377
394
|
:node-types="nodeTypes"
|
|
395
|
+
:edge-types="edgeTypes"
|
|
378
396
|
:nodes-connectable="connectable"
|
|
379
397
|
:selection-on-drag="selectable"
|
|
380
398
|
:pan-on-drag="selectable ? [1, 2] : true"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* An edge that curves THROUGH a list of waypoints.
|
|
4
|
+
*
|
|
5
|
+
* The built-in shapes each fail one way in a layered graph: a bezier bulges off
|
|
6
|
+
* the line between its ends and cuts through whatever stands between the
|
|
7
|
+
* columns, and orthogonal routing clears the cards but draws the graph as a
|
|
8
|
+
* grid of right angles. Given the gaps a layout already knows about, a curve
|
|
9
|
+
* threaded through them is both — clear of the cards and still a curve.
|
|
10
|
+
*
|
|
11
|
+
* Waypoints ride on the edge's `data.waypoints`; with none, this is a plain
|
|
12
|
+
* bezier, so the type is safe to use for every edge in a graph.
|
|
13
|
+
*/
|
|
14
|
+
import { BaseEdge, getBezierPath, Position } from "@vue-flow/core"
|
|
15
|
+
import { computed } from "vue"
|
|
16
|
+
|
|
17
|
+
const props = defineProps<{
|
|
18
|
+
id: string
|
|
19
|
+
sourceX: number
|
|
20
|
+
sourceY: number
|
|
21
|
+
targetX: number
|
|
22
|
+
targetY: number
|
|
23
|
+
sourcePosition?: Position
|
|
24
|
+
targetPosition?: Position
|
|
25
|
+
data?: { waypoints?: { x: number; y: number }[] }
|
|
26
|
+
markerEnd?: string
|
|
27
|
+
style?: Record<string, unknown>
|
|
28
|
+
}>()
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* Catmull-Rom through the points, converted to cubic beziers — the standard way
|
|
32
|
+
* to get a curve that actually passes through its control points rather than
|
|
33
|
+
* being pulled towards them. Tension 0.5 keeps it taut enough not to loop back
|
|
34
|
+
* on itself between closely spaced waypoints.
|
|
35
|
+
*/
|
|
36
|
+
function splineThrough(points: { x: number; y: number }[]): string {
|
|
37
|
+
if (points.length < 2) return ""
|
|
38
|
+
const p = [points[0]!, ...points, points[points.length - 1]!]
|
|
39
|
+
let d = `M${points[0]!.x},${points[0]!.y}`
|
|
40
|
+
for (let i = 1; i < p.length - 2; i++) {
|
|
41
|
+
const p0 = p[i - 1]!
|
|
42
|
+
const p1 = p[i]!
|
|
43
|
+
const p2 = p[i + 1]!
|
|
44
|
+
const p3 = p[i + 2]!
|
|
45
|
+
const c1x = p1.x + (p2.x - p0.x) / 6
|
|
46
|
+
const c1y = p1.y + (p2.y - p0.y) / 6
|
|
47
|
+
const c2x = p2.x - (p3.x - p1.x) / 6
|
|
48
|
+
const c2y = p2.y - (p3.y - p1.y) / 6
|
|
49
|
+
d += ` C${c1x},${c1y} ${c2x},${c2y} ${p2.x},${p2.y}`
|
|
50
|
+
}
|
|
51
|
+
return d
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const path = computed(() => {
|
|
55
|
+
const via = props.data?.waypoints ?? []
|
|
56
|
+
if (!via.length) {
|
|
57
|
+
const [d] = getBezierPath({
|
|
58
|
+
sourceX: props.sourceX,
|
|
59
|
+
sourceY: props.sourceY,
|
|
60
|
+
targetX: props.targetX,
|
|
61
|
+
targetY: props.targetY,
|
|
62
|
+
sourcePosition: props.sourcePosition ?? Position.Right,
|
|
63
|
+
targetPosition: props.targetPosition ?? Position.Left,
|
|
64
|
+
})
|
|
65
|
+
return d
|
|
66
|
+
}
|
|
67
|
+
return splineThrough([
|
|
68
|
+
{ x: props.sourceX, y: props.sourceY },
|
|
69
|
+
...via,
|
|
70
|
+
{ x: props.targetX, y: props.targetY },
|
|
71
|
+
])
|
|
72
|
+
})
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<template>
|
|
76
|
+
<BaseEdge :id="id" :path="path" :marker-end="markerEnd" :style="style" />
|
|
77
|
+
</template>
|