polly-graph 0.1.2 → 0.1.3
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/index.cjs +141 -0
- package/dist/index.css +47 -0
- package/dist/index.d.cts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +141 -0
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -3809,6 +3809,138 @@ function createGraphSimulation(config) {
|
|
|
3809
3809
|
return { simulation };
|
|
3810
3810
|
}
|
|
3811
3811
|
|
|
3812
|
+
// src/controls/graph-controls.utils.ts
|
|
3813
|
+
function resolveControlsPosition(position) {
|
|
3814
|
+
return position ?? "bottom-left";
|
|
3815
|
+
}
|
|
3816
|
+
function resolveControlsOrientation(orientation) {
|
|
3817
|
+
return orientation ?? "vertical";
|
|
3818
|
+
}
|
|
3819
|
+
function shouldRenderControl(config, key) {
|
|
3820
|
+
const show = config.show;
|
|
3821
|
+
if (!show) {
|
|
3822
|
+
return true;
|
|
3823
|
+
}
|
|
3824
|
+
const value = show[key];
|
|
3825
|
+
if (value === void 0) {
|
|
3826
|
+
return true;
|
|
3827
|
+
}
|
|
3828
|
+
return value;
|
|
3829
|
+
}
|
|
3830
|
+
|
|
3831
|
+
// src/assets/plus.svg?raw
|
|
3832
|
+
var plus_default = '<svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n>\n <path d="M5 12h14m-7-7v14" />\n</svg>';
|
|
3833
|
+
|
|
3834
|
+
// src/assets/minus.svg?raw
|
|
3835
|
+
var minus_default = '<svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n>\n <path d="M19 12H5" />\n</svg>';
|
|
3836
|
+
|
|
3837
|
+
// src/assets/fit.svg?raw
|
|
3838
|
+
var fit_default = '<svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n>\n <path d="M5 9V5H9" />\n <path d="M19 9V5H15" />\n <path d="M5 15V19H9" />\n <path d="M19 15V19H15" />\n</svg>';
|
|
3839
|
+
|
|
3840
|
+
// src/assets/reset.svg?raw
|
|
3841
|
+
var reset_default = '<svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n>\n <path d="M20 12a8 8 0 1 1-2.3-5.7" />\n <path d="M20 4.5v4h-4" />\n</svg>';
|
|
3842
|
+
|
|
3843
|
+
// src/controls/graph-controls.icons.ts
|
|
3844
|
+
var ICON_MAP = {
|
|
3845
|
+
"zoom-in": plus_default,
|
|
3846
|
+
"zoom-out": minus_default,
|
|
3847
|
+
fit: fit_default,
|
|
3848
|
+
reset: reset_default
|
|
3849
|
+
};
|
|
3850
|
+
function getControlIcon(icon) {
|
|
3851
|
+
const raw = ICON_MAP[icon];
|
|
3852
|
+
if (!raw) {
|
|
3853
|
+
throw new Error(`Icon not found: ${icon}`);
|
|
3854
|
+
}
|
|
3855
|
+
return raw.replace("<svg", '<svg class="pg-icon"');
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3858
|
+
// src/controls/create-graph-controls.ts
|
|
3859
|
+
function createGraphControls(container, graph, config) {
|
|
3860
|
+
let root2 = null;
|
|
3861
|
+
function mount() {
|
|
3862
|
+
if (!config.enabled) {
|
|
3863
|
+
return;
|
|
3864
|
+
}
|
|
3865
|
+
const parent = container.parentElement;
|
|
3866
|
+
if (!parent) {
|
|
3867
|
+
return;
|
|
3868
|
+
}
|
|
3869
|
+
root2 = document.createElement("div");
|
|
3870
|
+
root2.className = "pg-controls";
|
|
3871
|
+
applyPosition(root2, config);
|
|
3872
|
+
applyOrientation(root2, config);
|
|
3873
|
+
appendControls(root2, config, graph);
|
|
3874
|
+
parent.appendChild(root2);
|
|
3875
|
+
}
|
|
3876
|
+
function appendControls(root3, config2, graph2) {
|
|
3877
|
+
if (shouldRenderControl(config2, "zoomIn")) {
|
|
3878
|
+
root3.appendChild(createButton("zoom-in", "Zoom in", graph2.zoomIn.bind(graph2)));
|
|
3879
|
+
}
|
|
3880
|
+
if (shouldRenderControl(config2, "zoomOut")) {
|
|
3881
|
+
root3.appendChild(createButton("zoom-out", "Zoom out", graph2.zoomOut.bind(graph2)));
|
|
3882
|
+
}
|
|
3883
|
+
if (shouldRenderControl(config2, "fit")) {
|
|
3884
|
+
root3.appendChild(createButton("fit", "Fit view", graph2.fitView.bind(graph2)));
|
|
3885
|
+
}
|
|
3886
|
+
if (shouldRenderControl(config2, "reset")) {
|
|
3887
|
+
root3.appendChild(createButton("reset", "Reset view", graph2.resetView.bind(graph2)));
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
function createButton(type, label, onClick) {
|
|
3891
|
+
const button = document.createElement("button");
|
|
3892
|
+
button.type = "button";
|
|
3893
|
+
button.setAttribute("aria-label", label);
|
|
3894
|
+
const wrapper = document.createElement("div");
|
|
3895
|
+
wrapper.innerHTML = getControlIcon(type);
|
|
3896
|
+
const svg = wrapper.querySelector("svg");
|
|
3897
|
+
if (!svg) {
|
|
3898
|
+
throw new Error(`Invalid SVG for icon: ${type}`);
|
|
3899
|
+
}
|
|
3900
|
+
svg.classList.add("pg-icon");
|
|
3901
|
+
button.appendChild(svg);
|
|
3902
|
+
button.addEventListener("click", onClick);
|
|
3903
|
+
return button;
|
|
3904
|
+
}
|
|
3905
|
+
function destroy() {
|
|
3906
|
+
if (!root2) {
|
|
3907
|
+
return;
|
|
3908
|
+
}
|
|
3909
|
+
const clone = root2.cloneNode(true);
|
|
3910
|
+
root2.replaceWith(clone);
|
|
3911
|
+
root2 = null;
|
|
3912
|
+
}
|
|
3913
|
+
return { mount, destroy };
|
|
3914
|
+
}
|
|
3915
|
+
function applyPosition(el, config) {
|
|
3916
|
+
const position = resolveControlsPosition(config.position);
|
|
3917
|
+
const offset = config.offset ?? { x: 16, y: 16 };
|
|
3918
|
+
el.style.position = "absolute";
|
|
3919
|
+
switch (position) {
|
|
3920
|
+
case "bottom-left":
|
|
3921
|
+
el.style.left = `${offset.x}px`;
|
|
3922
|
+
el.style.bottom = `${offset.y}px`;
|
|
3923
|
+
break;
|
|
3924
|
+
case "bottom-right":
|
|
3925
|
+
el.style.right = `${offset.x}px`;
|
|
3926
|
+
el.style.bottom = `${offset.y}px`;
|
|
3927
|
+
break;
|
|
3928
|
+
case "top-left":
|
|
3929
|
+
el.style.left = `${offset.x}px`;
|
|
3930
|
+
el.style.top = `${offset.y}px`;
|
|
3931
|
+
break;
|
|
3932
|
+
case "top-right":
|
|
3933
|
+
el.style.right = `${offset.x}px`;
|
|
3934
|
+
el.style.top = `${offset.y}px`;
|
|
3935
|
+
break;
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
function applyOrientation(el, config) {
|
|
3939
|
+
const orientation = resolveControlsOrientation(config.orientation);
|
|
3940
|
+
el.style.display = "flex";
|
|
3941
|
+
el.style.flexDirection = orientation === "vertical" ? "column" : "row";
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3812
3944
|
// src/utils/resolve-link-style.ts
|
|
3813
3945
|
var DEFAULT_LINK_STYLE = {
|
|
3814
3946
|
stroke: "#94a3b8",
|
|
@@ -4365,6 +4497,7 @@ function createGraph(config) {
|
|
|
4365
4497
|
let cleanupResize = null;
|
|
4366
4498
|
let cleanupZoom = null;
|
|
4367
4499
|
let tooltipBinding = null;
|
|
4500
|
+
let controls = null;
|
|
4368
4501
|
let dimensions = { width: 0, height: 0 };
|
|
4369
4502
|
let rootGroup = null;
|
|
4370
4503
|
let zoomBehavior = null;
|
|
@@ -4464,6 +4597,10 @@ function createGraph(config) {
|
|
|
4464
4597
|
}
|
|
4465
4598
|
if (config.interaction?.selection?.enabled) {
|
|
4466
4599
|
}
|
|
4600
|
+
if (config.controls?.enabled) {
|
|
4601
|
+
controls = createGraphControls(config.container, { zoomIn, zoomOut, resetView, fitView, destroy, render }, config.controls);
|
|
4602
|
+
controls.mount();
|
|
4603
|
+
}
|
|
4467
4604
|
}
|
|
4468
4605
|
function resetView() {
|
|
4469
4606
|
if (!zoomBehavior) {
|
|
@@ -4534,6 +4671,10 @@ function createGraph(config) {
|
|
|
4534
4671
|
simulation.stop();
|
|
4535
4672
|
simulation = null;
|
|
4536
4673
|
}
|
|
4674
|
+
if (controls) {
|
|
4675
|
+
controls.destroy();
|
|
4676
|
+
controls = null;
|
|
4677
|
+
}
|
|
4537
4678
|
rootGroup = null;
|
|
4538
4679
|
zoomBehavior = null;
|
|
4539
4680
|
while (config.container.firstChild) {
|
package/dist/index.css
CHANGED
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
color: #f8fafc;
|
|
11
11
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
12
12
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.22);
|
|
13
|
+
font-family:
|
|
14
|
+
"Inter",
|
|
15
|
+
-apple-system,
|
|
16
|
+
BlinkMacSystemFont,
|
|
17
|
+
"Segoe UI",
|
|
18
|
+
sans-serif;
|
|
13
19
|
font-size: 12px;
|
|
14
20
|
line-height: 1.5;
|
|
15
21
|
opacity: 0;
|
|
@@ -72,5 +78,46 @@
|
|
|
72
78
|
margin-top: 4px;
|
|
73
79
|
font-size: 14px;
|
|
74
80
|
font-weight: 600;
|
|
81
|
+
line-height: 1.4;
|
|
75
82
|
color: #ffffff;
|
|
76
83
|
}
|
|
84
|
+
|
|
85
|
+
/* src/styles/graph-controls.css */
|
|
86
|
+
.pg-controls {
|
|
87
|
+
background: #ffffff;
|
|
88
|
+
border-radius: 12px;
|
|
89
|
+
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.12), 0 6px 14px rgba(0, 0, 0, 0.06);
|
|
90
|
+
display: flex;
|
|
91
|
+
flex-direction: column;
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
position: absolute;
|
|
94
|
+
z-index: 10;
|
|
95
|
+
}
|
|
96
|
+
.pg-controls button {
|
|
97
|
+
all: unset;
|
|
98
|
+
align-items: center;
|
|
99
|
+
background: transparent;
|
|
100
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
display: flex;
|
|
103
|
+
justify-content: center;
|
|
104
|
+
transition: background 120ms ease, transform 80ms ease;
|
|
105
|
+
height: 44px;
|
|
106
|
+
width: 44px;
|
|
107
|
+
}
|
|
108
|
+
.pg-controls button:last-child {
|
|
109
|
+
border-bottom: none;
|
|
110
|
+
}
|
|
111
|
+
.pg-controls button:hover {
|
|
112
|
+
background: #f9fafb;
|
|
113
|
+
}
|
|
114
|
+
.pg-controls button:active {
|
|
115
|
+
background: #f3f4f6;
|
|
116
|
+
}
|
|
117
|
+
.pg-controls button svg.pg-icon {
|
|
118
|
+
display: block;
|
|
119
|
+
fill: none;
|
|
120
|
+
height: 18px;
|
|
121
|
+
stroke: currentColor;
|
|
122
|
+
width: 18px;
|
|
123
|
+
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import { SimulationNodeDatum, SimulationLinkDatum } from 'd3-force';
|
|
2
2
|
|
|
3
|
+
interface Coordinates {
|
|
4
|
+
readonly x: number;
|
|
5
|
+
readonly y: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type GraphControlsPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
9
|
+
type GraphControlsOrientation = 'vertical' | 'horizontal';
|
|
10
|
+
interface GraphControlsConfig {
|
|
11
|
+
readonly enabled: boolean;
|
|
12
|
+
readonly position?: GraphControlsPosition;
|
|
13
|
+
readonly orientation?: GraphControlsOrientation;
|
|
14
|
+
readonly offset?: Coordinates;
|
|
15
|
+
readonly show?: {
|
|
16
|
+
readonly zoomIn?: boolean;
|
|
17
|
+
readonly zoomOut?: boolean;
|
|
18
|
+
readonly reset?: boolean;
|
|
19
|
+
readonly fit?: boolean;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
3
23
|
interface GraphNode extends SimulationNodeDatum {
|
|
4
24
|
readonly id: string;
|
|
5
25
|
readonly type: string;
|
|
@@ -81,6 +101,7 @@ interface GraphConfig {
|
|
|
81
101
|
readonly nodes: GraphNode[];
|
|
82
102
|
readonly links: GraphLink[];
|
|
83
103
|
readonly interaction?: GraphInteractionConfig;
|
|
104
|
+
readonly controls?: GraphControlsConfig;
|
|
84
105
|
}
|
|
85
106
|
|
|
86
107
|
interface GraphInstance {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import { SimulationNodeDatum, SimulationLinkDatum } from 'd3-force';
|
|
2
2
|
|
|
3
|
+
interface Coordinates {
|
|
4
|
+
readonly x: number;
|
|
5
|
+
readonly y: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type GraphControlsPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
9
|
+
type GraphControlsOrientation = 'vertical' | 'horizontal';
|
|
10
|
+
interface GraphControlsConfig {
|
|
11
|
+
readonly enabled: boolean;
|
|
12
|
+
readonly position?: GraphControlsPosition;
|
|
13
|
+
readonly orientation?: GraphControlsOrientation;
|
|
14
|
+
readonly offset?: Coordinates;
|
|
15
|
+
readonly show?: {
|
|
16
|
+
readonly zoomIn?: boolean;
|
|
17
|
+
readonly zoomOut?: boolean;
|
|
18
|
+
readonly reset?: boolean;
|
|
19
|
+
readonly fit?: boolean;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
3
23
|
interface GraphNode extends SimulationNodeDatum {
|
|
4
24
|
readonly id: string;
|
|
5
25
|
readonly type: string;
|
|
@@ -81,6 +101,7 @@ interface GraphConfig {
|
|
|
81
101
|
readonly nodes: GraphNode[];
|
|
82
102
|
readonly links: GraphLink[];
|
|
83
103
|
readonly interaction?: GraphInteractionConfig;
|
|
104
|
+
readonly controls?: GraphControlsConfig;
|
|
84
105
|
}
|
|
85
106
|
|
|
86
107
|
interface GraphInstance {
|
package/dist/index.js
CHANGED
|
@@ -3783,6 +3783,138 @@ function createGraphSimulation(config) {
|
|
|
3783
3783
|
return { simulation };
|
|
3784
3784
|
}
|
|
3785
3785
|
|
|
3786
|
+
// src/controls/graph-controls.utils.ts
|
|
3787
|
+
function resolveControlsPosition(position) {
|
|
3788
|
+
return position ?? "bottom-left";
|
|
3789
|
+
}
|
|
3790
|
+
function resolveControlsOrientation(orientation) {
|
|
3791
|
+
return orientation ?? "vertical";
|
|
3792
|
+
}
|
|
3793
|
+
function shouldRenderControl(config, key) {
|
|
3794
|
+
const show = config.show;
|
|
3795
|
+
if (!show) {
|
|
3796
|
+
return true;
|
|
3797
|
+
}
|
|
3798
|
+
const value = show[key];
|
|
3799
|
+
if (value === void 0) {
|
|
3800
|
+
return true;
|
|
3801
|
+
}
|
|
3802
|
+
return value;
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3805
|
+
// src/assets/plus.svg?raw
|
|
3806
|
+
var plus_default = '<svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n>\n <path d="M5 12h14m-7-7v14" />\n</svg>';
|
|
3807
|
+
|
|
3808
|
+
// src/assets/minus.svg?raw
|
|
3809
|
+
var minus_default = '<svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n>\n <path d="M19 12H5" />\n</svg>';
|
|
3810
|
+
|
|
3811
|
+
// src/assets/fit.svg?raw
|
|
3812
|
+
var fit_default = '<svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n>\n <path d="M5 9V5H9" />\n <path d="M19 9V5H15" />\n <path d="M5 15V19H9" />\n <path d="M19 15V19H15" />\n</svg>';
|
|
3813
|
+
|
|
3814
|
+
// src/assets/reset.svg?raw
|
|
3815
|
+
var reset_default = '<svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n fill="none"\n stroke="currentColor"\n stroke-width="2"\n stroke-linecap="round"\n stroke-linejoin="round"\n>\n <path d="M20 12a8 8 0 1 1-2.3-5.7" />\n <path d="M20 4.5v4h-4" />\n</svg>';
|
|
3816
|
+
|
|
3817
|
+
// src/controls/graph-controls.icons.ts
|
|
3818
|
+
var ICON_MAP = {
|
|
3819
|
+
"zoom-in": plus_default,
|
|
3820
|
+
"zoom-out": minus_default,
|
|
3821
|
+
fit: fit_default,
|
|
3822
|
+
reset: reset_default
|
|
3823
|
+
};
|
|
3824
|
+
function getControlIcon(icon) {
|
|
3825
|
+
const raw = ICON_MAP[icon];
|
|
3826
|
+
if (!raw) {
|
|
3827
|
+
throw new Error(`Icon not found: ${icon}`);
|
|
3828
|
+
}
|
|
3829
|
+
return raw.replace("<svg", '<svg class="pg-icon"');
|
|
3830
|
+
}
|
|
3831
|
+
|
|
3832
|
+
// src/controls/create-graph-controls.ts
|
|
3833
|
+
function createGraphControls(container, graph, config) {
|
|
3834
|
+
let root2 = null;
|
|
3835
|
+
function mount() {
|
|
3836
|
+
if (!config.enabled) {
|
|
3837
|
+
return;
|
|
3838
|
+
}
|
|
3839
|
+
const parent = container.parentElement;
|
|
3840
|
+
if (!parent) {
|
|
3841
|
+
return;
|
|
3842
|
+
}
|
|
3843
|
+
root2 = document.createElement("div");
|
|
3844
|
+
root2.className = "pg-controls";
|
|
3845
|
+
applyPosition(root2, config);
|
|
3846
|
+
applyOrientation(root2, config);
|
|
3847
|
+
appendControls(root2, config, graph);
|
|
3848
|
+
parent.appendChild(root2);
|
|
3849
|
+
}
|
|
3850
|
+
function appendControls(root3, config2, graph2) {
|
|
3851
|
+
if (shouldRenderControl(config2, "zoomIn")) {
|
|
3852
|
+
root3.appendChild(createButton("zoom-in", "Zoom in", graph2.zoomIn.bind(graph2)));
|
|
3853
|
+
}
|
|
3854
|
+
if (shouldRenderControl(config2, "zoomOut")) {
|
|
3855
|
+
root3.appendChild(createButton("zoom-out", "Zoom out", graph2.zoomOut.bind(graph2)));
|
|
3856
|
+
}
|
|
3857
|
+
if (shouldRenderControl(config2, "fit")) {
|
|
3858
|
+
root3.appendChild(createButton("fit", "Fit view", graph2.fitView.bind(graph2)));
|
|
3859
|
+
}
|
|
3860
|
+
if (shouldRenderControl(config2, "reset")) {
|
|
3861
|
+
root3.appendChild(createButton("reset", "Reset view", graph2.resetView.bind(graph2)));
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
function createButton(type, label, onClick) {
|
|
3865
|
+
const button = document.createElement("button");
|
|
3866
|
+
button.type = "button";
|
|
3867
|
+
button.setAttribute("aria-label", label);
|
|
3868
|
+
const wrapper = document.createElement("div");
|
|
3869
|
+
wrapper.innerHTML = getControlIcon(type);
|
|
3870
|
+
const svg = wrapper.querySelector("svg");
|
|
3871
|
+
if (!svg) {
|
|
3872
|
+
throw new Error(`Invalid SVG for icon: ${type}`);
|
|
3873
|
+
}
|
|
3874
|
+
svg.classList.add("pg-icon");
|
|
3875
|
+
button.appendChild(svg);
|
|
3876
|
+
button.addEventListener("click", onClick);
|
|
3877
|
+
return button;
|
|
3878
|
+
}
|
|
3879
|
+
function destroy() {
|
|
3880
|
+
if (!root2) {
|
|
3881
|
+
return;
|
|
3882
|
+
}
|
|
3883
|
+
const clone = root2.cloneNode(true);
|
|
3884
|
+
root2.replaceWith(clone);
|
|
3885
|
+
root2 = null;
|
|
3886
|
+
}
|
|
3887
|
+
return { mount, destroy };
|
|
3888
|
+
}
|
|
3889
|
+
function applyPosition(el, config) {
|
|
3890
|
+
const position = resolveControlsPosition(config.position);
|
|
3891
|
+
const offset = config.offset ?? { x: 16, y: 16 };
|
|
3892
|
+
el.style.position = "absolute";
|
|
3893
|
+
switch (position) {
|
|
3894
|
+
case "bottom-left":
|
|
3895
|
+
el.style.left = `${offset.x}px`;
|
|
3896
|
+
el.style.bottom = `${offset.y}px`;
|
|
3897
|
+
break;
|
|
3898
|
+
case "bottom-right":
|
|
3899
|
+
el.style.right = `${offset.x}px`;
|
|
3900
|
+
el.style.bottom = `${offset.y}px`;
|
|
3901
|
+
break;
|
|
3902
|
+
case "top-left":
|
|
3903
|
+
el.style.left = `${offset.x}px`;
|
|
3904
|
+
el.style.top = `${offset.y}px`;
|
|
3905
|
+
break;
|
|
3906
|
+
case "top-right":
|
|
3907
|
+
el.style.right = `${offset.x}px`;
|
|
3908
|
+
el.style.top = `${offset.y}px`;
|
|
3909
|
+
break;
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
function applyOrientation(el, config) {
|
|
3913
|
+
const orientation = resolveControlsOrientation(config.orientation);
|
|
3914
|
+
el.style.display = "flex";
|
|
3915
|
+
el.style.flexDirection = orientation === "vertical" ? "column" : "row";
|
|
3916
|
+
}
|
|
3917
|
+
|
|
3786
3918
|
// src/utils/resolve-link-style.ts
|
|
3787
3919
|
var DEFAULT_LINK_STYLE = {
|
|
3788
3920
|
stroke: "#94a3b8",
|
|
@@ -4339,6 +4471,7 @@ function createGraph(config) {
|
|
|
4339
4471
|
let cleanupResize = null;
|
|
4340
4472
|
let cleanupZoom = null;
|
|
4341
4473
|
let tooltipBinding = null;
|
|
4474
|
+
let controls = null;
|
|
4342
4475
|
let dimensions = { width: 0, height: 0 };
|
|
4343
4476
|
let rootGroup = null;
|
|
4344
4477
|
let zoomBehavior = null;
|
|
@@ -4438,6 +4571,10 @@ function createGraph(config) {
|
|
|
4438
4571
|
}
|
|
4439
4572
|
if (config.interaction?.selection?.enabled) {
|
|
4440
4573
|
}
|
|
4574
|
+
if (config.controls?.enabled) {
|
|
4575
|
+
controls = createGraphControls(config.container, { zoomIn, zoomOut, resetView, fitView, destroy, render }, config.controls);
|
|
4576
|
+
controls.mount();
|
|
4577
|
+
}
|
|
4441
4578
|
}
|
|
4442
4579
|
function resetView() {
|
|
4443
4580
|
if (!zoomBehavior) {
|
|
@@ -4508,6 +4645,10 @@ function createGraph(config) {
|
|
|
4508
4645
|
simulation.stop();
|
|
4509
4646
|
simulation = null;
|
|
4510
4647
|
}
|
|
4648
|
+
if (controls) {
|
|
4649
|
+
controls.destroy();
|
|
4650
|
+
controls = null;
|
|
4651
|
+
}
|
|
4511
4652
|
rootGroup = null;
|
|
4512
4653
|
zoomBehavior = null;
|
|
4513
4654
|
while (config.container.firstChild) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polly-graph",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Reusable D3-based graph visualization SDK with configurable nodes, links, labels, interactions, and layout behaviors.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Badal",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"clean": "rm -rf dist",
|
|
50
|
-
"build": "tsup
|
|
51
|
-
"dev": "tsup
|
|
50
|
+
"build": "tsup",
|
|
51
|
+
"dev": "tsup",
|
|
52
52
|
"lint": "eslint \"src/**/*.ts\"",
|
|
53
53
|
"typecheck": "tsc --noEmit",
|
|
54
54
|
"test": "vitest run --passWithNoTests",
|