From 3aaf14c3d9207f7317e557b3df5cd8019d67dbe2 Mon Sep 17 00:00:00 2001 From: zhaijunlei <276318515@qq.com> Date: Wed, 24 Jun 2026 11:17:46 +0800 Subject: [PATCH 1/4] fix(DockView): correct buttons and width when re-inserting into an emptied group --- .../wwwroot/js/dockview-group.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js index 175084c5..dd603e3d 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js @@ -39,6 +39,8 @@ const addGroupWithPanel = (dockview, panel, panels, index) => { const addPanelWidthGroupId = (dockview, panel, index) => { let group = dockview.api.getGroup(panel.groupId) + // Empty pre-existing group = deleted-side placeholder (deferred actions + collapsed branch); a populated one is healthy. + const reusedEmptyGroup = !!group && group.panels.length === 0; let { rect = {}, packup, floatType, drawer, direction = 'left' } = panel.params || {} if (!group) { group = dockview.createGroup({ id: panel.groupId }) @@ -73,6 +75,10 @@ const addPanelWidthGroupId = (dockview, panel, index) => { } } + // Placeholder branch collapsed to width 0 in the saved layout; restore the pre-delete width (currentPosition) + // via initialWidth → setSize, else it re-shows at min ~100. + const restoreWidth = reusedEmptyGroup && group.api.location.type === 'grid' + ? panel.params?.currentPosition?.width : undefined; dockview.addPanel({ id: panel.id, title: panel.title, @@ -80,8 +86,15 @@ const addPanelWidthGroupId = (dockview, panel, index) => { renderer: panel.renderer, component: panel.component, position: { referenceGroup: group, index: index || 0 }, + initialWidth: restoreWidth > 0 ? restoreWidth : undefined, params: { ...panel.params, rect, packup, visible: true } }) + + // Placeholder deferred its action states while empty (see resetActionStates); re-render now it has a panel. + if (reusedEmptyGroup && group.api.location.type === 'grid') { + const actionContainer = group.header.element.querySelector('.dv-right-actions-container'); + if (actionContainer) resetActionStates(group, actionContainer); + } } const addPanelWidthCreatGroup = (dockview, panel, panels) => { @@ -175,6 +188,10 @@ const disposeGroup = group => { const resetActionStates = (group, actionContainer, groupType) => { const dockview = group.api.accessor; + // Empty group: `[].every()` is vacuously true so every show*() falls back to options defaults, wrongly showing + // buttons that stick once re-filled. Defer until it has panels (re-rendered on insert in addPanelWidthGroupId). + if (group.panels.length === 0) return; + // bb-show-lock only gates the button; apply the lock STATE regardless so a locked group stays locked when showLock=false. if (showLock(dockview, group)) { actionContainer.classList.add('bb-show-lock'); } From ed8a9233586a2ee40bf6f881a6087a8d248a781d Mon Sep 17 00:00:00 2001 From: zhaijunlei <276318515@qq.com> Date: Wed, 24 Jun 2026 12:48:28 +0800 Subject: [PATCH 2/4] fix(DockView): re-render action buttons after docking a floating group back to grid --- .../wwwroot/js/dockview-group.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js index dd603e3d..038a8db7 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js @@ -92,8 +92,7 @@ const addPanelWidthGroupId = (dockview, panel, index) => { // Placeholder deferred its action states while empty (see resetActionStates); re-render now it has a panel. if (reusedEmptyGroup && group.api.location.type === 'grid') { - const actionContainer = group.header.element.querySelector('.dv-right-actions-container'); - if (actionContainer) resetActionStates(group, actionContainer); + reRenderActionStates(group); } } @@ -221,6 +220,12 @@ const resetActionStates = (group, actionContainer, groupType) => { } } +// Re-render action buttons after an empty placeholder gains a panel (its actions were deferred while empty). +const reRenderActionStates = group => { + const actionContainer = group.header.element.querySelector('.dv-right-actions-container'); + if (actionContainer) resetActionStates(group, actionContainer); +} + const showLock = (dockview, group) => { const { options } = dockview.params; return group.panels.every(panel => panel.params.showLock === null) @@ -638,6 +643,8 @@ const dock = (group, floatType) => { from: { group: group }, to: { group: originGroup, position: 'center' } }) + // originGroup was an empty placeholder while floated; its deferred action buttons need re-rendering now it is filled. + reRenderActionStates(originGroup) saveConfig(dockview) } From fde7efbd124dc4e490fe88bea0a1cf75183437e0 Mon Sep 17 00:00:00 2001 From: zhaijunlei <276318515@qq.com> Date: Wed, 24 Jun 2026 15:56:41 +0800 Subject: [PATCH 3/4] fix(DockView): keep floating group highlight, active panel and size across close and re-insert --- .../wwwroot/js/dockview-extensions.js | 7 ++++++- .../wwwroot/js/dockview-group.js | 13 +++++++++++-- .../wwwroot/js/dockview-panel.js | 5 +++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js index b6d6dc5e..cc4f5539 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js @@ -62,7 +62,12 @@ DockviewComponent.prototype.removeGroup = function (...args) { } else if (type == 'floating') { removeDrawerBtn(group) - return removeGroup.apply(this, args) + // Close panels (like the grid path) so each fires _panelVisibleChanged; the last close re-enters empty and removes the group. + const panels = [...group.panels] + if (panels.length === 0) { + return removeGroup.apply(this, args) + } + panels.forEach(panel => panel.api.close()) } } diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js index 038a8db7..ed07958f 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js @@ -41,14 +41,18 @@ const addPanelWidthGroupId = (dockview, panel, index) => { let group = dockview.api.getGroup(panel.groupId) // Empty pre-existing group = deleted-side placeholder (deferred actions + collapsed branch); a populated one is healthy. const reusedEmptyGroup = !!group && group.panels.length === 0; - let { rect = {}, packup, floatType, drawer, direction = 'left' } = panel.params || {} + const isNewFloatingGroup = !group; + let { rect = {}, packup, floatType, drawer, direction = 'left', currentPosition } = panel.params || {} if (!group) { group = dockview.createGroup({ id: panel.groupId }) const width = dockview.width > 500 ? 500 : (dockview.width - 10) const height = dockview.height > 460 ? 460 : (dockview.height - 10) const left = (dockview.width - width) / 2 const top = (dockview.height - height) / 2 - let floatingGroupRect = rect || { + // Prefer currentPosition (saved on hide) over rect (only refreshed on un-float) to keep last size & position. + let floatingGroupRect = (currentPosition?.width > 0 + ? { width: currentPosition.width, height: currentPosition.height, position: { top: currentPosition.top, left: currentPosition.left } } + : rect) || { width, height: packup?.isPackup ? packup.height : height, position: { left, top } } if (floatType == 'drawer') { @@ -90,6 +94,11 @@ const addPanelWidthGroupId = (dockview, panel, index) => { params: { ...panel.params, rect, packup, visible: true } }) + // addPanel is inactive; activate so a freshly created floating group isn't blank. + if (isNewFloatingGroup) { + group.panels.find(p => p.id === panel.id)?.api.setActive(); + } + // Placeholder deferred its action states while empty (see resetActionStates); re-render now it has a panel. if (reusedEmptyGroup && group.api.location.type === 'grid') { reRenderActionStates(group); diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js index 68a4e3a5..cc3a755a 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js @@ -65,8 +65,9 @@ const onRemovePanel = event => { currentPosition: { width: event.group.element.parentElement.offsetWidth, height: event.group.element.parentElement.offsetHeight, - top: parseFloat(event.group.element.parentElement.style.top || 0), - left: parseFloat(event.group.element.parentElement.style.left || 0) + // offsetTop/Left, not style.top/left which can be 'auto' -> parseFloat NaN -> lost position. + top: event.group.element.parentElement.offsetTop, + left: event.group.element.parentElement.offsetLeft }, index: event.group.delPanelIndex } From 656e9327c9a7b2bb2f06f78747b2376d2243b35a Mon Sep 17 00:00:00 2001 From: zhaijunlei <276318515@qq.com> Date: Wed, 24 Jun 2026 16:37:15 +0800 Subject: [PATCH 4/4] fix(DockView): clear pending size on re-open so float/dock-back keeps the resized width --- .../BootstrapBlazor.DockView/wwwroot/js/dockview-group.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js index ed07958f..2b72e762 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js @@ -102,6 +102,8 @@ const addPanelWidthGroupId = (dockview, panel, index) => { // Placeholder deferred its action states while empty (see resetActionStates); re-render now it has a panel. if (reusedEmptyGroup && group.api.location.type === 'grid') { reRenderActionStates(group); + // initialWidth left a _pendingSize; clear it so a later setVisible(true) (float->dock) won't replay this stale width. + if (restoreWidth > 0) group.api._pendingSize = undefined; } }