feat: implement draggable sidebar resizer with persistent state and dynamic UI updates
This commit is contained in:
@@ -4,7 +4,7 @@ let simulation;
|
||||
let zoomBehavior;
|
||||
let svgElement;
|
||||
|
||||
let node, link, rootGroup, badge, width, height, currentDotNetHelper;
|
||||
let node, link, rootGroup, badge, width, height, currentDotNetHelper, resizeHandler;
|
||||
|
||||
export function mount(containerId, data, dotNetHelper) {
|
||||
const container = document.getElementById(containerId);
|
||||
@@ -66,6 +66,9 @@ export function mount(containerId, data, dotNetHelper) {
|
||||
|
||||
svgElement.call(zoomBehavior).on("wheel.zoom", null);
|
||||
|
||||
resizeHandler = () => handleResize(containerId);
|
||||
window.addEventListener('resize', resizeHandler);
|
||||
|
||||
simulation = d3.forceSimulation()
|
||||
.force("link", d3.forceLink().id(d => d.id).distance(120))
|
||||
.force("charge", d3.forceManyBody().strength(-400))
|
||||
@@ -228,12 +231,27 @@ export function unmount(containerId) {
|
||||
if (simulation) {
|
||||
simulation.stop();
|
||||
}
|
||||
if (resizeHandler) {
|
||||
window.removeEventListener('resize', resizeHandler);
|
||||
}
|
||||
const container = document.getElementById(containerId);
|
||||
if (container) {
|
||||
container.innerHTML = ''; // clear svg
|
||||
}
|
||||
}
|
||||
|
||||
export function handleResize(containerId) {
|
||||
const container = document.getElementById(containerId);
|
||||
if (!container || !svgElement || !simulation) return;
|
||||
|
||||
width = container.clientWidth;
|
||||
height = container.clientHeight;
|
||||
|
||||
svgElement.attr("viewBox", [0, 0, width, height]);
|
||||
simulation.force("center", d3.forceCenter(width / 2, height / 2));
|
||||
simulation.alpha(0.3).restart();
|
||||
}
|
||||
|
||||
export function scrollToNode(id) {
|
||||
const el = document.getElementById(id);
|
||||
if (el) {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Handles resizing of the main application layout panes.
|
||||
*/
|
||||
export function initResizer(containerSelector, resizerSelector, variableName) {
|
||||
const container = document.querySelector(containerSelector);
|
||||
const resizer = document.querySelector(resizerSelector);
|
||||
|
||||
if (!container || !resizer) return;
|
||||
|
||||
const storageKey = 'nexus-sidebar-width';
|
||||
let isResizing = false;
|
||||
|
||||
// Load initial width
|
||||
const savedWidth = localStorage.getItem(storageKey);
|
||||
if (savedWidth) {
|
||||
container.style.setProperty(variableName, savedWidth);
|
||||
// Delay a bit to ensure components are mounted before triggering resize
|
||||
setTimeout(() => window.dispatchEvent(new Event('resize')), 100);
|
||||
}
|
||||
|
||||
resizer.addEventListener('mousedown', (e) => {
|
||||
isResizing = true;
|
||||
document.body.style.cursor = 'col-resize';
|
||||
container.classList.add('is-resizing');
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
if (!isResizing) return;
|
||||
|
||||
// Calculate new width for the right panel
|
||||
// container width - mouse X position
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const newWidth = containerRect.right - e.clientX;
|
||||
|
||||
// Constraints
|
||||
const minWidth = 300;
|
||||
const maxWidth = containerRect.width * 0.7;
|
||||
|
||||
if (newWidth >= minWidth && newWidth <= maxWidth) {
|
||||
container.style.setProperty(variableName, `${newWidth}px`);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseup', () => {
|
||||
if (isResizing) {
|
||||
isResizing = false;
|
||||
document.body.style.cursor = '';
|
||||
container.classList.remove('is-resizing');
|
||||
|
||||
// Save width
|
||||
const currentWidth = container.style.getPropertyValue(variableName);
|
||||
localStorage.setItem(storageKey, currentWidth);
|
||||
|
||||
// Dispatch a window resize event to notify components like D3
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user