backpack-viewer 0.2.16 → 0.2.19
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 +73 -1
- package/bin/serve.js +155 -0
- package/dist/api.d.ts +27 -0
- package/dist/api.js +71 -0
- package/dist/app/assets/index-CTM-vKgB.js +21 -0
- package/dist/app/assets/index-CjzMJjZ-.css +1 -0
- package/dist/app/index.html +2 -2
- package/dist/canvas.d.ts +22 -1
- package/dist/canvas.js +143 -65
- package/dist/config.d.ts +4 -0
- package/dist/config.js +32 -0
- package/dist/default-config.json +66 -0
- package/dist/dialog.d.ts +9 -0
- package/dist/dialog.js +119 -0
- package/dist/info-panel.d.ts +4 -0
- package/dist/info-panel.js +66 -11
- package/dist/keybindings.d.ts +6 -0
- package/dist/keybindings.js +67 -0
- package/dist/layout.d.ts +2 -0
- package/dist/layout.js +18 -8
- package/dist/main.js +175 -42
- package/dist/search.d.ts +5 -1
- package/dist/search.js +46 -85
- package/dist/shortcuts.d.ts +3 -1
- package/dist/shortcuts.js +51 -19
- package/dist/sidebar.d.ts +8 -0
- package/dist/sidebar.js +106 -1
- package/dist/style.css +328 -6
- package/dist/tools-pane.d.ts +10 -0
- package/dist/tools-pane.js +407 -148
- package/package.json +1 -1
- package/dist/app/assets/index-Mi0vDG5K.js +0 -21
- package/dist/app/assets/index-z15vEFEy.css +0 -1
package/dist/sidebar.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { showConfirm, showPrompt } from "./dialog";
|
|
1
2
|
export function initSidebar(container, onSelectOrCallbacks) {
|
|
2
3
|
const cbs = typeof onSelectOrCallbacks === "function"
|
|
3
4
|
? { onSelect: onSelectOrCallbacks }
|
|
@@ -16,12 +17,31 @@ export function initSidebar(container, onSelectOrCallbacks) {
|
|
|
16
17
|
footer.innerHTML =
|
|
17
18
|
'<a href="mailto:support@backpackontology.com">support@backpackontology.com</a>' +
|
|
18
19
|
"<span>Feedback & support</span>";
|
|
19
|
-
|
|
20
|
+
// Collapse toggle button
|
|
21
|
+
const collapseBtn = document.createElement("button");
|
|
22
|
+
collapseBtn.className = "sidebar-collapse-btn";
|
|
23
|
+
collapseBtn.title = "Toggle sidebar (Tab)";
|
|
24
|
+
collapseBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="11 17 6 12 11 7"/><polyline points="18 17 13 12 18 7"/></svg>';
|
|
25
|
+
let collapsed = false;
|
|
26
|
+
function toggleSidebar() {
|
|
27
|
+
collapsed = !collapsed;
|
|
28
|
+
container.classList.toggle("sidebar-collapsed", collapsed);
|
|
29
|
+
collapseBtn.innerHTML = collapsed
|
|
30
|
+
? '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="13 7 18 12 13 17"/><polyline points="6 7 11 12 6 17"/></svg>'
|
|
31
|
+
: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="11 17 6 12 11 7"/><polyline points="18 17 13 12 18 7"/></svg>';
|
|
32
|
+
}
|
|
33
|
+
collapseBtn.addEventListener("click", toggleSidebar);
|
|
34
|
+
const headingRow = document.createElement("div");
|
|
35
|
+
headingRow.className = "sidebar-heading-row";
|
|
36
|
+
headingRow.appendChild(heading);
|
|
37
|
+
headingRow.appendChild(collapseBtn);
|
|
38
|
+
container.appendChild(headingRow);
|
|
20
39
|
container.appendChild(input);
|
|
21
40
|
container.appendChild(list);
|
|
22
41
|
container.appendChild(footer);
|
|
23
42
|
let items = [];
|
|
24
43
|
let activeName = "";
|
|
44
|
+
let activeBranchName = "main";
|
|
25
45
|
// Filter
|
|
26
46
|
input.addEventListener("input", () => {
|
|
27
47
|
const query = input.value.toLowerCase();
|
|
@@ -43,8 +63,12 @@ export function initSidebar(container, onSelectOrCallbacks) {
|
|
|
43
63
|
const statsSpan = document.createElement("span");
|
|
44
64
|
statsSpan.className = "stats";
|
|
45
65
|
statsSpan.textContent = `${s.nodeCount} nodes, ${s.edgeCount} edges`;
|
|
66
|
+
const branchSpan = document.createElement("span");
|
|
67
|
+
branchSpan.className = "sidebar-branch";
|
|
68
|
+
branchSpan.dataset.graph = s.name;
|
|
46
69
|
li.appendChild(nameSpan);
|
|
47
70
|
li.appendChild(statsSpan);
|
|
71
|
+
li.appendChild(branchSpan);
|
|
48
72
|
if (cbs.onRename) {
|
|
49
73
|
const editBtn = document.createElement("button");
|
|
50
74
|
editBtn.className = "sidebar-edit-btn";
|
|
@@ -99,5 +123,86 @@ export function initSidebar(container, onSelectOrCallbacks) {
|
|
|
99
123
|
item.classList.toggle("active", item.dataset.name === name);
|
|
100
124
|
}
|
|
101
125
|
},
|
|
126
|
+
setActiveBranch(graphName, branchName, allBranches) {
|
|
127
|
+
activeBranchName = branchName;
|
|
128
|
+
const spans = list.querySelectorAll(`.sidebar-branch[data-graph="${graphName}"]`);
|
|
129
|
+
for (const span of spans) {
|
|
130
|
+
span.textContent = `/ ${branchName}`;
|
|
131
|
+
span.title = "Click to switch branch";
|
|
132
|
+
span.style.cursor = "pointer";
|
|
133
|
+
// Remove old listener by replacing element
|
|
134
|
+
const fresh = span.cloneNode(true);
|
|
135
|
+
span.replaceWith(fresh);
|
|
136
|
+
fresh.addEventListener("click", (e) => {
|
|
137
|
+
e.stopPropagation();
|
|
138
|
+
showBranchPicker(graphName, fresh, allBranches ?? []);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
toggle: toggleSidebar,
|
|
102
143
|
};
|
|
144
|
+
function showBranchPicker(graphName, anchor, branches) {
|
|
145
|
+
// Remove existing picker
|
|
146
|
+
const old = container.querySelector(".branch-picker");
|
|
147
|
+
if (old)
|
|
148
|
+
old.remove();
|
|
149
|
+
const picker = document.createElement("div");
|
|
150
|
+
picker.className = "branch-picker";
|
|
151
|
+
for (const b of branches) {
|
|
152
|
+
const row = document.createElement("div");
|
|
153
|
+
row.className = "branch-picker-item";
|
|
154
|
+
if (b.active)
|
|
155
|
+
row.classList.add("branch-picker-active");
|
|
156
|
+
const label = document.createElement("span");
|
|
157
|
+
label.textContent = b.name;
|
|
158
|
+
row.appendChild(label);
|
|
159
|
+
if (!b.active && cbs.onBranchDelete) {
|
|
160
|
+
const del = document.createElement("button");
|
|
161
|
+
del.className = "branch-picker-delete";
|
|
162
|
+
del.textContent = "\u00d7";
|
|
163
|
+
del.title = `Delete ${b.name}`;
|
|
164
|
+
del.addEventListener("click", (e) => {
|
|
165
|
+
e.stopPropagation();
|
|
166
|
+
showConfirm("Delete branch", `Delete branch "${b.name}"?`).then((ok) => {
|
|
167
|
+
if (ok) {
|
|
168
|
+
cbs.onBranchDelete(graphName, b.name);
|
|
169
|
+
picker.remove();
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
row.appendChild(del);
|
|
174
|
+
}
|
|
175
|
+
if (!b.active) {
|
|
176
|
+
row.addEventListener("click", () => {
|
|
177
|
+
cbs.onBranchSwitch?.(graphName, b.name);
|
|
178
|
+
picker.remove();
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
picker.appendChild(row);
|
|
182
|
+
}
|
|
183
|
+
// Create new branch row
|
|
184
|
+
if (cbs.onBranchCreate) {
|
|
185
|
+
const createRow = document.createElement("div");
|
|
186
|
+
createRow.className = "branch-picker-item branch-picker-create";
|
|
187
|
+
createRow.textContent = "+ New branch";
|
|
188
|
+
createRow.addEventListener("click", () => {
|
|
189
|
+
showPrompt("New branch", "Branch name").then((name) => {
|
|
190
|
+
if (name) {
|
|
191
|
+
cbs.onBranchCreate(graphName, name);
|
|
192
|
+
picker.remove();
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
picker.appendChild(createRow);
|
|
197
|
+
}
|
|
198
|
+
anchor.after(picker);
|
|
199
|
+
// Close on outside click
|
|
200
|
+
const close = (e) => {
|
|
201
|
+
if (!picker.contains(e.target)) {
|
|
202
|
+
picker.remove();
|
|
203
|
+
document.removeEventListener("click", close);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
setTimeout(() => document.addEventListener("click", close), 0);
|
|
207
|
+
}
|
|
103
208
|
}
|
package/dist/style.css
CHANGED
|
@@ -114,6 +114,41 @@ body {
|
|
|
114
114
|
overflow-y: auto;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
#sidebar.sidebar-collapsed {
|
|
118
|
+
width: 0;
|
|
119
|
+
min-width: 0;
|
|
120
|
+
padding: 0;
|
|
121
|
+
overflow: hidden;
|
|
122
|
+
border-right: none;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.sidebar-heading-row {
|
|
126
|
+
display: flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
justify-content: space-between;
|
|
129
|
+
margin-bottom: 14px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.sidebar-heading-row h2 {
|
|
133
|
+
margin-bottom: 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.sidebar-collapse-btn {
|
|
137
|
+
background: none;
|
|
138
|
+
border: 1px solid var(--border);
|
|
139
|
+
border-radius: 6px;
|
|
140
|
+
color: var(--text-dim);
|
|
141
|
+
cursor: pointer;
|
|
142
|
+
padding: 4px 6px;
|
|
143
|
+
line-height: 1;
|
|
144
|
+
transition: color 0.15s, border-color 0.15s;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.sidebar-collapse-btn:hover {
|
|
148
|
+
color: var(--text);
|
|
149
|
+
border-color: var(--text-muted);
|
|
150
|
+
}
|
|
151
|
+
|
|
117
152
|
#sidebar h2 {
|
|
118
153
|
font-size: 13px;
|
|
119
154
|
font-weight: 600;
|
|
@@ -218,6 +253,74 @@ body {
|
|
|
218
253
|
padding: 0;
|
|
219
254
|
}
|
|
220
255
|
|
|
256
|
+
.sidebar-branch {
|
|
257
|
+
font-size: 10px;
|
|
258
|
+
color: var(--accent);
|
|
259
|
+
opacity: 0.7;
|
|
260
|
+
display: block;
|
|
261
|
+
margin-top: 2px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.sidebar-branch:hover {
|
|
265
|
+
opacity: 1;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.branch-picker {
|
|
269
|
+
background: var(--bg-surface);
|
|
270
|
+
border: 1px solid var(--border);
|
|
271
|
+
border-radius: 8px;
|
|
272
|
+
padding: 4px;
|
|
273
|
+
margin-top: 4px;
|
|
274
|
+
box-shadow: 0 4px 16px var(--shadow);
|
|
275
|
+
z-index: 50;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.branch-picker-item {
|
|
279
|
+
display: flex;
|
|
280
|
+
align-items: center;
|
|
281
|
+
justify-content: space-between;
|
|
282
|
+
padding: 6px 8px;
|
|
283
|
+
font-size: 12px;
|
|
284
|
+
color: var(--text);
|
|
285
|
+
border-radius: 4px;
|
|
286
|
+
cursor: pointer;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.branch-picker-item:hover {
|
|
290
|
+
background: var(--bg-hover);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.branch-picker-active {
|
|
294
|
+
color: var(--accent);
|
|
295
|
+
font-weight: 600;
|
|
296
|
+
cursor: default;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.branch-picker-active:hover {
|
|
300
|
+
background: none;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.branch-picker-delete {
|
|
304
|
+
background: none;
|
|
305
|
+
border: none;
|
|
306
|
+
color: var(--text-dim);
|
|
307
|
+
cursor: pointer;
|
|
308
|
+
font-size: 14px;
|
|
309
|
+
padding: 0 4px;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.branch-picker-delete:hover {
|
|
313
|
+
color: var(--danger, #e55);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.branch-picker-create {
|
|
317
|
+
color: var(--accent);
|
|
318
|
+
font-size: 11px;
|
|
319
|
+
border-top: 1px solid var(--border);
|
|
320
|
+
margin-top: 4px;
|
|
321
|
+
padding-top: 8px;
|
|
322
|
+
}
|
|
323
|
+
|
|
221
324
|
/* --- Sidebar Footer --- */
|
|
222
325
|
|
|
223
326
|
.sidebar-footer {
|
|
@@ -269,6 +372,11 @@ body {
|
|
|
269
372
|
gap: 4px;
|
|
270
373
|
}
|
|
271
374
|
|
|
375
|
+
.canvas-top-left {
|
|
376
|
+
flex-shrink: 0;
|
|
377
|
+
min-width: var(--tools-width, 264px);
|
|
378
|
+
}
|
|
379
|
+
|
|
272
380
|
.canvas-top-center {
|
|
273
381
|
flex: 1;
|
|
274
382
|
justify-content: center;
|
|
@@ -510,7 +618,8 @@ body {
|
|
|
510
618
|
transition: background 0.1s;
|
|
511
619
|
}
|
|
512
620
|
|
|
513
|
-
.search-result-item:hover
|
|
621
|
+
.search-result-item:hover,
|
|
622
|
+
.search-result-active {
|
|
514
623
|
background: var(--bg-hover);
|
|
515
624
|
}
|
|
516
625
|
|
|
@@ -626,13 +735,15 @@ body {
|
|
|
626
735
|
position: absolute;
|
|
627
736
|
top: 56px;
|
|
628
737
|
right: 16px;
|
|
738
|
+
bottom: 16px;
|
|
629
739
|
width: 360px;
|
|
630
|
-
max-height: calc(100vh - 72px);
|
|
631
740
|
background: var(--bg-surface);
|
|
632
741
|
border: 1px solid var(--border);
|
|
633
742
|
border-radius: 10px;
|
|
634
|
-
overflow
|
|
635
|
-
|
|
743
|
+
overflow: hidden;
|
|
744
|
+
display: flex;
|
|
745
|
+
flex-direction: column;
|
|
746
|
+
padding: 0;
|
|
636
747
|
z-index: 10;
|
|
637
748
|
box-shadow: 0 8px 32px var(--shadow);
|
|
638
749
|
transition: top 0.25s ease, right 0.25s ease, bottom 0.25s ease,
|
|
@@ -640,6 +751,19 @@ body {
|
|
|
640
751
|
border-radius 0.25s ease;
|
|
641
752
|
}
|
|
642
753
|
|
|
754
|
+
.info-panel-header {
|
|
755
|
+
flex-shrink: 0;
|
|
756
|
+
padding: 20px 20px 12px;
|
|
757
|
+
position: relative;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
.info-panel-body {
|
|
761
|
+
flex: 1;
|
|
762
|
+
overflow-y: auto;
|
|
763
|
+
min-height: 0;
|
|
764
|
+
padding: 0 20px 20px;
|
|
765
|
+
}
|
|
766
|
+
|
|
643
767
|
.info-panel.hidden {
|
|
644
768
|
display: none;
|
|
645
769
|
}
|
|
@@ -837,6 +961,11 @@ body {
|
|
|
837
961
|
flex-wrap: wrap;
|
|
838
962
|
}
|
|
839
963
|
|
|
964
|
+
.info-connection-active {
|
|
965
|
+
outline: 1.5px solid var(--accent);
|
|
966
|
+
background: var(--bg-hover);
|
|
967
|
+
}
|
|
968
|
+
|
|
840
969
|
.info-target-dot {
|
|
841
970
|
width: 8px;
|
|
842
971
|
height: 8px;
|
|
@@ -1069,8 +1198,11 @@ body {
|
|
|
1069
1198
|
left: 16px;
|
|
1070
1199
|
bottom: 16px;
|
|
1071
1200
|
z-index: 20;
|
|
1072
|
-
width:
|
|
1073
|
-
|
|
1201
|
+
width: var(--tools-width, 264px);
|
|
1202
|
+
box-sizing: border-box;
|
|
1203
|
+
overflow: hidden;
|
|
1204
|
+
display: flex;
|
|
1205
|
+
flex-direction: column;
|
|
1074
1206
|
background: var(--bg-surface);
|
|
1075
1207
|
border: 1px solid var(--border);
|
|
1076
1208
|
border-radius: 10px;
|
|
@@ -1296,6 +1428,75 @@ body {
|
|
|
1296
1428
|
padding: 8px 0;
|
|
1297
1429
|
}
|
|
1298
1430
|
|
|
1431
|
+
.tools-pane-tabs {
|
|
1432
|
+
display: flex;
|
|
1433
|
+
gap: 2px;
|
|
1434
|
+
margin-bottom: 10px;
|
|
1435
|
+
padding-bottom: 8px;
|
|
1436
|
+
border-bottom: 1px solid var(--border);
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
.tools-pane-tab {
|
|
1440
|
+
flex: 1;
|
|
1441
|
+
padding: 4px 0;
|
|
1442
|
+
font-size: 10px;
|
|
1443
|
+
font-weight: 600;
|
|
1444
|
+
text-transform: uppercase;
|
|
1445
|
+
letter-spacing: 0.03em;
|
|
1446
|
+
background: none;
|
|
1447
|
+
border: 1px solid transparent;
|
|
1448
|
+
border-radius: 5px;
|
|
1449
|
+
color: var(--text-dim);
|
|
1450
|
+
cursor: pointer;
|
|
1451
|
+
transition: color 0.15s, background 0.15s, border-color 0.15s;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
.tools-pane-tab:hover {
|
|
1455
|
+
color: var(--text-muted);
|
|
1456
|
+
background: var(--bg-hover);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
.tools-pane-tab-active {
|
|
1460
|
+
color: var(--text);
|
|
1461
|
+
background: var(--bg-hover);
|
|
1462
|
+
border-color: var(--border);
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
.tools-pane-tab-content {
|
|
1466
|
+
flex: 1;
|
|
1467
|
+
overflow-y: auto;
|
|
1468
|
+
overflow-x: hidden;
|
|
1469
|
+
min-height: 0;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
.tools-pane-search {
|
|
1473
|
+
width: 100%;
|
|
1474
|
+
padding: 4px 8px;
|
|
1475
|
+
font-size: 11px;
|
|
1476
|
+
background: var(--bg);
|
|
1477
|
+
border: 1px solid var(--border);
|
|
1478
|
+
border-radius: 6px;
|
|
1479
|
+
color: var(--text);
|
|
1480
|
+
outline: none;
|
|
1481
|
+
margin-bottom: 8px;
|
|
1482
|
+
box-sizing: border-box;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
.tools-pane-search:focus {
|
|
1486
|
+
border-color: var(--accent);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
.tools-pane-search::placeholder {
|
|
1490
|
+
color: var(--text-dim);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
.tools-pane-empty-msg {
|
|
1494
|
+
font-size: 11px;
|
|
1495
|
+
color: var(--text-dim);
|
|
1496
|
+
text-align: center;
|
|
1497
|
+
padding: 16px 0;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1299
1500
|
/* --- Empty State --- */
|
|
1300
1501
|
|
|
1301
1502
|
.empty-state {
|
|
@@ -1512,3 +1713,124 @@ body {
|
|
|
1512
1713
|
opacity: 0.6;
|
|
1513
1714
|
}
|
|
1514
1715
|
}
|
|
1716
|
+
|
|
1717
|
+
/* --- Dialog System --- */
|
|
1718
|
+
|
|
1719
|
+
.bp-dialog-overlay {
|
|
1720
|
+
position: fixed;
|
|
1721
|
+
inset: 0;
|
|
1722
|
+
background: rgba(0, 0, 0, 0.5);
|
|
1723
|
+
display: flex;
|
|
1724
|
+
align-items: center;
|
|
1725
|
+
justify-content: center;
|
|
1726
|
+
z-index: 1000;
|
|
1727
|
+
backdrop-filter: blur(2px);
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
.bp-dialog {
|
|
1731
|
+
background: var(--bg-surface);
|
|
1732
|
+
border: 1px solid var(--border);
|
|
1733
|
+
border-radius: 12px;
|
|
1734
|
+
padding: 20px;
|
|
1735
|
+
min-width: 280px;
|
|
1736
|
+
max-width: 400px;
|
|
1737
|
+
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.3);
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
.bp-dialog-title {
|
|
1741
|
+
font-size: 14px;
|
|
1742
|
+
font-weight: 600;
|
|
1743
|
+
color: var(--text);
|
|
1744
|
+
margin-bottom: 12px;
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
.bp-dialog-message {
|
|
1748
|
+
font-size: 13px;
|
|
1749
|
+
color: var(--text-muted);
|
|
1750
|
+
margin-bottom: 16px;
|
|
1751
|
+
line-height: 1.5;
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
.bp-dialog-input {
|
|
1755
|
+
width: 100%;
|
|
1756
|
+
padding: 8px 12px;
|
|
1757
|
+
font-size: 13px;
|
|
1758
|
+
background: var(--bg);
|
|
1759
|
+
border: 1px solid var(--border);
|
|
1760
|
+
border-radius: 8px;
|
|
1761
|
+
color: var(--text);
|
|
1762
|
+
outline: none;
|
|
1763
|
+
margin-bottom: 16px;
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
.bp-dialog-input:focus {
|
|
1767
|
+
border-color: var(--accent);
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
.bp-dialog-buttons {
|
|
1771
|
+
display: flex;
|
|
1772
|
+
justify-content: flex-end;
|
|
1773
|
+
gap: 8px;
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
.bp-dialog-btn {
|
|
1777
|
+
padding: 6px 16px;
|
|
1778
|
+
font-size: 12px;
|
|
1779
|
+
border-radius: 6px;
|
|
1780
|
+
border: 1px solid var(--border);
|
|
1781
|
+
background: var(--bg);
|
|
1782
|
+
color: var(--text-muted);
|
|
1783
|
+
cursor: pointer;
|
|
1784
|
+
transition: all 0.15s;
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
.bp-dialog-btn:hover {
|
|
1788
|
+
background: var(--bg-hover);
|
|
1789
|
+
color: var(--text);
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
.bp-dialog-btn-accent {
|
|
1793
|
+
background: var(--accent);
|
|
1794
|
+
color: #fff;
|
|
1795
|
+
border-color: var(--accent);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
.bp-dialog-btn-accent:hover {
|
|
1799
|
+
opacity: 0.9;
|
|
1800
|
+
color: #fff;
|
|
1801
|
+
background: var(--accent);
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
.bp-dialog-btn-danger {
|
|
1805
|
+
background: #e55;
|
|
1806
|
+
color: #fff;
|
|
1807
|
+
border-color: #e55;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
.bp-dialog-btn-danger:hover {
|
|
1811
|
+
opacity: 0.9;
|
|
1812
|
+
color: #fff;
|
|
1813
|
+
background: #e55;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
.bp-toast {
|
|
1817
|
+
position: fixed;
|
|
1818
|
+
bottom: 24px;
|
|
1819
|
+
left: 50%;
|
|
1820
|
+
transform: translateX(-50%) translateY(20px);
|
|
1821
|
+
background: var(--bg-surface);
|
|
1822
|
+
border: 1px solid var(--border);
|
|
1823
|
+
color: var(--text);
|
|
1824
|
+
padding: 8px 20px;
|
|
1825
|
+
border-radius: 8px;
|
|
1826
|
+
font-size: 12px;
|
|
1827
|
+
z-index: 1001;
|
|
1828
|
+
opacity: 0;
|
|
1829
|
+
transition: opacity 0.3s, transform 0.3s;
|
|
1830
|
+
box-shadow: 0 4px 16px var(--shadow);
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
.bp-toast-visible {
|
|
1834
|
+
opacity: 1;
|
|
1835
|
+
transform: translateX(-50%) translateY(0);
|
|
1836
|
+
}
|
package/dist/tools-pane.d.ts
CHANGED
|
@@ -9,7 +9,10 @@ interface ToolsPaneCallbacks {
|
|
|
9
9
|
onToggleTypeHulls: (visible: boolean) => void;
|
|
10
10
|
onToggleMinimap: (visible: boolean) => void;
|
|
11
11
|
onLayoutChange: (param: string, value: number) => void;
|
|
12
|
+
onPanSpeedChange: (speed: number) => void;
|
|
12
13
|
onExport: (format: "png" | "svg") => void;
|
|
14
|
+
onSnapshot?: (label?: string) => void;
|
|
15
|
+
onRollback?: (version: number) => void;
|
|
13
16
|
onOpen?: () => void;
|
|
14
17
|
}
|
|
15
18
|
export declare function initToolsPane(container: HTMLElement, callbacks: ToolsPaneCallbacks): {
|
|
@@ -17,5 +20,12 @@ export declare function initToolsPane(container: HTMLElement, callbacks: ToolsPa
|
|
|
17
20
|
addToFocusSet(nodeIds: string[]): void;
|
|
18
21
|
clearFocusSet(): void;
|
|
19
22
|
setData(newData: LearningGraphData | null): void;
|
|
23
|
+
setSnapshots(list: {
|
|
24
|
+
version: number;
|
|
25
|
+
timestamp: string;
|
|
26
|
+
nodeCount: number;
|
|
27
|
+
edgeCount: number;
|
|
28
|
+
label?: string;
|
|
29
|
+
}[]): void;
|
|
20
30
|
};
|
|
21
31
|
export {};
|