diff --git a/src/components/BootstrapBlazor.DockView/BootstrapBlazor.DockView.csproj b/src/components/BootstrapBlazor.DockView/BootstrapBlazor.DockView.csproj index 05dd23b3..7b354b7a 100644 --- a/src/components/BootstrapBlazor.DockView/BootstrapBlazor.DockView.csproj +++ b/src/components/BootstrapBlazor.DockView/BootstrapBlazor.DockView.csproj @@ -1,7 +1,7 @@  - 9.1.8 + 9.1.9 diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/css/dockview-bb.css b/src/components/BootstrapBlazor.DockView/wwwroot/css/dockview-bb.css index 8436a92c..1ec748c9 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/css/dockview-bb.css +++ b/src/components/BootstrapBlazor.DockView/wwwroot/css/dockview-bb.css @@ -1,31 +1,5 @@ @import './dockview.css'; -[data-bs-theme='dark'] .bb-dockview { - --dv-background-color: black; - --dv-paneview-active-outline-color: dodgerblue; - --dv-tabs-and-actions-container-font-size: 13px; - --dv-tabs-and-actions-container-height: 35px; - --dv-drag-over-background-color: rgba(83, 89, 93, 0.5); - --dv-drag-over-border-color: white; - --dv-tabs-container-scrollbar-color: #888; - --dv-icon-hover-background-color: rgba(90, 93, 94, 0.31); - --dv-floating-box-shadow: 8px 8px 8px 0px rgba(83, 89, 93, 0.5); - --dv-group-view-background-color: #1e1e1e; - --dv-tabs-and-actions-container-background-color: #252526; - --dv-activegroup-visiblepanel-tab-background-color: #1e1e1e; - --dv-activegroup-hiddenpanel-tab-background-color: #2d2d2d; - --dv-inactivegroup-visiblepanel-tab-background-color: #1e1e1e; - --dv-inactivegroup-hiddenpanel-tab-background-color: #2d2d2d; - --dv-tab-divider-color: #1e1e1e; - --dv-activegroup-visiblepanel-tab-color: white; - --dv-activegroup-hiddenpanel-tab-color: #969696; - --dv-inactivegroup-visiblepanel-tab-color: #8f8f8f; - --dv-inactivegroup-hiddenpanel-tab-color: #626262; - --dv-separator-border: rgb(68, 68, 68); - --dv-paneview-header-border-color: rgba(204, 204, 204, 0.2); - --dv-active-sash-color: #595959; -} - .bb-dockview { --bb-dockview-padding: .25rem; --bb-dockview-tab-line-height: 21px; @@ -36,6 +10,7 @@ --bb-dockview-control-dropdown-padding-y: .25rem; --bb-dockview-control-dropdown-item-padding-x: 0; --bb-dockview-control-dropdown-item-padding-y: 3px; + --bb-dockview-aside-width: calc(1.5em + .25rem); --dv-tabs-and-actions-container-font-size: 13px; --dv-tabs-and-actions-container-height: 35px; --dv-active-sash-color: #bcbcbc; @@ -45,12 +20,12 @@ position: relative; } -.bb-dockview > div { - --dv-tabs-and-actions-container-height: 30px; - --bb-dockview-tab-line-height: 30px; - --bb-dockview-tab-padding: 0 3px; - --dv-tabs-and-actions-container-font-size: 12px; -} + .bb-dockview > div { + --dv-tabs-and-actions-container-height: 30px; + --bb-dockview-tab-line-height: 30px; + --bb-dockview-tab-padding: 0 3px; + --dv-tabs-and-actions-container-font-size: 12px; + } .bb-dockview .bb-dockview-panel { height: 100%; @@ -208,68 +183,92 @@ transition-duration: .3s; } -.bb-dockview .bb-dockview-btn-wrapper { - cursor: pointer; - float: left; - position: absolute; - left: 0; - top: 0; - transform: translate(-100%); - user-select: none; +.ribbon-body.ribbon-body > div, +.bb-dockview .dv-split-view-container, +.bb-dockview .dv-split-view-container .dv-view-container .dv-view { + overflow: initial; } - .bb-dockview .bb-dockview-btn-wrapper > div { - width: 20px; - padding: 2px 0; - margin-bottom: 10px; - position: relative; - writing-mode: vertical-lr; - text-orientation: sideways; - color: var(--dv-inactivegroup-visiblepanel-tab-color); + .bb-dockview .dv-split-view-container .dv-view-container > .dv-view > .dv-groupview:has(.dv-resize-container) { + overflow: initial !important; } - .bb-dockview .bb-dockview-btn-wrapper > div:hover, - .bb-dockview .bb-dockview-btn-wrapper > div.active { - color: var(--dv-activegroup-visiblepanel-tab-color); - } - .bb-dockview .bb-dockview-btn-wrapper > div:hover::after, - .bb-dockview .bb-dockview-btn-wrapper > div.active::after { - content: ''; - position: absolute; - left: -3px; - top: 0; - width: 3px; - height: 100%; - background-color: var(--bb-ribbon-menu-bg); - } +.bb-dockview > div:has(> .bb-dockview-aside-left > div) { + padding-left: var(--bb-dockview-aside-width); +} - .bb-dockview .bb-dockview-btn-wrapper > div span { - display: block; - margin-bottom: -5px; - } +.bb-dockview > div:has(> .bb-dockview-aside-right > div) { + padding-right: var(--bb-dockview-aside-width); +} + +.bb-dockview .bb-dockview-aside { + position: absolute; + height: 100%; + top: 0; + width: var(--bb-dockview-aside-width); + display: flex; + align-items: flex-start; + justify-content: center; +} -.bb-dockview:has(>.bb-dockview-btn-wrapper>div) { - margin-left: 23px; - width: calc(100% - 23px); +.bb-dockview .bb-dockview-aside-left { + left: 0 } -.bb-dockview .dv-resize-container.dv-resize-container-drawer > div:not(.dv-resize-handle-right):not(.dv-groupview-floating), -.bb-dockview .dv-resize-container.dv-resize-container-drawer > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-float, -.bb-dockview .dv-resize-container.dv-resize-container-drawer > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-dock, -.bb-dockview .dv-resize-container.dv-resize-container-drawer > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-down, -.bb-dockview .dv-resize-container:not(.dv-resize-container-drawer) > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-pin, -.bb-dockview .dv-resize-container:not(.dv-resize-container-drawer) > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-pushpin { - display: none; +.bb-dockview .bb-dockview-aside-right { + right: 0 +} + +.bb-dockview .bb-dockview-aside > .bb-dockview-aside-button { + position: relative; + margin-inline: .25rem; + padding-inline: .5rem; + cursor: pointer; + user-select: none; + writing-mode: vertical-lr; + text-orientation: sideways; + color: var(--dv-inactivegroup-visiblepanel-tab-color); + border-radius: 5px; +} + + .bb-dockview .bb-dockview-aside > .bb-dockview-aside-button:hover, + .bb-dockview .bb-dockview-aside > .bb-dockview-aside-button.active { + color: var(--dv-activegroup-visiblepanel-tab-color); + background-color: var(--dv-icon-hover-background-color); + } + +.bb-dockview .bb-dockview-aside-right > .bb-dockview-aside-button:hover::after, +.bb-dockview .bb-dockview-aside-right > .bb-dockview-aside-button.active::after { + right: 0; } .bb-dockview .dv-resize-container-drawer { height: 100% !important; } + .bb-dockview .dv-resize-container-drawer:not(.active) { + z-index: -1 !important; + } + +.bb-dockview .dv-resize-container.dv-resize-container-drawer.bb-resize-container-right { + box-shadow: -8px 8px 8px 0px rgba(83, 89, 93, 0.5); +} + + .bb-dockview .dv-resize-container.dv-resize-container-drawer.bb-resize-container-right > div:not(.dv-resize-handle-left):not(.dv-groupview-floating), + .bb-dockview .dv-resize-container.dv-resize-container-drawer.bb-resize-container-left > div:not(.dv-resize-handle-right):not(.dv-groupview-floating), + .bb-dockview .dv-resize-container.dv-resize-container-drawer > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-float, + .bb-dockview .dv-resize-container.dv-resize-container-drawer > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-dock, + .bb-dockview .dv-resize-container.dv-resize-container-drawer > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-down, + .bb-dockview .dv-resize-container:not(.dv-resize-container-drawer) > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-pin, + .bb-dockview .dv-resize-container:not(.dv-resize-container-drawer) > .dv-groupview-floating > .dv-tabs-and-actions-container .bb-dockview-control-icon-pushpin { + display: none; + } + .bb-dockview .dv-tabs-and-actions-container:has(.dropdown-item) .dv-scrollbar-horizontal { display: none; } + .bb-dockview .dv-tab.dv-inactive-tab .dv-default-tab .dv-default-tab-action { visibility: visible; } diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-core.esm.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-core.esm.js index aa51cb5c..fc74b43d 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-core.esm.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-core.esm.js @@ -7229,6 +7229,7 @@ class Overlay extends CompositeDisposable { this.onDidChangeEnd = this._onDidChangeEnd.event; this.addDisposables(this._onDidChange, this._onDidChangeEnd); this._element.className = 'dv-resize-container'; + this.options.className && this._element.classList.add(this.options.className); this._isVisible = true; this.setupResize('top'); this.setupResize('bottom'); @@ -8802,8 +8803,7 @@ class DockviewComponent extends BaseGrid { }; } const anchoredBox = getAnchoredBox(); - const overlay = new Overlay(Object.assign(Object.assign({ container: this.gridview.element, content: group.element }, anchoredBox), { - minimumInViewportWidth: this.options.floatingGroupBounds === 'boundedWithinViewport' + const overlay = new Overlay(Object.assign(Object.assign({ container: this.gridview.element, content: group.element, className: options === null || options === void 0 ? void 0 : options.className }, anchoredBox), { minimumInViewportWidth: this.options.floatingGroupBounds === 'boundedWithinViewport' ? undefined : (_c = (_b = this.options.floatingGroupBounds) === null || _b === void 0 ? void 0 : _b.minimumWidthWithinViewport) !== null && _c !== void 0 ? _c : DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE, minimumInViewportHeight: this.options.floatingGroupBounds === 'boundedWithinViewport' ? undefined diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js index dd2c97c4..8297e89e 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js @@ -38,7 +38,7 @@ const addGroupWithPanel = (dockview, panel, panels, index) => { const addPanelWidthGroupId = (dockview, panel, index) => { let group = dockview.api.getGroup(panel.groupId) - let { rect = {}, packup, floatType, drawer } = panel.params || {} + let { rect = {}, packup, floatType, drawer, direction = 'left' } = panel.params || {} if (!group) { group = dockview.createGroup({ id: panel.groupId }) // const floatingGroupPosition = isMaximized ? { @@ -64,7 +64,7 @@ const addPanelWidthGroupId = (dockview, panel, index) => { floatingGroupRect = { width: drawer.width || 300, height: dockview.height, - position: { left: 0, top: 0 } + position: { [direction]: 0, top: 0 } } } dockview.addFloatingGroup(group, { ...floatingGroupRect, skipRemoveGroup: true }) @@ -72,7 +72,7 @@ const addPanelWidthGroupId = (dockview, panel, index) => { observeOverlayChange(overlay, group) createGroupActions(group, floatType); if (floatType == 'drawer') { - setTimeout(() => createDrawerHandle(group), 0); + setTimeout(() => createDrawerHandle(group, direction == 'right'), 0); } // const floatingGroup = createFloatingGroup(group, floatingGroupRect) const autoHideBtn = group.header.rightActionsContainer.querySelector('.bb-dockview-control-icon-autohide') @@ -326,19 +326,27 @@ const autoHide = group => { if (!canFloat(group)) return; // 1、点击图标创建浮动窗口并隐藏 const { drawer = { width: 300, visible: true } } = group.getParams() + + const left = getOffsetFromDockview(group.element) + const width = group.element.offsetWidth + const dockviewWidth = dockview.element.querySelector('&>.dv-dockview').offsetWidth + const isRight = ((left + width) == dockviewWidth && left > 0) || left > (dockviewWidth / 2) + const rect = { position: { - left: -9999, + [isRight ? 'right' : 'left']: 0, top: 0 }, width: drawer.width, - height: '100%' + height: '100%', + className: 'dv-resize-container-drawer' } - group.setParams({ drawer, floatType: 'drawer' }) + group.setParams({ drawer, floatType: 'drawer', direction: isRight ? 'right' : 'left' }) + const floatingGroup = createFloatingGroup(group, rect, 'drawer') if (floatingGroup) { setTimeout(() => { - createDrawerHandle(floatingGroup) + createDrawerHandle(floatingGroup, isRight) }, 0); setTimeout(() => { saveConfig(dockview) @@ -347,19 +355,31 @@ const autoHide = group => { } } -const createDrawerHandle = (floatingGroup) => { +function getOffsetFromDockview(element) { + let offsetLeft = element.offsetLeft; + let parent = element.offsetParent; + while (parent && !parent.classList.contains('dv-dockview')) { + offsetLeft += parent.offsetLeft; + parent = parent.offsetParent; + } + return offsetLeft +} + +const createDrawerHandle = (floatingGroup, isRight) => { + const className = isRight ? 'bb-resize-container-right' : 'bb-resize-container-left' floatingGroup.element.parentElement.classList.add('dv-resize-container-drawer') - createDrawerBtn(floatingGroup) + floatingGroup.element.parentElement.classList.add(className) + createDrawerBtn(floatingGroup, isRight) } -const createDrawerBtn = floatingGroup => { +const createDrawerBtn = (floatingGroup, isRight) => { const dockview = floatingGroup.api.accessor const btn = document.createElement('div') const title = floatingGroup.activePanel?.title || floatingGroup.panels[0]?.title btn.innerHTML = title btn.setAttribute('groupid', dockview.id + '_' + floatingGroup.id) - btn.classList.add('drawer-btn') - if (floatingGroup.element.parentElement.style.left == '-1px') { + btn.classList.add('bb-dockview-aside-button') + if (floatingGroup.element.parentElement.classList.contains('active')) { btn.classList.add('active') } @@ -367,38 +387,41 @@ const createDrawerBtn = floatingGroup => { const fgWrapper = floatingGroup.element.parentElement const activePanel = floatingGroup.activePanel const parentElement = activePanel.view.content.element.parentElement + const direction = fgWrapper.style.left == 'auto' ? 'right' : 'left' dockview.floatingGroups.forEach(item => { const params = item.group.getParams() if (params.floatType == 'drawer' && item.group != floatingGroup) { - item.group.element.parentElement.style.left = '-9999px' + item.group.element.parentElement.classList.remove('active') if (activePanel?.renderer == 'always' && parentElement) { - parentElement.style.left = '-9999px' + parentElement.classList.remove('active'); } } }) - ;[...btn.parentElement.children].forEach(btnEle => { - btnEle.classList.remove('active') - }) - if (fgWrapper.style.left == '-1px') { - fgWrapper.style.left = '-9999px' + btn.parentElement.parentElement.querySelectorAll('&>.bb-dockview-aside>.bb-dockview-aside-button').forEach(btnEle => { + btnEle.classList.remove('active') + }) + + if (fgWrapper.classList.contains('active')) { + fgWrapper.classList.remove('active') if (activePanel?.renderer == 'always' && parentElement) { - parentElement.style.left = '-9999px' + parentElement.classList.remove('active') } } else { btn.classList.add('active') - fgWrapper.style.left = '-1px' + fgWrapper.classList.add('active') if (parentElement) { - parentElement.style.left = '0' + parentElement.classList.add('active') } } saveConfig(dockview) }) - const dvEleBox = dockview.element.parentElement - let btnWrapper = [...dvEleBox.children].find(item => item.classList.contains('bb-dockview-btn-wrapper')) + const dvEleBox = dockview.element + const className = `bb-dockview-aside-${isRight ? 'right' : 'left'}` + let btnWrapper = dvEleBox.querySelector(`&>.${className}`) if (!btnWrapper) { - btnWrapper = document.createElement('div') - btnWrapper.className = 'bb-dockview-btn-wrapper' - dvEleBox.prepend(btnWrapper) + btnWrapper = document.createElement('aside') + btnWrapper.className = className + ' bb-dockview-aside' + isRight ? dvEleBox.append(btnWrapper) : dvEleBox.prepend(btnWrapper) } btnWrapper.append(btn) } @@ -412,7 +435,7 @@ const removeDrawerBtn = group => { const setDrawerTitle = group => { const title = group.activePanel?.title || group.panels[0]?.title const groupId = group.api.accessor.id + '_' + group.id - const btnEle = group.api.accessor.element.parentElement.parentElement.querySelector(`.bb-dockview-btn-wrapper>[groupId="${groupId}"]`) + const btnEle = group.api.accessor.element.parentElement.parentElement.querySelector(`.bb-dockview-aside>[groupId="${groupId}"]`) if (!btnEle) return btnEle.innerHTML = title } @@ -508,7 +531,10 @@ const observeOverlayChange = (overlay, group) => { const parentEle = group.element.parentElement parentEle.style.height = `${parentEle.getBoundingClientRect().height}px` parentEle.classList.remove('dv-resize-container-drawer') + parentEle.classList.remove('bb-resize-container-right') + parentEle.classList.remove('bb-resize-container-left') group.removePropsOfParams('floatType') + group.removePropsOfParams('direction') group.header.rightActionsContainer.classList.remove('bb-show-autohide') group.header.rightActionsContainer.classList.add('bb-show-float') group.header.rightActionsContainer.querySelector('.bb-dockview-control-icon-down').style.display = 'block' @@ -561,6 +587,7 @@ const dock = (group, floatType) => { if (floatType == 'drawer') { group.setParams({ drawer: { ...drawer, width: rect.width } }) group.removePropsOfParams('floatType') + group.removePropsOfParams('direction') removeDrawerBtn(group) } else { @@ -577,7 +604,7 @@ const dock = (group, floatType) => { const down = (group, actionContainer) => { const parentEle = group.element.parentElement const { top, bottom, height } = parentEle.style - const tabHeight = group.activePanel.view.tab.element.offsetHeight + 2 + const tabHeight = group.header.element.offsetHeight || 30 const { packup } = group.getParams(); if (packup?.isPackup) { group.setParams({ packup: { ...packup, isPackup: false } }) diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js index 29682dc0..ca598b92 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js @@ -65,9 +65,9 @@ const onRemovePanel = event => { const appendTemplatePanelEle = (panel) => { const dockview = panel.accessor if (panel.view.content.element) { - if (panel.titleMenuEle) { - panel.view.content.element.append(panel.titleMenuEle) - } + // if (panel.titleMenuEle) { + // panel.view.content.element.append(panel.titleMenuEle) + // } if (dockview.params.template) { dockview.params.template.append(panel.view.content.element) } @@ -103,6 +103,7 @@ const updateTitle = panel => { if (titleBarElement) { titleBarElement.removeAttribute('title'); tabEle.insertAdjacentElement("afterbegin", titleBarElement); + panel.titleMenuEle = titleBarElement; } } } diff --git a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js index bfbe378a..ff4235ca 100644 --- a/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js +++ b/src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js @@ -107,9 +107,9 @@ const initDockview = (dockview, options, template) => { // saveConfig(dockview); // }) observeOverlayChange(fg.overlay, fg.group) - const { floatType } = fg.group.getParams(); + const { floatType, direction } = fg.group.getParams(); if (floatType == 'drawer') { - createDrawerHandle(fg.group) + createDrawerHandle(fg.group, direction == 'right') } else { const autoHideBtn = fg.group.header.rightActionsContainer.querySelector('.bb-dockview-control-icon-autohide') @@ -123,6 +123,14 @@ const initDockview = (dockview, options, template) => { dockview.groups.forEach(group => { observeGroup(group) }) + dockview.element.querySelector('&>.dv-dockview>.dv-branch-node').addEventListener('click', function (e) { + this.parentElement.querySelectorAll('&>.dv-resize-container-drawer').forEach(item => { + item.classList.remove('active') + }) + this.closest('.bb-dockview').querySelectorAll('&>.bb-dockview-aside>.bb-dockview-aside-button').forEach(item => { + item.classList.remove('active') + }) + }) dockview._inited = true; dockview._initialized?.fire(); }, 100);