dockview-core 7.0.4 → 8.0.0
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/LICENCE.md +21 -0
- package/README.md +17 -86
- package/dist/cjs/api/component.api.d.ts +100 -9
- package/dist/cjs/api/dockviewGroupPanelApi.d.ts +45 -1
- package/dist/cjs/api/dockviewPanelApi.d.ts +21 -0
- package/dist/cjs/dismissableLayer.d.ts +57 -0
- package/dist/cjs/dnd/backend.d.ts +2 -2
- package/dist/cjs/dnd/dropTargetAnchorContainer.d.ts +12 -0
- package/dist/cjs/dnd/droptarget.d.ts +94 -0
- package/dist/cjs/dnd/ghost.d.ts +1 -0
- package/dist/cjs/dnd/pointer/longPress.d.ts +2 -2
- package/dist/cjs/dnd/pointer/pointerDragController.d.ts +5 -2
- package/dist/cjs/dnd/pointer/pointerDragSource.d.ts +1 -1
- package/dist/cjs/dnd/pointer/pointerDropTarget.d.ts +30 -1
- package/dist/cjs/dnd/pointer/pointerGhost.d.ts +1 -1
- package/dist/cjs/dockview/accessibilityMessages.d.ts +6 -0
- package/dist/cjs/dockview/advancedDnDService.d.ts +46 -0
- package/dist/cjs/dockview/components/panel/content.d.ts +1 -1
- package/dist/cjs/dockview/components/tab/defaultTab.d.ts +2 -0
- package/dist/cjs/dockview/components/tab/tab.d.ts +2 -0
- package/dist/cjs/dockview/components/titlebar/floatingTitleBar.d.ts +2 -2
- package/dist/cjs/dockview/components/titlebar/groupDragSource.d.ts +1 -1
- package/dist/cjs/dockview/components/titlebar/tabGroupChip.d.ts +1 -1
- package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.d.ts +73 -2
- package/dist/cjs/dockview/components/titlebar/tabGroups.d.ts +1 -1
- package/dist/cjs/dockview/components/titlebar/tabReorderController.d.ts +295 -0
- package/dist/cjs/dockview/components/titlebar/tabs.d.ts +120 -50
- package/dist/cjs/dockview/components/titlebar/tabsContainer.d.ts +48 -0
- package/dist/cjs/dockview/dndCapabilities.d.ts +1 -1
- package/dist/cjs/dockview/dockviewComponent.d.ts +303 -19
- package/dist/cjs/dockview/dockviewGroupPanel.d.ts +5 -0
- package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +52 -2
- package/dist/cjs/dockview/dockviewPanel.d.ts +12 -0
- package/dist/cjs/dockview/dockviewShell.d.ts +48 -24
- package/dist/cjs/dockview/edgeGroupService.d.ts +20 -0
- package/dist/cjs/dockview/events.d.ts +6 -0
- package/dist/cjs/dockview/liveRegionService.d.ts +18 -5
- package/dist/cjs/dockview/moduleContracts.d.ts +480 -14
- package/dist/cjs/dockview/modules.d.ts +101 -22
- package/dist/cjs/dockview/options.d.ts +337 -30
- package/dist/cjs/dockview/optionsModules.d.ts +73 -0
- package/dist/cjs/dockview/popoutWindowService.d.ts +15 -10
- package/dist/cjs/dockview/rootDropTargetService.d.ts +11 -0
- package/dist/cjs/dockview/tabGroupAccent.d.ts +1 -1
- package/dist/cjs/dockview/tabGroupChipsService.d.ts +10 -0
- package/dist/cjs/dockview/theme.d.ts +2 -2
- package/dist/cjs/dockview/types.d.ts +3 -0
- package/dist/cjs/dom.d.ts +9 -1
- package/dist/cjs/gridview/baseComponentGridview.d.ts +2 -2
- package/dist/cjs/gridview/gridview.d.ts +2 -0
- package/dist/cjs/index.d.ts +35 -29
- package/dist/cjs/lifecycle.d.ts +1 -0
- package/dist/cjs/overlay/overlay.d.ts +4 -2
- package/dist/cjs/overlay/overlayRenderContainer.d.ts +8 -0
- package/dist/cjs/paneview/paneview.d.ts +2 -1
- package/dist/cjs/paneview/paneviewComponent.d.ts +3 -0
- package/dist/cjs/paneview/paneviewPanel.d.ts +5 -0
- package/dist/cjs/svg.d.ts +1 -0
- package/dist/cjs/types.d.ts +8 -0
- package/dist/dockview-core.js +18391 -19679
- package/dist/dockview-core.min.js +4138 -6
- package/dist/dockview-core.min.noStyle.js +6 -7
- package/dist/dockview-core.noStyle.js +18390 -19656
- package/dist/package/main.cjs.js +18002 -19268
- package/dist/package/main.cjs.min.js +6 -6
- package/dist/package/main.esm.min.mjs +6 -6
- package/dist/package/main.esm.mjs +17959 -19260
- package/package.json +81 -77
- package/dist/cjs/api/component.api.js +0 -1242
- package/dist/cjs/api/dockviewGroupPanelApi.js +0 -200
- package/dist/cjs/api/dockviewPanelApi.js +0 -172
- package/dist/cjs/api/entryPoints.js +0 -27
- package/dist/cjs/api/gridviewPanelApi.js +0 -45
- package/dist/cjs/api/panelApi.js +0 -133
- package/dist/cjs/api/paneviewPanelApi.js +0 -57
- package/dist/cjs/api/splitviewPanelApi.js +0 -47
- package/dist/cjs/array.js +0 -66
- package/dist/cjs/constants.js +0 -11
- package/dist/cjs/dnd/backend.js +0 -171
- package/dist/cjs/dnd/dataTransfer.js +0 -100
- package/dist/cjs/dnd/dnd.js +0 -74
- package/dist/cjs/dnd/dropOverlay.js +0 -197
- package/dist/cjs/dnd/dropTargetAnchorContainer.js +0 -104
- package/dist/cjs/dnd/droptarget.js +0 -362
- package/dist/cjs/dnd/ghost.js +0 -17
- package/dist/cjs/dnd/pointer/index.js +0 -13
- package/dist/cjs/dnd/pointer/longPress.js +0 -151
- package/dist/cjs/dnd/pointer/pointerDragController.js +0 -243
- package/dist/cjs/dnd/pointer/pointerDragSource.js +0 -197
- package/dist/cjs/dnd/pointer/pointerDropTarget.js +0 -198
- package/dist/cjs/dnd/pointer/pointerGhost.js +0 -44
- package/dist/cjs/dnd/pointer/types.js +0 -2
- package/dist/cjs/dockview/accessibilityMessages.js +0 -51
- package/dist/cjs/dockview/allModules.js +0 -25
- package/dist/cjs/dockview/components/panel/content.js +0 -213
- package/dist/cjs/dockview/components/popupService.js +0 -132
- package/dist/cjs/dockview/components/tab/defaultTab.js +0 -70
- package/dist/cjs/dockview/components/tab/tab.js +0 -281
- package/dist/cjs/dockview/components/titlebar/floatingTitleBar.js +0 -95
- package/dist/cjs/dockview/components/titlebar/groupDragSource.js +0 -218
- package/dist/cjs/dockview/components/titlebar/tabGroupChip.js +0 -104
- package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +0 -477
- package/dist/cjs/dockview/components/titlebar/tabGroups.js +0 -854
- package/dist/cjs/dockview/components/titlebar/tabOverflowControl.js +0 -19
- package/dist/cjs/dockview/components/titlebar/tabs.js +0 -2016
- package/dist/cjs/dockview/components/titlebar/tabsContainer.js +0 -458
- package/dist/cjs/dockview/components/titlebar/voidContainer.js +0 -120
- package/dist/cjs/dockview/components/watermark/watermark.js +0 -40
- package/dist/cjs/dockview/deserializer.js +0 -39
- package/dist/cjs/dockview/dndCapabilities.js +0 -39
- package/dist/cjs/dockview/dockviewComponent.js +0 -3896
- package/dist/cjs/dockview/dockviewFloatingGroupPanel.js +0 -70
- package/dist/cjs/dockview/dockviewGroupPanel.js +0 -204
- package/dist/cjs/dockview/dockviewGroupPanelModel.js +0 -1514
- package/dist/cjs/dockview/dockviewPanel.js +0 -265
- package/dist/cjs/dockview/dockviewPanelModel.js +0 -105
- package/dist/cjs/dockview/dockviewShell.js +0 -744
- package/dist/cjs/dockview/edgeGroupService.js +0 -128
- package/dist/cjs/dockview/events.js +0 -67
- package/dist/cjs/dockview/floatingGroupService.js +0 -231
- package/dist/cjs/dockview/framework.js +0 -2
- package/dist/cjs/dockview/headerActionsService.js +0 -149
- package/dist/cjs/dockview/liveRegionService.js +0 -185
- package/dist/cjs/dockview/moduleContracts.js +0 -2
- package/dist/cjs/dockview/modules.js +0 -304
- package/dist/cjs/dockview/options.js +0 -103
- package/dist/cjs/dockview/popoutWindowService.js +0 -261
- package/dist/cjs/dockview/rootDropTargetService.js +0 -87
- package/dist/cjs/dockview/strictEventsSequencing.js +0 -63
- package/dist/cjs/dockview/tabGroup.js +0 -219
- package/dist/cjs/dockview/tabGroupAccent.js +0 -126
- package/dist/cjs/dockview/theme.js +0 -139
- package/dist/cjs/dockview/types.js +0 -2
- package/dist/cjs/dockview/validate.js +0 -76
- package/dist/cjs/dockview/watermarkService.js +0 -61
- package/dist/cjs/dom.js +0 -543
- package/dist/cjs/events.js +0 -296
- package/dist/cjs/framwork.js +0 -2
- package/dist/cjs/gridview/baseComponentGridview.js +0 -330
- package/dist/cjs/gridview/basePanelView.js +0 -162
- package/dist/cjs/gridview/branchNode.js +0 -372
- package/dist/cjs/gridview/gridview.js +0 -776
- package/dist/cjs/gridview/gridviewComponent.js +0 -363
- package/dist/cjs/gridview/gridviewPanel.js +0 -249
- package/dist/cjs/gridview/leafNode.js +0 -169
- package/dist/cjs/gridview/options.js +0 -17
- package/dist/cjs/gridview/types.js +0 -2
- package/dist/cjs/index.js +0 -105
- package/dist/cjs/lifecycle.js +0 -80
- package/dist/cjs/math.js +0 -38
- package/dist/cjs/overlay/overlay.js +0 -602
- package/dist/cjs/overlay/overlayRenderContainer.js +0 -309
- package/dist/cjs/panel/types.js +0 -2
- package/dist/cjs/paneview/defaultPaneviewHeader.js +0 -92
- package/dist/cjs/paneview/draggablePaneviewPanel.js +0 -141
- package/dist/cjs/paneview/options.js +0 -44
- package/dist/cjs/paneview/paneview.js +0 -203
- package/dist/cjs/paneview/paneviewComponent.js +0 -430
- package/dist/cjs/paneview/paneviewPanel.js +0 -275
- package/dist/cjs/popoutWindow.js +0 -244
- package/dist/cjs/resizable.js +0 -97
- package/dist/cjs/scrollbar.js +0 -169
- package/dist/cjs/splitview/options.js +0 -19
- package/dist/cjs/splitview/splitview.js +0 -999
- package/dist/cjs/splitview/splitviewComponent.js +0 -401
- package/dist/cjs/splitview/splitviewPanel.js +0 -179
- package/dist/cjs/splitview/viewItem.js +0 -119
- package/dist/cjs/svg.js +0 -43
- package/dist/cjs/types.js +0 -2
- package/dist/dockview-core.min.js.map +0 -1
- package/dist/dockview-core.min.noStyle.js.map +0 -1
- package/dist/esm/api/component.api.d.ts +0 -640
- package/dist/esm/api/component.api.js +0 -887
- package/dist/esm/api/dockviewGroupPanelApi.d.ts +0 -109
- package/dist/esm/api/dockviewGroupPanelApi.js +0 -155
- package/dist/esm/api/dockviewPanelApi.d.ts +0 -84
- package/dist/esm/api/dockviewPanelApi.js +0 -124
- package/dist/esm/api/entryPoints.d.ts +0 -9
- package/dist/esm/api/entryPoints.js +0 -21
- package/dist/esm/api/gridviewPanelApi.d.ts +0 -37
- package/dist/esm/api/gridviewPanelApi.js +0 -23
- package/dist/esm/api/panelApi.d.ts +0 -100
- package/dist/esm/api/panelApi.js +0 -87
- package/dist/esm/api/paneviewPanelApi.d.ts +0 -26
- package/dist/esm/api/paneviewPanelApi.js +0 -27
- package/dist/esm/api/splitviewPanelApi.d.ts +0 -32
- package/dist/esm/api/splitviewPanelApi.js +0 -25
- package/dist/esm/array.d.ts +0 -13
- package/dist/esm/array.js +0 -57
- package/dist/esm/constants.d.ts +0 -8
- package/dist/esm/constants.js +0 -8
- package/dist/esm/dnd/backend.d.ts +0 -70
- package/dist/esm/dnd/backend.js +0 -148
- package/dist/esm/dnd/dataTransfer.d.ts +0 -31
- package/dist/esm/dnd/dataTransfer.js +0 -67
- package/dist/esm/dnd/dnd.d.ts +0 -32
- package/dist/esm/dnd/dnd.js +0 -51
- package/dist/esm/dnd/dropOverlay.d.ts +0 -20
- package/dist/esm/dnd/dropOverlay.js +0 -192
- package/dist/esm/dnd/dropTargetAnchorContainer.d.ts +0 -16
- package/dist/esm/dnd/dropTargetAnchorContainer.js +0 -73
- package/dist/esm/dnd/droptarget.d.ts +0 -116
- package/dist/esm/dnd/droptarget.js +0 -316
- package/dist/esm/dnd/ghost.d.ts +0 -4
- package/dist/esm/dnd/ghost.js +0 -14
- package/dist/esm/dnd/pointer/index.d.ts +0 -11
- package/dist/esm/dnd/pointer/index.js +0 -5
- package/dist/esm/dnd/pointer/longPress.d.ts +0 -32
- package/dist/esm/dnd/pointer/longPress.js +0 -127
- package/dist/esm/dnd/pointer/pointerDragController.d.ts +0 -60
- package/dist/esm/dnd/pointer/pointerDragController.js +0 -193
- package/dist/esm/dnd/pointer/pointerDragSource.d.ts +0 -61
- package/dist/esm/dnd/pointer/pointerDragSource.js +0 -173
- package/dist/esm/dnd/pointer/pointerDropTarget.d.ts +0 -39
- package/dist/esm/dnd/pointer/pointerDropTarget.js +0 -168
- package/dist/esm/dnd/pointer/pointerGhost.d.ts +0 -30
- package/dist/esm/dnd/pointer/pointerGhost.js +0 -39
- package/dist/esm/dnd/pointer/types.d.ts +0 -16
- package/dist/esm/dnd/pointer/types.js +0 -1
- package/dist/esm/dockview/accessibilityMessages.d.ts +0 -32
- package/dist/esm/dockview/accessibilityMessages.js +0 -30
- package/dist/esm/dockview/allModules.d.ts +0 -8
- package/dist/esm/dockview/allModules.js +0 -22
- package/dist/esm/dockview/components/panel/content.d.ts +0 -54
- package/dist/esm/dockview/components/panel/content.js +0 -185
- package/dist/esm/dockview/components/popupService.d.ts +0 -21
- package/dist/esm/dockview/components/popupService.js +0 -108
- package/dist/esm/dockview/components/tab/defaultTab.d.ts +0 -12
- package/dist/esm/dockview/components/tab/defaultTab.js +0 -43
- package/dist/esm/dockview/components/tab/tab.d.ts +0 -44
- package/dist/esm/dockview/components/tab/tab.js +0 -242
- package/dist/esm/dockview/components/titlebar/floatingTitleBar.d.ts +0 -34
- package/dist/esm/dockview/components/titlebar/floatingTitleBar.js +0 -65
- package/dist/esm/dockview/components/titlebar/groupDragSource.d.ts +0 -51
- package/dist/esm/dockview/components/titlebar/groupDragSource.js +0 -178
- package/dist/esm/dockview/components/titlebar/tabGroupChip.d.ts +0 -37
- package/dist/esm/dockview/components/titlebar/tabGroupChip.js +0 -77
- package/dist/esm/dockview/components/titlebar/tabGroupIndicator.d.ts +0 -72
- package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +0 -360
- package/dist/esm/dockview/components/titlebar/tabGroups.d.ts +0 -107
- package/dist/esm/dockview/components/titlebar/tabGroups.js +0 -621
- package/dist/esm/dockview/components/titlebar/tabOverflowControl.d.ts +0 -8
- package/dist/esm/dockview/components/titlebar/tabOverflowControl.js +0 -16
- package/dist/esm/dockview/components/titlebar/tabs.d.ts +0 -167
- package/dist/esm/dockview/components/titlebar/tabs.js +0 -1653
- package/dist/esm/dockview/components/titlebar/tabsContainer.d.ts +0 -104
- package/dist/esm/dockview/components/titlebar/tabsContainer.js +0 -359
- package/dist/esm/dockview/components/titlebar/voidContainer.d.ts +0 -21
- package/dist/esm/dockview/components/titlebar/voidContainer.js +0 -92
- package/dist/esm/dockview/components/watermark/watermark.d.ts +0 -8
- package/dist/esm/dockview/components/watermark/watermark.js +0 -14
- package/dist/esm/dockview/deserializer.d.ts +0 -12
- package/dist/esm/dockview/deserializer.js +0 -34
- package/dist/esm/dockview/dndCapabilities.d.ts +0 -19
- package/dist/esm/dockview/dndCapabilities.js +0 -36
- package/dist/esm/dockview/dockviewComponent.d.ts +0 -626
- package/dist/esm/dockview/dockviewComponent.js +0 -3214
- package/dist/esm/dockview/dockviewFloatingGroupPanel.d.ts +0 -45
- package/dist/esm/dockview/dockviewFloatingGroupPanel.js +0 -44
- package/dist/esm/dockview/dockviewGroupPanel.d.ts +0 -35
- package/dist/esm/dockview/dockviewGroupPanel.js +0 -142
- package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +0 -358
- package/dist/esm/dockview/dockviewGroupPanelModel.js +0 -1180
- package/dist/esm/dockview/dockviewPanel.d.ts +0 -69
- package/dist/esm/dockview/dockviewPanel.js +0 -178
- package/dist/esm/dockview/dockviewPanelModel.d.ts +0 -37
- package/dist/esm/dockview/dockviewPanelModel.js +0 -81
- package/dist/esm/dockview/dockviewShell.d.ts +0 -150
- package/dist/esm/dockview/dockviewShell.js +0 -678
- package/dist/esm/dockview/edgeGroupService.d.ts +0 -38
- package/dist/esm/dockview/edgeGroupService.js +0 -63
- package/dist/esm/dockview/events.d.ts +0 -38
- package/dist/esm/dockview/events.js +0 -34
- package/dist/esm/dockview/floatingGroupService.d.ts +0 -37
- package/dist/esm/dockview/floatingGroupService.js +0 -150
- package/dist/esm/dockview/framework.d.ts +0 -65
- package/dist/esm/dockview/framework.js +0 -1
- package/dist/esm/dockview/headerActionsService.d.ts +0 -32
- package/dist/esm/dockview/headerActionsService.js +0 -86
- package/dist/esm/dockview/liveRegionService.d.ts +0 -53
- package/dist/esm/dockview/liveRegionService.js +0 -159
- package/dist/esm/dockview/moduleContracts.d.ts +0 -119
- package/dist/esm/dockview/moduleContracts.js +0 -1
- package/dist/esm/dockview/modules.d.ts +0 -110
- package/dist/esm/dockview/modules.js +0 -170
- package/dist/esm/dockview/options.d.ts +0 -474
- package/dist/esm/dockview/options.js +0 -77
- package/dist/esm/dockview/popoutWindowService.d.ts +0 -95
- package/dist/esm/dockview/popoutWindowService.js +0 -175
- package/dist/esm/dockview/rootDropTargetService.d.ts +0 -35
- package/dist/esm/dockview/rootDropTargetService.js +0 -82
- package/dist/esm/dockview/strictEventsSequencing.d.ts +0 -7
- package/dist/esm/dockview/strictEventsSequencing.js +0 -41
- package/dist/esm/dockview/tabGroup.d.ts +0 -99
- package/dist/esm/dockview/tabGroup.js +0 -144
- package/dist/esm/dockview/tabGroupAccent.d.ts +0 -65
- package/dist/esm/dockview/tabGroupAccent.js +0 -114
- package/dist/esm/dockview/theme.d.ts +0 -86
- package/dist/esm/dockview/theme.js +0 -136
- package/dist/esm/dockview/types.d.ts +0 -53
- package/dist/esm/dockview/types.js +0 -1
- package/dist/esm/dockview/validate.d.ts +0 -0
- package/dist/esm/dockview/validate.js +0 -76
- package/dist/esm/dockview/watermarkService.d.ts +0 -30
- package/dist/esm/dockview/watermarkService.js +0 -56
- package/dist/esm/dom.d.ts +0 -60
- package/dist/esm/dom.js +0 -375
- package/dist/esm/events.d.ts +0 -79
- package/dist/esm/events.js +0 -219
- package/dist/esm/framwork.d.ts +0 -4
- package/dist/esm/framwork.js +0 -1
- package/dist/esm/gridview/baseComponentGridview.d.ts +0 -111
- package/dist/esm/gridview/baseComponentGridview.js +0 -237
- package/dist/esm/gridview/basePanelView.d.ts +0 -40
- package/dist/esm/gridview/basePanelView.js +0 -91
- package/dist/esm/gridview/branchNode.d.ts +0 -57
- package/dist/esm/gridview/branchNode.js +0 -257
- package/dist/esm/gridview/gridview.d.ts +0 -158
- package/dist/esm/gridview/gridview.js +0 -681
- package/dist/esm/gridview/gridviewComponent.d.ts +0 -88
- package/dist/esm/gridview/gridviewComponent.js +0 -265
- package/dist/esm/gridview/gridviewPanel.d.ts +0 -77
- package/dist/esm/gridview/gridviewPanel.js +0 -182
- package/dist/esm/gridview/leafNode.d.ts +0 -34
- package/dist/esm/gridview/leafNode.js +0 -102
- package/dist/esm/gridview/options.d.ts +0 -15
- package/dist/esm/gridview/options.js +0 -14
- package/dist/esm/gridview/types.d.ts +0 -3
- package/dist/esm/gridview/types.js +0 -1
- package/dist/esm/index.d.ts +0 -58
- package/dist/esm/index.js +0 -44
- package/dist/esm/lifecycle.d.ts +0 -25
- package/dist/esm/lifecycle.js +0 -56
- package/dist/esm/math.d.ts +0 -5
- package/dist/esm/math.js +0 -32
- package/dist/esm/overlay/overlay.d.ts +0 -91
- package/dist/esm/overlay/overlay.js +0 -520
- package/dist/esm/overlay/overlayRenderContainer.d.ts +0 -24
- package/dist/esm/overlay/overlayRenderContainer.js +0 -249
- package/dist/esm/panel/types.d.ts +0 -33
- package/dist/esm/panel/types.js +0 -1
- package/dist/esm/paneview/defaultPaneviewHeader.d.ts +0 -21
- package/dist/esm/paneview/defaultPaneviewHeader.js +0 -65
- package/dist/esm/paneview/draggablePaneviewPanel.d.ts +0 -38
- package/dist/esm/paneview/draggablePaneviewPanel.js +0 -107
- package/dist/esm/paneview/options.d.ts +0 -30
- package/dist/esm/paneview/options.js +0 -22
- package/dist/esm/paneview/paneview.d.ts +0 -41
- package/dist/esm/paneview/paneview.js +0 -148
- package/dist/esm/paneview/paneviewComponent.d.ts +0 -133
- package/dist/esm/paneview/paneviewComponent.js +0 -306
- package/dist/esm/paneview/paneviewPanel.d.ts +0 -98
- package/dist/esm/paneview/paneviewPanel.js +0 -192
- package/dist/esm/popoutWindow.d.ts +0 -38
- package/dist/esm/popoutWindow.js +0 -170
- package/dist/esm/resizable.d.ts +0 -12
- package/dist/esm/resizable.js +0 -66
- package/dist/esm/scrollbar.d.ts +0 -15
- package/dist/esm/scrollbar.js +0 -139
- package/dist/esm/splitview/options.d.ts +0 -21
- package/dist/esm/splitview/options.js +0 -16
- package/dist/esm/splitview/splitview.d.ts +0 -145
- package/dist/esm/splitview/splitview.js +0 -770
- package/dist/esm/splitview/splitviewComponent.d.ts +0 -101
- package/dist/esm/splitview/splitviewComponent.js +0 -267
- package/dist/esm/splitview/splitviewPanel.d.ts +0 -45
- package/dist/esm/splitview/splitviewPanel.js +0 -108
- package/dist/esm/splitview/viewItem.d.ts +0 -25
- package/dist/esm/splitview/viewItem.js +0 -74
- package/dist/esm/svg.d.ts +0 -3
- package/dist/esm/svg.js +0 -31
- package/dist/esm/types.d.ts +0 -31
- package/dist/esm/types.js +0 -1
- package/dist/styles/dockview.css +0 -3436
|
@@ -1,1653 +0,0 @@
|
|
|
1
|
-
import { getPanelData } from '../../../dnd/dataTransfer';
|
|
2
|
-
import { addClasses, isChildEntirelyVisibleWithinParent, OverflowObserver, removeClasses, toggleClass, } from '../../../dom';
|
|
3
|
-
import { addDisposableListener, Emitter } from '../../../events';
|
|
4
|
-
import { CompositeDisposable, Disposable, MutableDisposable, } from '../../../lifecycle';
|
|
5
|
-
import { Scrollbar } from '../../../scrollbar';
|
|
6
|
-
import { PointerDragController } from '../../../dnd/pointer/pointerDragController';
|
|
7
|
-
import { DockviewWillShowOverlayLocationEvent } from '../../events';
|
|
8
|
-
import { Tab } from '../tab/tab';
|
|
9
|
-
import { TabGroupManager } from './tabGroups';
|
|
10
|
-
export class Tabs extends CompositeDisposable {
|
|
11
|
-
get showTabsOverflowControl() {
|
|
12
|
-
return this._showTabsOverflowControl;
|
|
13
|
-
}
|
|
14
|
-
set showTabsOverflowControl(value) {
|
|
15
|
-
if (this._showTabsOverflowControl == value) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
this._showTabsOverflowControl = value;
|
|
19
|
-
if (value) {
|
|
20
|
-
const observer = new OverflowObserver(this._tabsList);
|
|
21
|
-
this._observerDisposable.value = new CompositeDisposable(observer, observer.onDidChange((event) => {
|
|
22
|
-
const hasOverflow = event.hasScrollX || event.hasScrollY;
|
|
23
|
-
this.toggleDropdown({ reset: !hasOverflow });
|
|
24
|
-
if (this._tabGroupManager.groupUnderlines.size > 0) {
|
|
25
|
-
this._tabGroupManager.positionUnderlines();
|
|
26
|
-
}
|
|
27
|
-
}), addDisposableListener(this._tabsList, 'scroll', () => {
|
|
28
|
-
this.toggleDropdown({ reset: false });
|
|
29
|
-
if (this._tabGroupManager.groupUnderlines.size > 0) {
|
|
30
|
-
this._tabGroupManager.positionUnderlines();
|
|
31
|
-
}
|
|
32
|
-
}));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
get element() {
|
|
36
|
-
return this._element;
|
|
37
|
-
}
|
|
38
|
-
set voidContainer(el) {
|
|
39
|
-
var _a;
|
|
40
|
-
(_a = this._voidContainerListeners) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
41
|
-
this._voidContainerListeners = null;
|
|
42
|
-
this._voidContainer = el;
|
|
43
|
-
if (el) {
|
|
44
|
-
this._voidContainerListeners = new CompositeDisposable(addDisposableListener(el, 'dragover', (event) => {
|
|
45
|
-
if (this._animState) {
|
|
46
|
-
event.preventDefault();
|
|
47
|
-
}
|
|
48
|
-
}), addDisposableListener(el, 'drop', (event) => {
|
|
49
|
-
var _a;
|
|
50
|
-
if (((_a = this._animState) === null || _a === void 0 ? void 0 : _a.sourceTabGroupId) &&
|
|
51
|
-
this._animState.currentInsertionIndex !== null) {
|
|
52
|
-
event.preventDefault();
|
|
53
|
-
event.stopPropagation();
|
|
54
|
-
this.handleVoidDrop();
|
|
55
|
-
}
|
|
56
|
-
}));
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Handle a drop that occurred on the void container (empty header
|
|
61
|
-
* space to the right of the tabs). Returns `true` if the drop was
|
|
62
|
-
* consumed by an active group drag, `false` otherwise.
|
|
63
|
-
*/
|
|
64
|
-
handleVoidDrop() {
|
|
65
|
-
var _a, _b;
|
|
66
|
-
if (!((_a = this._animState) === null || _a === void 0 ? void 0 : _a.sourceTabGroupId)) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
const sourceTabGroupId = this._animState.sourceTabGroupId;
|
|
70
|
-
const insertionIndex = (_b = this._animState.currentInsertionIndex) !== null && _b !== void 0 ? _b : this._tabs.length;
|
|
71
|
-
this._animState = null;
|
|
72
|
-
this._commitGroupMove(sourceTabGroupId, insertionIndex);
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
get panels() {
|
|
76
|
-
return this._tabs.map((_) => _.value.panel.id);
|
|
77
|
-
}
|
|
78
|
-
get size() {
|
|
79
|
-
return this._tabs.length;
|
|
80
|
-
}
|
|
81
|
-
get tabs() {
|
|
82
|
-
return this._tabs.map((_) => _.value);
|
|
83
|
-
}
|
|
84
|
-
get direction() {
|
|
85
|
-
return this._direction;
|
|
86
|
-
}
|
|
87
|
-
set direction(value) {
|
|
88
|
-
if (this._direction === value) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
this._direction = value;
|
|
92
|
-
this._tabsList.setAttribute('aria-orientation', value === 'vertical' ? 'vertical' : 'horizontal');
|
|
93
|
-
if (this._scrollbar) {
|
|
94
|
-
this._scrollbar.orientation = value;
|
|
95
|
-
}
|
|
96
|
-
removeClasses(this._tabsList, 'dv-horizontal', 'dv-vertical');
|
|
97
|
-
if (value === 'vertical') {
|
|
98
|
-
addClasses(this._tabsList, 'dv-tabs-container-vertical', 'dv-vertical');
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
removeClasses(this._tabsList, 'dv-tabs-container-vertical');
|
|
102
|
-
addClasses(this._tabsList, 'dv-horizontal');
|
|
103
|
-
}
|
|
104
|
-
for (const tab of this._tabs) {
|
|
105
|
-
tab.value.setDirection(value);
|
|
106
|
-
}
|
|
107
|
-
this._tabGroupManager.updateDirection();
|
|
108
|
-
}
|
|
109
|
-
constructor(group, accessor, options) {
|
|
110
|
-
super();
|
|
111
|
-
this.group = group;
|
|
112
|
-
this.accessor = accessor;
|
|
113
|
-
this._observerDisposable = new MutableDisposable();
|
|
114
|
-
this._scrollbar = null;
|
|
115
|
-
this._tabs = [];
|
|
116
|
-
this._tabMap = new Map();
|
|
117
|
-
this.selectedIndex = -1;
|
|
118
|
-
this._showTabsOverflowControl = false;
|
|
119
|
-
this._direction = 'horizontal';
|
|
120
|
-
this._animState = null;
|
|
121
|
-
this._pendingMarginCleanups = new Map();
|
|
122
|
-
this._pendingCollapse = false;
|
|
123
|
-
this._flipTransitionCleanup = null;
|
|
124
|
-
this._voidContainer = null;
|
|
125
|
-
this._voidContainerListeners = null;
|
|
126
|
-
this._extendedDropZone = null;
|
|
127
|
-
this._pointerInsideTabsList = false;
|
|
128
|
-
this._onTabDragStart = new Emitter();
|
|
129
|
-
this.onTabDragStart = this._onTabDragStart.event;
|
|
130
|
-
this._onDrop = new Emitter();
|
|
131
|
-
this.onDrop = this._onDrop.event;
|
|
132
|
-
this._onWillShowOverlay = new Emitter();
|
|
133
|
-
this.onWillShowOverlay = this._onWillShowOverlay.event;
|
|
134
|
-
this._onOverflowTabsChange = new Emitter();
|
|
135
|
-
this.onOverflowTabsChange = this._onOverflowTabsChange.event;
|
|
136
|
-
this._tabsList = document.createElement('div');
|
|
137
|
-
this._tabsList.className = 'dv-tabs-container';
|
|
138
|
-
// WAI-ARIA Tabs pattern: the strip of tabs is the tablist.
|
|
139
|
-
this._tabsList.setAttribute('role', 'tablist');
|
|
140
|
-
this._tabsList.setAttribute('aria-orientation', this._direction === 'vertical' ? 'vertical' : 'horizontal');
|
|
141
|
-
this.showTabsOverflowControl = options.showTabsOverflowControl;
|
|
142
|
-
if (accessor.options.scrollbars === 'native') {
|
|
143
|
-
this._element = this._tabsList;
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
this._scrollbar = new Scrollbar(this._tabsList);
|
|
147
|
-
this._scrollbar.orientation = this.direction;
|
|
148
|
-
this._element = this._scrollbar.element;
|
|
149
|
-
this.addDisposables(this._scrollbar);
|
|
150
|
-
}
|
|
151
|
-
this._tabGroupManager = new TabGroupManager({
|
|
152
|
-
group: this.group,
|
|
153
|
-
accessor: this.accessor,
|
|
154
|
-
tabsList: this._tabsList,
|
|
155
|
-
getTabs: () => this._tabs,
|
|
156
|
-
getTabMap: () => this._tabMap,
|
|
157
|
-
getDirection: () => this._direction,
|
|
158
|
-
}, {
|
|
159
|
-
onChipContextMenu: (tabGroup, event) => {
|
|
160
|
-
var _a;
|
|
161
|
-
(_a = this.accessor.contextMenuService) === null || _a === void 0 ? void 0 : _a.showForChip(tabGroup, this.group, event);
|
|
162
|
-
},
|
|
163
|
-
onChipDragStart: (tabGroup, chip, event) => {
|
|
164
|
-
this._handleChipDragStart(tabGroup, chip, event);
|
|
165
|
-
},
|
|
166
|
-
onChipDragEnd: () => {
|
|
167
|
-
// HTML5 chip dragend (incl. cancels). The Html5DragSource
|
|
168
|
-
// owns the listener on the chip element, so this fires
|
|
169
|
-
// even if the chip was detached cross-group — the
|
|
170
|
-
// element keeps its listeners until the source is
|
|
171
|
-
// disposed. resetDragAnimation is a no-op after a
|
|
172
|
-
// successful drop (anim state already null) thanks to
|
|
173
|
-
// the gating inside it.
|
|
174
|
-
this.resetDragAnimation();
|
|
175
|
-
},
|
|
176
|
-
onChipDrop: (tabGroup, event) => {
|
|
177
|
-
this._handleChipDrop(tabGroup, event);
|
|
178
|
-
},
|
|
179
|
-
});
|
|
180
|
-
this.addDisposables(this._onOverflowTabsChange, this._observerDisposable, this._onWillShowOverlay, this._onDrop, this._onTabDragStart, {
|
|
181
|
-
dispose: () => {
|
|
182
|
-
var _a;
|
|
183
|
-
(_a = this._flipTransitionCleanup) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
// Pointer-side cleanup: when any pointer drag ends, tear
|
|
187
|
-
// down smooth-reorder anim state the dragover bridge may
|
|
188
|
-
// have installed. The chip's pointer drag source handles
|
|
189
|
-
// its own transfer payload + iframe-shield cleanup.
|
|
190
|
-
PointerDragController.getInstance().onDragEnd(() => {
|
|
191
|
-
this._pointerInsideTabsList = false;
|
|
192
|
-
this.resetDragAnimation();
|
|
193
|
-
}),
|
|
194
|
-
// Pointer-event mirror of the HTML5 dragover / dragleave handlers
|
|
195
|
-
// below. Drives smooth-reorder for `dndStrategy: 'pointer'` and
|
|
196
|
-
// for touch drags in `'auto'`.
|
|
197
|
-
PointerDragController.getInstance().onDragMove((e) => {
|
|
198
|
-
this._handlePointerDragMove(e.clientX, e.clientY);
|
|
199
|
-
}), addDisposableListener(this.element, 'pointerdown', (event) => {
|
|
200
|
-
if (event.defaultPrevented) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
const isLeftClick = event.button === 0;
|
|
204
|
-
if (isLeftClick) {
|
|
205
|
-
this.accessor.doSetGroupActive(this.group);
|
|
206
|
-
}
|
|
207
|
-
}),
|
|
208
|
-
// Trackpad / wheel forwarding. The strip scrolls along its own
|
|
209
|
-
// axis (x for horizontal headers, y for vertical), so deltaY
|
|
210
|
-
// from a plain mouse wheel maps onto the strip's axis too —
|
|
211
|
-
// this gives the VS Code-style "scroll over tab bar to page
|
|
212
|
-
// through tabs" feel. We only consume the event when the strip
|
|
213
|
-
// is actually overflowing in the direction the user wheeled in,
|
|
214
|
-
// so a wheel at the edge of a non-overflowing strip still
|
|
215
|
-
// bubbles up and scrolls the page. `{ passive: false }` is
|
|
216
|
-
// required because we call preventDefault().
|
|
217
|
-
addDisposableListener(this._tabsList, 'wheel', (event) => {
|
|
218
|
-
const isVertical = this._direction === 'vertical';
|
|
219
|
-
const primary = isVertical
|
|
220
|
-
? event.deltaY || event.deltaX
|
|
221
|
-
: event.deltaX || event.deltaY;
|
|
222
|
-
if (primary === 0) {
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
const max = isVertical
|
|
226
|
-
? this._tabsList.scrollHeight -
|
|
227
|
-
this._tabsList.clientHeight
|
|
228
|
-
: this._tabsList.scrollWidth -
|
|
229
|
-
this._tabsList.clientWidth;
|
|
230
|
-
if (max <= 0) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
const current = isVertical
|
|
234
|
-
? this._tabsList.scrollTop
|
|
235
|
-
: this._tabsList.scrollLeft;
|
|
236
|
-
// At the edge in the wheel direction: let the page
|
|
237
|
-
// scroll instead of trapping the gesture.
|
|
238
|
-
if ((primary < 0 && current <= 0) ||
|
|
239
|
-
(primary > 0 && current >= max)) {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
event.preventDefault();
|
|
243
|
-
// Custom-scrollbar mode wraps the tabs list and installs
|
|
244
|
-
// its own wheel listener that rewrites scrollLeft from a
|
|
245
|
-
// deltaY-only tracker. Without stopPropagation that
|
|
246
|
-
// handler would clobber our deltaX-aware update.
|
|
247
|
-
event.stopPropagation();
|
|
248
|
-
if (isVertical) {
|
|
249
|
-
this._tabsList.scrollTop = current + primary;
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
this._tabsList.scrollLeft = current + primary;
|
|
253
|
-
}
|
|
254
|
-
}, { passive: false }),
|
|
255
|
-
// WAI-ARIA Tabs keyboard pattern: arrow keys move the roving
|
|
256
|
-
// focus along the strip, Home/End jump to the ends, and
|
|
257
|
-
// Enter/Space activate the focused tab (manual activation, so
|
|
258
|
-
// arrowing through tabs doesn't switch panels until committed).
|
|
259
|
-
addDisposableListener(this._tabsList, 'keydown', (event) => {
|
|
260
|
-
this._onKeyDown(event);
|
|
261
|
-
}), addDisposableListener(this._tabsList, 'dragover', (event) => {
|
|
262
|
-
if (this._processDragOver(event.clientX)) {
|
|
263
|
-
// Allow `drop` to fire on the tabs list container.
|
|
264
|
-
event.preventDefault();
|
|
265
|
-
}
|
|
266
|
-
}, true), addDisposableListener(this._tabsList, 'dragleave', (event) => {
|
|
267
|
-
this._processDragLeave(event.relatedTarget);
|
|
268
|
-
}, true), addDisposableListener(this._tabsList, 'dragend', () => {
|
|
269
|
-
this.resetDragAnimation();
|
|
270
|
-
}), addDisposableListener(this._tabsList, 'drop', (event) => {
|
|
271
|
-
var _a, _b, _c;
|
|
272
|
-
if (!this._animState ||
|
|
273
|
-
this._animState.currentInsertionIndex === null) {
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
// In non-smooth mode only handle group drags here;
|
|
277
|
-
// individual tab drops are handled by tab Droptargets.
|
|
278
|
-
if (((_a = this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) !==
|
|
279
|
-
'smooth' &&
|
|
280
|
-
!this._animState.sourceTabGroupId) {
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
event.stopPropagation();
|
|
284
|
-
event.preventDefault();
|
|
285
|
-
// The capturing stopPropagation above prevents the
|
|
286
|
-
// individual tab's Droptarget.onDrop from firing, so
|
|
287
|
-
// the anchor overlay won't be cleared by that path.
|
|
288
|
-
// Clear it explicitly here before processing the drop.
|
|
289
|
-
(_c = (_b = this.group.model.dropTargetContainer) === null || _b === void 0 ? void 0 : _b.model) === null || _c === void 0 ? void 0 : _c.clear();
|
|
290
|
-
const animState = this._animState;
|
|
291
|
-
this._animState = null;
|
|
292
|
-
this._pendingCollapse = false;
|
|
293
|
-
// Handle group drag (entire group repositioned)
|
|
294
|
-
if (animState.sourceTabGroupId) {
|
|
295
|
-
this._commitGroupMove(animState.sourceTabGroupId, animState.currentInsertionIndex);
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
const insertionIndex = animState.currentInsertionIndex;
|
|
299
|
-
const sourceIndex = animState.sourceIndex;
|
|
300
|
-
const adjustedIndex = insertionIndex -
|
|
301
|
-
(sourceIndex !== -1 && sourceIndex < insertionIndex
|
|
302
|
-
? 1
|
|
303
|
-
: 0);
|
|
304
|
-
const sourceCurrentGroup = this.group.model.getTabGroupForPanel(animState.sourceTabId);
|
|
305
|
-
if (adjustedIndex === sourceIndex &&
|
|
306
|
-
!animState.targetTabGroupId &&
|
|
307
|
-
!sourceCurrentGroup) {
|
|
308
|
-
this._uncollapsSourceTab(animState.sourceTabId);
|
|
309
|
-
this.resetTabTransforms();
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
this._uncollapsSourceTab(animState.sourceTabId);
|
|
313
|
-
const firstPositions = this.snapshotTabPositions();
|
|
314
|
-
this.resetTabTransforms();
|
|
315
|
-
this._onDrop.fire({
|
|
316
|
-
event,
|
|
317
|
-
index: adjustedIndex,
|
|
318
|
-
targetTabGroupId: animState.targetTabGroupId,
|
|
319
|
-
});
|
|
320
|
-
this.runFlipAnimation(firstPositions, animState.sourceTabId, animState.sourceIndex === -1, {
|
|
321
|
-
from: Math.min(sourceIndex, adjustedIndex),
|
|
322
|
-
to: Math.max(sourceIndex, adjustedIndex),
|
|
323
|
-
});
|
|
324
|
-
}, true), Disposable.from(() => {
|
|
325
|
-
var _a;
|
|
326
|
-
(_a = this._voidContainerListeners) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
327
|
-
this.resetDragAnimation();
|
|
328
|
-
this._tabGroupManager.disposeAll();
|
|
329
|
-
for (const { value, disposable } of this._tabs) {
|
|
330
|
-
disposable.dispose();
|
|
331
|
-
value.dispose();
|
|
332
|
-
}
|
|
333
|
-
this._tabs = [];
|
|
334
|
-
this._tabMap.clear();
|
|
335
|
-
}));
|
|
336
|
-
}
|
|
337
|
-
indexOf(id) {
|
|
338
|
-
return this._tabs.findIndex((tab) => tab.value.panel.id === id);
|
|
339
|
-
}
|
|
340
|
-
/** DOM id of the tab element for a panel — for the tabpanel's `aria-labelledby`. */
|
|
341
|
-
getTabId(panelId) {
|
|
342
|
-
var _a;
|
|
343
|
-
return (_a = this._tabMap.get(panelId)) === null || _a === void 0 ? void 0 : _a.value.element.id;
|
|
344
|
-
}
|
|
345
|
-
isActive(tab) {
|
|
346
|
-
return (this.selectedIndex > -1 &&
|
|
347
|
-
this._tabs[this.selectedIndex].value === tab);
|
|
348
|
-
}
|
|
349
|
-
_onKeyDown(event) {
|
|
350
|
-
// Only handle when a tab element itself is focused — never hijack keys
|
|
351
|
-
// typed inside a custom tab renderer's own controls (inputs etc.).
|
|
352
|
-
const index = this._tabs.findIndex((tab) => tab.value.element === event.target);
|
|
353
|
-
if (index === -1) {
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
const isVertical = this._direction === 'vertical';
|
|
357
|
-
const nextKey = isVertical ? 'ArrowDown' : 'ArrowRight';
|
|
358
|
-
const prevKey = isVertical ? 'ArrowUp' : 'ArrowLeft';
|
|
359
|
-
const last = this._tabs.length - 1;
|
|
360
|
-
switch (event.key) {
|
|
361
|
-
case nextKey:
|
|
362
|
-
event.preventDefault();
|
|
363
|
-
this._focusTab(Math.min(index + 1, last));
|
|
364
|
-
break;
|
|
365
|
-
case prevKey:
|
|
366
|
-
event.preventDefault();
|
|
367
|
-
this._focusTab(Math.max(index - 1, 0));
|
|
368
|
-
break;
|
|
369
|
-
case 'Home':
|
|
370
|
-
event.preventDefault();
|
|
371
|
-
this._focusTab(0);
|
|
372
|
-
break;
|
|
373
|
-
case 'End':
|
|
374
|
-
event.preventDefault();
|
|
375
|
-
this._focusTab(last);
|
|
376
|
-
break;
|
|
377
|
-
case 'Enter':
|
|
378
|
-
case ' ':
|
|
379
|
-
// Manual activation of the focused tab.
|
|
380
|
-
event.preventDefault();
|
|
381
|
-
this.accessor.withOrigin('user', () => this._tabs[index].value.panel.api.setActive());
|
|
382
|
-
break;
|
|
383
|
-
case 'Delete':
|
|
384
|
-
case 'Backspace':
|
|
385
|
-
// Close the focused tab (Backspace covers macOS, where the
|
|
386
|
-
// primary delete key reports as Backspace).
|
|
387
|
-
event.preventDefault();
|
|
388
|
-
this._closeTab(index);
|
|
389
|
-
break;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Close the tab at `index` and move roving focus to a neighbouring tab so
|
|
394
|
-
* keyboard focus stays in the tablist.
|
|
395
|
-
*/
|
|
396
|
-
_closeTab(index) {
|
|
397
|
-
var _a, _b, _c, _d, _e;
|
|
398
|
-
const tab = (_a = this._tabs[index]) === null || _a === void 0 ? void 0 : _a.value;
|
|
399
|
-
if (!tab) {
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
// Resolve the post-close focus target before closing mutates the list:
|
|
403
|
-
// prefer the next tab, otherwise the previous.
|
|
404
|
-
const neighbourId = (_e = ((_c = (_b = this._tabs[index + 1]) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : (_d = this._tabs[index - 1]) === null || _d === void 0 ? void 0 : _d.value)) === null || _e === void 0 ? void 0 : _e.panel.id;
|
|
405
|
-
tab.panel.api.close();
|
|
406
|
-
if (neighbourId !== undefined) {
|
|
407
|
-
const nextIndex = this._tabs.findIndex((t) => t.value.panel.id === neighbourId);
|
|
408
|
-
if (nextIndex > -1) {
|
|
409
|
-
this._focusTab(nextIndex);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
/** Move the roving focus to the tab at `index` (updates tabindex + DOM focus). */
|
|
414
|
-
_focusTab(index) {
|
|
415
|
-
for (let i = 0; i < this._tabs.length; i++) {
|
|
416
|
-
this._tabs[i].value.element.tabIndex = i === index ? 0 : -1;
|
|
417
|
-
}
|
|
418
|
-
this._tabs[index].value.element.focus();
|
|
419
|
-
}
|
|
420
|
-
/** Move DOM focus to the active tab — the entry point into the tablist. */
|
|
421
|
-
focusActiveTab() {
|
|
422
|
-
var _a;
|
|
423
|
-
if (this._tabs.length === 0) {
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
const activeId = (_a = this.group.activePanel) === null || _a === void 0 ? void 0 : _a.id;
|
|
427
|
-
const activeIndex = activeId
|
|
428
|
-
? this._tabs.findIndex((t) => t.value.panel.id === activeId)
|
|
429
|
-
: -1;
|
|
430
|
-
this._focusTab(activeIndex > -1 ? activeIndex : 0);
|
|
431
|
-
}
|
|
432
|
-
setActivePanel(panel) {
|
|
433
|
-
const isVertical = this._direction === 'vertical';
|
|
434
|
-
let running = 0;
|
|
435
|
-
for (const tab of this._tabs) {
|
|
436
|
-
const isActivePanel = panel.id === tab.value.panel.id;
|
|
437
|
-
tab.value.setActive(isActivePanel);
|
|
438
|
-
if (isActivePanel) {
|
|
439
|
-
const element = tab.value.element;
|
|
440
|
-
const parentElement = element.parentElement;
|
|
441
|
-
if (isVertical) {
|
|
442
|
-
if (running < parentElement.scrollTop ||
|
|
443
|
-
running + element.clientHeight >
|
|
444
|
-
parentElement.scrollTop + parentElement.clientHeight) {
|
|
445
|
-
parentElement.scrollTop = running;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
else if (running < parentElement.scrollLeft ||
|
|
449
|
-
running + element.clientWidth >
|
|
450
|
-
parentElement.scrollLeft + parentElement.clientWidth) {
|
|
451
|
-
parentElement.scrollLeft = running;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
running += isVertical
|
|
455
|
-
? tab.value.element.clientHeight
|
|
456
|
-
: tab.value.element.clientWidth;
|
|
457
|
-
}
|
|
458
|
-
// Reposition underlines so the wrap-around follows the new active tab
|
|
459
|
-
if (this._tabGroupManager.groupUnderlines.size > 0) {
|
|
460
|
-
this._tabGroupManager.positionUnderlines();
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
openPanel(panel, index = this._tabs.length) {
|
|
464
|
-
if (this._tabMap.has(panel.id)) {
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
const tab = new Tab(panel, this.accessor, this.group);
|
|
468
|
-
tab.setContent(panel.view.tab);
|
|
469
|
-
if (this._direction !== 'horizontal') {
|
|
470
|
-
tab.setDirection(this._direction);
|
|
471
|
-
}
|
|
472
|
-
const disposable = new CompositeDisposable(tab.onDragStart((event) => {
|
|
473
|
-
var _a;
|
|
474
|
-
this._onTabDragStart.fire({ nativeEvent: event, panel });
|
|
475
|
-
// Both HTML5 and pointer drags initialize _animState. Cleanup
|
|
476
|
-
// is wired in both paths: HTML5 via dragend/drop on _tabsList,
|
|
477
|
-
// pointer via PointerDragController.onDragEnd subscriptions.
|
|
478
|
-
if (((_a = this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) === 'smooth') {
|
|
479
|
-
const tabWidth = tab.element.getBoundingClientRect().width;
|
|
480
|
-
const sourceIndex = this._tabs.findIndex((x) => x.value === tab);
|
|
481
|
-
this._animState = {
|
|
482
|
-
sourceTabId: panel.id,
|
|
483
|
-
sourceIndex,
|
|
484
|
-
tabPositions: this.snapshotTabPositions(),
|
|
485
|
-
chipPositions: this._tabGroupManager.snapshotChipWidths(),
|
|
486
|
-
currentInsertionIndex: null,
|
|
487
|
-
targetTabGroupId: null,
|
|
488
|
-
sourceTabGroupId: null,
|
|
489
|
-
sourceGroupPanelIds: null,
|
|
490
|
-
sourceChipWidth: 0,
|
|
491
|
-
cursorOffsetFromDragLeft: tabWidth / 2,
|
|
492
|
-
sourceGapWidth: tabWidth,
|
|
493
|
-
containerLeft: this._tabsList.getBoundingClientRect().left,
|
|
494
|
-
};
|
|
495
|
-
// Collapse the source tab after the browser captures the
|
|
496
|
-
// drag image, then open the gap at the source position in
|
|
497
|
-
// the same paint frame — no visual jump.
|
|
498
|
-
// Both collapse and gap must be instant (no transition).
|
|
499
|
-
this._pendingCollapse = true;
|
|
500
|
-
requestAnimationFrame(() => {
|
|
501
|
-
var _a;
|
|
502
|
-
var _b;
|
|
503
|
-
this._pendingCollapse = false;
|
|
504
|
-
if (!this._animState) {
|
|
505
|
-
return;
|
|
506
|
-
}
|
|
507
|
-
// Collapse source tab instantly (no transition)
|
|
508
|
-
tab.element.style.transition = 'none';
|
|
509
|
-
toggleClass(tab.element, 'dv-tab--dragging', true);
|
|
510
|
-
void tab.element.offsetHeight; // force reflow
|
|
511
|
-
(_a = (_b = this._animState).currentInsertionIndex) !== null && _a !== void 0 ? _a : (_b.currentInsertionIndex = sourceIndex);
|
|
512
|
-
// Apply gap with transitions disabled on the target
|
|
513
|
-
this.applyDragOverTransforms(true);
|
|
514
|
-
// Re-enable transitions for subsequent moves
|
|
515
|
-
tab.element.style.removeProperty('transition');
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
}), tab.onTabClick((event) => {
|
|
519
|
-
if (event.defaultPrevented) {
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
if (this.group.api.location.type !== 'edge') {
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
if (this.group.activePanel === panel) {
|
|
526
|
-
// Clicking the active tab toggles expansion
|
|
527
|
-
if (this.group.api.isCollapsed()) {
|
|
528
|
-
this.group.api.expand();
|
|
529
|
-
}
|
|
530
|
-
else {
|
|
531
|
-
this.group.api.collapse();
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
// Clicking a non-active tab switches the active tab.
|
|
536
|
-
// If the group is collapsed, also expand it.
|
|
537
|
-
this.group.model.openPanel(panel);
|
|
538
|
-
if (this.group.api.isCollapsed()) {
|
|
539
|
-
this.group.api.expand();
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
}), tab.onPointerDown((event) => {
|
|
543
|
-
if (event.defaultPrevented) {
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
|
|
547
|
-
const isFloatingWithOnePanel = this.group.api.location.type === 'floating' &&
|
|
548
|
-
this.size === 1;
|
|
549
|
-
if (isFloatingGroupsEnabled &&
|
|
550
|
-
!isFloatingWithOnePanel &&
|
|
551
|
-
event.shiftKey) {
|
|
552
|
-
event.preventDefault();
|
|
553
|
-
const panel = this.accessor.getGroupPanel(tab.panel.id);
|
|
554
|
-
const { top, left } = tab.element.getBoundingClientRect();
|
|
555
|
-
const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
|
|
556
|
-
this.accessor.addFloatingGroup(panel, {
|
|
557
|
-
x: left - rootLeft,
|
|
558
|
-
y: top - rootTop,
|
|
559
|
-
inDragMode: true,
|
|
560
|
-
});
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
// Edge groups are skipped here: all their tab interaction
|
|
564
|
-
// is handled by onTabClick to avoid race conditions with
|
|
565
|
-
// active panel state.
|
|
566
|
-
if (event.button === 0 &&
|
|
567
|
-
this.group.api.location.type !== 'edge' &&
|
|
568
|
-
this.group.activePanel !== panel) {
|
|
569
|
-
this.group.model.openPanel(panel);
|
|
570
|
-
}
|
|
571
|
-
}), tab.onDrop((event) => {
|
|
572
|
-
var _a, _b, _c, _d;
|
|
573
|
-
const animState = this._animState;
|
|
574
|
-
this._animState = null;
|
|
575
|
-
this._pendingCollapse = false;
|
|
576
|
-
const tabIndex = this._tabs.findIndex((x) => x.value === tab);
|
|
577
|
-
if (animState) {
|
|
578
|
-
const dropIndex = event.position === 'right' ? tabIndex + 1 : tabIndex;
|
|
579
|
-
if (animState.sourceTabGroupId) {
|
|
580
|
-
this._commitGroupMove(animState.sourceTabGroupId, (_a = animState.currentInsertionIndex) !== null && _a !== void 0 ? _a : dropIndex);
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
this._uncollapsSourceTab(animState.sourceTabId);
|
|
584
|
-
const firstPositions = this.snapshotTabPositions();
|
|
585
|
-
this.resetTabTransforms();
|
|
586
|
-
this._onDrop.fire({
|
|
587
|
-
event: event.nativeEvent,
|
|
588
|
-
index: dropIndex,
|
|
589
|
-
targetTabGroupId: animState.targetTabGroupId,
|
|
590
|
-
});
|
|
591
|
-
if (((_b = this.accessor.options.theme) === null || _b === void 0 ? void 0 : _b.tabAnimation) === 'smooth') {
|
|
592
|
-
this.runFlipAnimation(firstPositions, animState.sourceTabId, animState.sourceIndex === -1, animState.sourceIndex === -1
|
|
593
|
-
? undefined
|
|
594
|
-
: {
|
|
595
|
-
from: Math.min(animState.sourceIndex, dropIndex),
|
|
596
|
-
to: Math.max(animState.sourceIndex, dropIndex),
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
else {
|
|
601
|
-
// Compute insertion index based on which half of the tab
|
|
602
|
-
// the pointer is over, then adjust for same-group removal:
|
|
603
|
-
// when the source tab sits before the insertion point,
|
|
604
|
-
// removing it shifts all subsequent indices down by one.
|
|
605
|
-
const afterPosition = this._direction === 'vertical' ? 'bottom' : 'right';
|
|
606
|
-
const insertionIndex = event.position === afterPosition
|
|
607
|
-
? tabIndex + 1
|
|
608
|
-
: tabIndex;
|
|
609
|
-
const data = getPanelData();
|
|
610
|
-
const sourceIndex = data
|
|
611
|
-
? this._tabs.findIndex((x) => x.value.panel.id === data.panelId)
|
|
612
|
-
: -1;
|
|
613
|
-
const adjustedIndex = insertionIndex -
|
|
614
|
-
(sourceIndex !== -1 && sourceIndex < insertionIndex
|
|
615
|
-
? 1
|
|
616
|
-
: 0);
|
|
617
|
-
const targetTabGroupId = (_d = (_c = this.group.model.getTabGroupForPanel(tab.panel.id)) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : null;
|
|
618
|
-
this._onDrop.fire({
|
|
619
|
-
event: event.nativeEvent,
|
|
620
|
-
index: adjustedIndex,
|
|
621
|
-
targetTabGroupId,
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
}), tab.onWillShowOverlay((event) => {
|
|
625
|
-
this._onWillShowOverlay.fire(new DockviewWillShowOverlayLocationEvent(event, {
|
|
626
|
-
kind: 'tab',
|
|
627
|
-
panel: this.group.activePanel,
|
|
628
|
-
api: this.accessor.api,
|
|
629
|
-
group: this.group,
|
|
630
|
-
getData: getPanelData,
|
|
631
|
-
}));
|
|
632
|
-
}));
|
|
633
|
-
const value = { value: tab, disposable };
|
|
634
|
-
this.addTab(value, index);
|
|
635
|
-
// A new tab may have been inserted between a chip and its
|
|
636
|
-
// group's first tab — reposition all chips to stay correct.
|
|
637
|
-
this._tabGroupManager.positionAllChips();
|
|
638
|
-
// If a tab was added during active drag, refresh positions
|
|
639
|
-
if (this._animState) {
|
|
640
|
-
this._animState.tabPositions = this.snapshotTabPositions();
|
|
641
|
-
this._animState.chipPositions =
|
|
642
|
-
this._tabGroupManager.snapshotChipWidths();
|
|
643
|
-
this.applyDragOverTransforms();
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
delete(id) {
|
|
647
|
-
var _a;
|
|
648
|
-
if (((_a = this._animState) === null || _a === void 0 ? void 0 : _a.sourceTabId) === id) {
|
|
649
|
-
this.resetTabTransforms();
|
|
650
|
-
this._animState = null;
|
|
651
|
-
}
|
|
652
|
-
// Force-clean any pending transitionend listener
|
|
653
|
-
this._tabGroupManager.cleanupTransition(id);
|
|
654
|
-
const index = this.indexOf(id);
|
|
655
|
-
const tabToRemove = this._tabs.splice(index, 1)[0];
|
|
656
|
-
this._tabMap.delete(id);
|
|
657
|
-
if (tabToRemove) {
|
|
658
|
-
const { value, disposable } = tabToRemove;
|
|
659
|
-
disposable.dispose();
|
|
660
|
-
value.dispose();
|
|
661
|
-
value.element.remove();
|
|
662
|
-
}
|
|
663
|
-
// If a non-source tab was removed during active drag, refresh positions
|
|
664
|
-
if (this._animState) {
|
|
665
|
-
this._animState.tabPositions = this.snapshotTabPositions();
|
|
666
|
-
this._animState.chipPositions =
|
|
667
|
-
this._tabGroupManager.snapshotChipWidths();
|
|
668
|
-
this.applyDragOverTransforms();
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
addTab(tab, index = this._tabs.length) {
|
|
672
|
-
if (index < 0 || index > this._tabs.length) {
|
|
673
|
-
throw new Error('invalid location');
|
|
674
|
-
}
|
|
675
|
-
// Use the tab element at `index` as the reference node rather than
|
|
676
|
-
// `children[index]`, because `_tabsList` may contain non-tab children
|
|
677
|
-
// (e.g. group chips, underlines) that shift the DOM indices.
|
|
678
|
-
const refNode = index < this._tabs.length ? this._tabs[index].value.element : null;
|
|
679
|
-
this._tabsList.insertBefore(tab.value.element, refNode);
|
|
680
|
-
this._tabs = [
|
|
681
|
-
...this._tabs.slice(0, index),
|
|
682
|
-
tab,
|
|
683
|
-
...this._tabs.slice(index),
|
|
684
|
-
];
|
|
685
|
-
this._tabMap.set(tab.value.panel.id, tab);
|
|
686
|
-
if (this.selectedIndex < 0) {
|
|
687
|
-
this.selectedIndex = index;
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
toggleDropdown(options) {
|
|
691
|
-
if (options.reset) {
|
|
692
|
-
this._onOverflowTabsChange.fire({
|
|
693
|
-
tabs: [],
|
|
694
|
-
tabGroups: [],
|
|
695
|
-
reset: true,
|
|
696
|
-
});
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
const tabs = this._tabs
|
|
700
|
-
.filter((tab) => !isChildEntirelyVisibleWithinParent(tab.value.element, this._tabsList))
|
|
701
|
-
.map((x) => x.value.panel.id);
|
|
702
|
-
// Detect tab groups whose chip is clipped or whose tabs are all
|
|
703
|
-
// in the overflow set (e.g. collapsed groups scrolled out of view).
|
|
704
|
-
const overflowTabSet = new Set(tabs);
|
|
705
|
-
const tabGroups = [];
|
|
706
|
-
for (const tg of this.group.model.getTabGroups()) {
|
|
707
|
-
const chipEntry = this._tabGroupManager.chipRenderers.get(tg.id);
|
|
708
|
-
const chipClipped = chipEntry &&
|
|
709
|
-
!isChildEntirelyVisibleWithinParent(chipEntry.chip.element, this._tabsList);
|
|
710
|
-
// A group is in overflow if its chip is clipped OR all its
|
|
711
|
-
// visible tabs are in the overflow set.
|
|
712
|
-
const allTabsOverflow = tg.panelIds.length > 0 &&
|
|
713
|
-
tg.panelIds.every((pid) => overflowTabSet.has(pid));
|
|
714
|
-
if (chipClipped || allTabsOverflow) {
|
|
715
|
-
tabGroups.push(tg.id);
|
|
716
|
-
// For collapsed groups whose chip is clipped, ensure all
|
|
717
|
-
// member tabs are included in the overflow list so they
|
|
718
|
-
// appear in the dropdown.
|
|
719
|
-
if (tg.collapsed) {
|
|
720
|
-
for (const pid of tg.panelIds) {
|
|
721
|
-
if (!overflowTabSet.has(pid)) {
|
|
722
|
-
overflowTabSet.add(pid);
|
|
723
|
-
tabs.push(pid);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
this._onOverflowTabsChange.fire({ tabs, tabGroups, reset: false });
|
|
730
|
-
}
|
|
731
|
-
updateDragAndDropState() {
|
|
732
|
-
for (const tab of this._tabs) {
|
|
733
|
-
tab.value.updateDragAndDropState();
|
|
734
|
-
}
|
|
735
|
-
this._tabGroupManager.updateDragAndDropState();
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* Synchronize chip elements and CSS classes for all tab groups
|
|
739
|
-
* in the parent group model. Call after any tab group mutation.
|
|
740
|
-
*/
|
|
741
|
-
updateTabGroups() {
|
|
742
|
-
this._tabGroupManager.update();
|
|
743
|
-
}
|
|
744
|
-
refreshTabGroupAccent() {
|
|
745
|
-
this._tabGroupManager.refreshAccents();
|
|
746
|
-
}
|
|
747
|
-
/**
|
|
748
|
-
* Tabs-list-specific side effects of a chip drag start. The chip's
|
|
749
|
-
* drag sources (constructed by `TabGroupManager`) own the transfer
|
|
750
|
-
* payload, iframe shielding, dataTransfer setup, and the HTML5 drag
|
|
751
|
-
* image. This method just sets up the smooth-reorder anim state and
|
|
752
|
-
* collapses the source-group tabs in the tabs list.
|
|
753
|
-
*/
|
|
754
|
-
_handleChipDragStart(tabGroup, chip, event) {
|
|
755
|
-
var _a;
|
|
756
|
-
const firstPanelId = tabGroup.panelIds[0];
|
|
757
|
-
const firstIdx = firstPanelId
|
|
758
|
-
? this._tabs.findIndex((t) => t.value.panel.id === firstPanelId)
|
|
759
|
-
: -1;
|
|
760
|
-
const chipRect = chip.element.getBoundingClientRect();
|
|
761
|
-
// Compute total group width (chip + all tabs)
|
|
762
|
-
let groupGapWidth = chipRect.width;
|
|
763
|
-
for (const pid of tabGroup.panelIds) {
|
|
764
|
-
const tabEntry = this._tabMap.get(pid);
|
|
765
|
-
if (tabEntry) {
|
|
766
|
-
groupGapWidth +=
|
|
767
|
-
tabEntry.value.element.getBoundingClientRect().width;
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
this._animState = {
|
|
771
|
-
sourceTabId: '',
|
|
772
|
-
sourceIndex: firstIdx,
|
|
773
|
-
tabPositions: this.snapshotTabPositions(),
|
|
774
|
-
chipPositions: this._tabGroupManager.snapshotChipWidths(),
|
|
775
|
-
currentInsertionIndex: null,
|
|
776
|
-
targetTabGroupId: null,
|
|
777
|
-
sourceTabGroupId: tabGroup.id,
|
|
778
|
-
sourceGroupPanelIds: new Set(tabGroup.panelIds),
|
|
779
|
-
sourceChipWidth: chipRect.width,
|
|
780
|
-
cursorOffsetFromDragLeft: event.clientX - chipRect.left,
|
|
781
|
-
sourceGapWidth: groupGapWidth,
|
|
782
|
-
containerLeft: this._tabsList.getBoundingClientRect().left,
|
|
783
|
-
};
|
|
784
|
-
if (((_a = this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) !== 'smooth') {
|
|
785
|
-
return;
|
|
786
|
-
}
|
|
787
|
-
// Collapse group tabs + chip after the browser captures the drag
|
|
788
|
-
// image, then open the gap at the source position — all instant
|
|
789
|
-
// (no transitions).
|
|
790
|
-
const groupPanelIds = new Set(tabGroup.panelIds);
|
|
791
|
-
this._pendingCollapse = true;
|
|
792
|
-
requestAnimationFrame(() => {
|
|
793
|
-
var _a;
|
|
794
|
-
var _b;
|
|
795
|
-
this._pendingCollapse = false;
|
|
796
|
-
if (!this._animState) {
|
|
797
|
-
return;
|
|
798
|
-
}
|
|
799
|
-
// Collapse all group tabs instantly
|
|
800
|
-
for (const t of this._tabs) {
|
|
801
|
-
if (groupPanelIds.has(t.value.panel.id)) {
|
|
802
|
-
t.value.element.style.transition = 'none';
|
|
803
|
-
toggleClass(t.value.element, 'dv-tab--dragging', true);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
// Collapse the group chip instantly
|
|
807
|
-
const chipEntry = this._tabGroupManager.chipRenderers.get(tabGroup.id);
|
|
808
|
-
if (chipEntry) {
|
|
809
|
-
chipEntry.chip.element.style.transition = 'none';
|
|
810
|
-
toggleClass(chipEntry.chip.element, 'dv-tab-group-chip--dragging', true);
|
|
811
|
-
}
|
|
812
|
-
// Single reflow for the entire batch
|
|
813
|
-
void this._tabsList.offsetHeight;
|
|
814
|
-
const underline = this._tabGroupManager.groupUnderlines.get(tabGroup.id);
|
|
815
|
-
if (underline) {
|
|
816
|
-
underline.style.display = 'none';
|
|
817
|
-
}
|
|
818
|
-
(_a = (_b = this._animState).currentInsertionIndex) !== null && _a !== void 0 ? _a : (_b.currentInsertionIndex = firstIdx);
|
|
819
|
-
this.applyDragOverTransforms(true);
|
|
820
|
-
for (const t of this._tabs) {
|
|
821
|
-
if (groupPanelIds.has(t.value.panel.id)) {
|
|
822
|
-
t.value.element.style.removeProperty('transition');
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
if (chipEntry) {
|
|
826
|
-
chipEntry.chip.element.style.removeProperty('transition');
|
|
827
|
-
}
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
|
-
/**
|
|
831
|
-
* A drop on a tab group chip means "insert before this group". Resolve to
|
|
832
|
-
* the index of the group's first tab, adjusting for same-group removal
|
|
833
|
-
* (when the source tab is currently to the left of the target slot, its
|
|
834
|
-
* removal shifts the insertion index down by one). Always clears
|
|
835
|
-
* `targetTabGroupId` so the dropped tab lands outside the group.
|
|
836
|
-
*/
|
|
837
|
-
_handleChipDrop(tabGroup, event) {
|
|
838
|
-
const firstPanelId = tabGroup.panelIds[0];
|
|
839
|
-
if (!firstPanelId) {
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
const insertionIndex = this._tabs.findIndex((x) => x.value.panel.id === firstPanelId);
|
|
843
|
-
if (insertionIndex === -1) {
|
|
844
|
-
return;
|
|
845
|
-
}
|
|
846
|
-
const data = getPanelData();
|
|
847
|
-
const sourceIndex = (data === null || data === void 0 ? void 0 : data.groupId) === this.group.id && (data === null || data === void 0 ? void 0 : data.panelId)
|
|
848
|
-
? this._tabs.findIndex((x) => x.value.panel.id === data.panelId)
|
|
849
|
-
: -1;
|
|
850
|
-
const adjustedIndex = insertionIndex -
|
|
851
|
-
(sourceIndex !== -1 && sourceIndex < insertionIndex ? 1 : 0);
|
|
852
|
-
this._onDrop.fire({
|
|
853
|
-
event: event.nativeEvent,
|
|
854
|
-
index: adjustedIndex,
|
|
855
|
-
targetTabGroupId: null,
|
|
856
|
-
});
|
|
857
|
-
}
|
|
858
|
-
/**
|
|
859
|
-
* Sets the broader container that is part of the same logical drop surface
|
|
860
|
-
* as this tab list (e.g. the full header element). When a dragleave from
|
|
861
|
-
* the tabs list lands inside this container, `_animState` is preserved so
|
|
862
|
-
* that external dragover listeners can continue the animation.
|
|
863
|
-
*/
|
|
864
|
-
setExtendedDropZone(el) {
|
|
865
|
-
this._extendedDropZone = el;
|
|
866
|
-
}
|
|
867
|
-
/**
|
|
868
|
-
* Allows external elements (e.g. void container, left actions) to push an
|
|
869
|
-
* insertion index into the animation while the cursor is outside the tabs
|
|
870
|
-
* list itself. Pass `null` to clear the indicator.
|
|
871
|
-
*/
|
|
872
|
-
setExternalInsertionIndex(index) {
|
|
873
|
-
if (!this._animState) {
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
if (index === this._animState.currentInsertionIndex) {
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
this._animState.currentInsertionIndex = index;
|
|
880
|
-
this.applyDragOverTransforms();
|
|
881
|
-
}
|
|
882
|
-
/**
|
|
883
|
-
* Called when the drag cursor leaves the entire header area (not just the
|
|
884
|
-
* tabs list). Clears animation state for cross-group drags, which never
|
|
885
|
-
* receive a `dragend` event on this tab list.
|
|
886
|
-
*/
|
|
887
|
-
clearExternalAnimState() {
|
|
888
|
-
if (!this._animState) {
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
this.resetTabTransforms();
|
|
892
|
-
if (this._animState.sourceIndex === -1) {
|
|
893
|
-
this._animState = null;
|
|
894
|
-
}
|
|
895
|
-
else {
|
|
896
|
-
this._animState.currentInsertionIndex = null;
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
snapshotTabPositions() {
|
|
900
|
-
const positions = new Map();
|
|
901
|
-
for (const tab of this._tabs) {
|
|
902
|
-
positions.set(tab.value.panel.id, tab.value.element.getBoundingClientRect());
|
|
903
|
-
}
|
|
904
|
-
return positions;
|
|
905
|
-
}
|
|
906
|
-
getAverageTabWidth() {
|
|
907
|
-
if (this._tabs.length === 0) {
|
|
908
|
-
return 0;
|
|
909
|
-
}
|
|
910
|
-
const isVertical = this._direction === 'vertical';
|
|
911
|
-
let total = 0;
|
|
912
|
-
for (const tab of this._tabs) {
|
|
913
|
-
const rect = tab.value.element.getBoundingClientRect();
|
|
914
|
-
total += isVertical ? rect.height : rect.width;
|
|
915
|
-
}
|
|
916
|
-
return total / this._tabs.length;
|
|
917
|
-
}
|
|
918
|
-
/**
|
|
919
|
-
* Pointer-event entry point. The HTML5 path enters via the per-element
|
|
920
|
-
* `dragover` listener; this one hit-tests the global pointer-drag
|
|
921
|
-
* position against the tabs list and routes through the same shared
|
|
922
|
-
* `_processDragOver` / `_processDragLeave` helpers.
|
|
923
|
-
*/
|
|
924
|
-
_handlePointerDragMove(clientX, clientY) {
|
|
925
|
-
var _a;
|
|
926
|
-
const sourceDoc = (_a = this._tabsList.ownerDocument) !== null && _a !== void 0 ? _a : document;
|
|
927
|
-
const elAtPoint = sourceDoc.elementFromPoint(clientX, clientY);
|
|
928
|
-
const inside = !!elAtPoint &&
|
|
929
|
-
(this._tabsList.contains(elAtPoint) ||
|
|
930
|
-
(!!this._extendedDropZone &&
|
|
931
|
-
this._extendedDropZone.contains(elAtPoint)));
|
|
932
|
-
if (!inside) {
|
|
933
|
-
if (this._pointerInsideTabsList) {
|
|
934
|
-
this._pointerInsideTabsList = false;
|
|
935
|
-
this._processDragLeave(elAtPoint);
|
|
936
|
-
}
|
|
937
|
-
return;
|
|
938
|
-
}
|
|
939
|
-
this._pointerInsideTabsList = true;
|
|
940
|
-
this._processDragOver(clientX);
|
|
941
|
-
}
|
|
942
|
-
/**
|
|
943
|
-
* Shared body of the dragover entry point. Refreshes stale anim state
|
|
944
|
-
* for a changed drag identity, initializes anim state for incoming
|
|
945
|
-
* cross-group drags, and dispatches to the gap-following math in
|
|
946
|
-
* `handleDragOver`. Returns true when this tabs list has taken
|
|
947
|
-
* ownership of the drag — HTML5 callers use this to gate
|
|
948
|
-
* `event.preventDefault()`.
|
|
949
|
-
*/
|
|
950
|
-
_processDragOver(clientX) {
|
|
951
|
-
var _a, _b, _c, _d;
|
|
952
|
-
if (this.accessor.options.disableDnd) {
|
|
953
|
-
return false;
|
|
954
|
-
}
|
|
955
|
-
// Stale-state guard: if a previous drag's anim state is still here
|
|
956
|
-
// but the current drag is a different identity, drop the stale one
|
|
957
|
-
// so the new drag starts from a clean slate.
|
|
958
|
-
if (this._animState) {
|
|
959
|
-
const data = getPanelData();
|
|
960
|
-
if ((data === null || data === void 0 ? void 0 : data.tabGroupId) &&
|
|
961
|
-
data.groupId !== this.group.id &&
|
|
962
|
-
this._animState.sourceTabGroupId !== data.tabGroupId) {
|
|
963
|
-
this._animState = null;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
if (!this._animState) {
|
|
967
|
-
const data = getPanelData();
|
|
968
|
-
// In default animation mode, individual tab drops are handled
|
|
969
|
-
// by per-tab Droptargets; only chip drags need tabs-list-level
|
|
970
|
-
// handling so drops on void space still work.
|
|
971
|
-
if (((_a = this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) === 'default' &&
|
|
972
|
-
!(data === null || data === void 0 ? void 0 : data.tabGroupId)) {
|
|
973
|
-
return false;
|
|
974
|
-
}
|
|
975
|
-
if (data &&
|
|
976
|
-
(data.panelId || data.tabGroupId) &&
|
|
977
|
-
data.groupId !== this.group.id) {
|
|
978
|
-
const avgWidth = this.getAverageTabWidth();
|
|
979
|
-
if (data.tabGroupId) {
|
|
980
|
-
// External group drag — look up the source group to
|
|
981
|
-
// size the gap.
|
|
982
|
-
const sourceGroup = this.accessor.getPanel(data.groupId);
|
|
983
|
-
const sourceTg = sourceGroup === null || sourceGroup === void 0 ? void 0 : sourceGroup.model.getTabGroups().find((tg) => tg.id === data.tabGroupId);
|
|
984
|
-
const panelCount = (_b = sourceTg === null || sourceTg === void 0 ? void 0 : sourceTg.panelIds.length) !== null && _b !== void 0 ? _b : 1;
|
|
985
|
-
const groupGapWidth = avgWidth * panelCount + avgWidth;
|
|
986
|
-
this._animState = {
|
|
987
|
-
sourceTabId: '',
|
|
988
|
-
sourceIndex: -1,
|
|
989
|
-
tabPositions: this.snapshotTabPositions(),
|
|
990
|
-
chipPositions: this._tabGroupManager.snapshotChipWidths(),
|
|
991
|
-
currentInsertionIndex: null,
|
|
992
|
-
targetTabGroupId: null,
|
|
993
|
-
sourceTabGroupId: data.tabGroupId,
|
|
994
|
-
sourceGroupPanelIds: sourceTg
|
|
995
|
-
? new Set(sourceTg.panelIds)
|
|
996
|
-
: new Set(),
|
|
997
|
-
sourceChipWidth: avgWidth,
|
|
998
|
-
cursorOffsetFromDragLeft: groupGapWidth / 2,
|
|
999
|
-
sourceGapWidth: groupGapWidth,
|
|
1000
|
-
containerLeft: this._tabsList.getBoundingClientRect().left,
|
|
1001
|
-
};
|
|
1002
|
-
}
|
|
1003
|
-
else {
|
|
1004
|
-
this._animState = {
|
|
1005
|
-
sourceTabId: data.panelId,
|
|
1006
|
-
sourceIndex: -1,
|
|
1007
|
-
tabPositions: this.snapshotTabPositions(),
|
|
1008
|
-
chipPositions: this._tabGroupManager.snapshotChipWidths(),
|
|
1009
|
-
currentInsertionIndex: null,
|
|
1010
|
-
targetTabGroupId: null,
|
|
1011
|
-
sourceTabGroupId: null,
|
|
1012
|
-
sourceGroupPanelIds: null,
|
|
1013
|
-
sourceChipWidth: 0,
|
|
1014
|
-
cursorOffsetFromDragLeft: avgWidth / 2,
|
|
1015
|
-
sourceGapWidth: avgWidth,
|
|
1016
|
-
containerLeft: this._tabsList.getBoundingClientRect().left,
|
|
1017
|
-
};
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
else {
|
|
1021
|
-
return false;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
// For intra-group drag (sourceIndex >= 0) the gap animation is the
|
|
1025
|
-
// sole visual indicator — clear any stale anchor overlay that may
|
|
1026
|
-
// have been set while the cursor was over the panel content area or
|
|
1027
|
-
// another zone. External drags (sourceIndex === -1) leave the
|
|
1028
|
-
// overlay to the individual tab Droptargets so cross-group
|
|
1029
|
-
// animation is not disrupted.
|
|
1030
|
-
if (this._animState.sourceIndex !== -1) {
|
|
1031
|
-
(_d = (_c = this.group.model.dropTargetContainer) === null || _c === void 0 ? void 0 : _c.model) === null || _d === void 0 ? void 0 : _d.clear();
|
|
1032
|
-
}
|
|
1033
|
-
this.handleDragOver({ clientX });
|
|
1034
|
-
return true;
|
|
1035
|
-
}
|
|
1036
|
-
/**
|
|
1037
|
-
* Shared body of the dragleave entry point. Preserves anim state when
|
|
1038
|
-
* the drag moves between tabs-list children, into the extended drop
|
|
1039
|
-
* zone, or into the void container; tears it down otherwise.
|
|
1040
|
-
*/
|
|
1041
|
-
_processDragLeave(related) {
|
|
1042
|
-
var _a, _b, _c;
|
|
1043
|
-
if (!this._animState) {
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
|
-
// Moves between children of the tabs list aren't real leaves.
|
|
1047
|
-
if (related && this._tabsList.contains(related)) {
|
|
1048
|
-
return;
|
|
1049
|
-
}
|
|
1050
|
-
// Moving into the broader drop zone (e.g. void container, left
|
|
1051
|
-
// actions) — keep anim state alive so external listeners can
|
|
1052
|
-
// continue the gap animation.
|
|
1053
|
-
if (related && ((_a = this._extendedDropZone) === null || _a === void 0 ? void 0 : _a.contains(related))) {
|
|
1054
|
-
this.resetTabTransforms();
|
|
1055
|
-
this._animState.currentInsertionIndex = null;
|
|
1056
|
-
return;
|
|
1057
|
-
}
|
|
1058
|
-
// Leaving toward the void container (empty header space to the
|
|
1059
|
-
// right): keep anim state so a drop can still land at the end.
|
|
1060
|
-
const isVoid = this._voidContainer &&
|
|
1061
|
-
related &&
|
|
1062
|
-
(related === this._voidContainer ||
|
|
1063
|
-
this._voidContainer.contains(related));
|
|
1064
|
-
if (isVoid) {
|
|
1065
|
-
return;
|
|
1066
|
-
}
|
|
1067
|
-
this.resetTabTransforms();
|
|
1068
|
-
if (this._animState.sourceIndex === -1) {
|
|
1069
|
-
(_c = (_b = this.group.model.dropTargetContainer) === null || _b === void 0 ? void 0 : _b.model) === null || _c === void 0 ? void 0 : _c.clear();
|
|
1070
|
-
this._animState = null;
|
|
1071
|
-
}
|
|
1072
|
-
else {
|
|
1073
|
-
this._animState.currentInsertionIndex = null;
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
handleDragOver(event) {
|
|
1077
|
-
var _a, _b, _c, _d, _e;
|
|
1078
|
-
if (!this._animState) {
|
|
1079
|
-
return;
|
|
1080
|
-
}
|
|
1081
|
-
const mouseX = event.clientX;
|
|
1082
|
-
let insertionIndex = null;
|
|
1083
|
-
let targetTabGroupId = null;
|
|
1084
|
-
const sourceGroupPanelIds = this._animState.sourceGroupPanelIds;
|
|
1085
|
-
// Accumulation approach: compute where the drag image's left edge
|
|
1086
|
-
// would be, then walk tabs left-to-right using their original widths.
|
|
1087
|
-
// A tab fits to the left of the gap if the cumulative width of all
|
|
1088
|
-
// preceding non-source tabs <= available space.
|
|
1089
|
-
const dragLeftEdge = mouseX - this._animState.cursorOffsetFromDragLeft;
|
|
1090
|
-
const availableSpace = dragLeftEdge - this._animState.containerLeft;
|
|
1091
|
-
let accWidth = 0;
|
|
1092
|
-
// Build lookup: first panel ID of each non-source group → group ID
|
|
1093
|
-
// so we can add chip widths when we encounter a group's first tab.
|
|
1094
|
-
const firstPanelToGroup = new Map();
|
|
1095
|
-
if (this._tabGroupManager.chipRenderers.size > 0) {
|
|
1096
|
-
const tabGroups = this.group.model.getTabGroups();
|
|
1097
|
-
for (const tg of tabGroups) {
|
|
1098
|
-
if (tg.id === this._animState.sourceTabGroupId) {
|
|
1099
|
-
continue;
|
|
1100
|
-
}
|
|
1101
|
-
if (tg.panelIds.length > 0) {
|
|
1102
|
-
firstPanelToGroup.set(tg.panelIds[0], tg.id);
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
for (let i = 0; i < this._tabs.length; i++) {
|
|
1107
|
-
const tab = this._tabs[i].value;
|
|
1108
|
-
if (tab.panel.id === this._animState.sourceTabId) {
|
|
1109
|
-
continue;
|
|
1110
|
-
}
|
|
1111
|
-
if (sourceGroupPanelIds === null || sourceGroupPanelIds === void 0 ? void 0 : sourceGroupPanelIds.has(tab.panel.id)) {
|
|
1112
|
-
continue;
|
|
1113
|
-
}
|
|
1114
|
-
// If this tab is the first of a non-source group, include
|
|
1115
|
-
// the chip width (which sits before it in the DOM).
|
|
1116
|
-
const groupId = firstPanelToGroup.get(tab.panel.id);
|
|
1117
|
-
if (groupId) {
|
|
1118
|
-
const chipWidth = (_a = this._animState.chipPositions.get(groupId)) !== null && _a !== void 0 ? _a : 0;
|
|
1119
|
-
if (accWidth + chipWidth > availableSpace) {
|
|
1120
|
-
// Chip alone overflows — gap goes before this group
|
|
1121
|
-
insertionIndex !== null && insertionIndex !== void 0 ? insertionIndex : (insertionIndex = i);
|
|
1122
|
-
break;
|
|
1123
|
-
}
|
|
1124
|
-
accWidth += chipWidth;
|
|
1125
|
-
}
|
|
1126
|
-
// Use original width (before collapse/transforms)
|
|
1127
|
-
const origRect = this._animState.tabPositions.get(tab.panel.id);
|
|
1128
|
-
const tabWidth = origRect
|
|
1129
|
-
? origRect.width
|
|
1130
|
-
: tab.element.getBoundingClientRect().width;
|
|
1131
|
-
// Shift at the midpoint: a tab moves left once the drag image
|
|
1132
|
-
// covers half of it (like Chrome's tab drag behavior).
|
|
1133
|
-
if (accWidth + tabWidth / 2 <= availableSpace) {
|
|
1134
|
-
accWidth += tabWidth;
|
|
1135
|
-
insertionIndex = i + 1;
|
|
1136
|
-
}
|
|
1137
|
-
else {
|
|
1138
|
-
insertionIndex !== null && insertionIndex !== void 0 ? insertionIndex : (insertionIndex = i);
|
|
1139
|
-
break;
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
// Determine which tab group (if any) the insertion index falls within.
|
|
1143
|
-
//
|
|
1144
|
-
// We use snapshot-based positions (accWidth from the accumulation loop
|
|
1145
|
-
// above) to compute original chip boundaries. This avoids reading
|
|
1146
|
-
// getBoundingClientRect() on chips whose live position is shifted by
|
|
1147
|
-
// the drag gap margin, which caused oscillation / visual jumps.
|
|
1148
|
-
if (insertionIndex !== null &&
|
|
1149
|
-
this._tabGroupManager.chipRenderers.size > 0) {
|
|
1150
|
-
const isGroupDrag = !!this._animState.sourceTabGroupId;
|
|
1151
|
-
const tabGroups = this.group.model.getTabGroups();
|
|
1152
|
-
// Rebuild the accumulated width up to insertionIndex so we know
|
|
1153
|
-
// the original right edge of the chip (if any) that precedes it.
|
|
1154
|
-
// We walk exactly the same way as the accumulation loop above.
|
|
1155
|
-
let accUpTo = 0;
|
|
1156
|
-
for (let i = 0; i < this._tabs.length; i++) {
|
|
1157
|
-
const tab = this._tabs[i].value;
|
|
1158
|
-
if (tab.panel.id === this._animState.sourceTabId) {
|
|
1159
|
-
continue;
|
|
1160
|
-
}
|
|
1161
|
-
if (sourceGroupPanelIds === null || sourceGroupPanelIds === void 0 ? void 0 : sourceGroupPanelIds.has(tab.panel.id)) {
|
|
1162
|
-
continue;
|
|
1163
|
-
}
|
|
1164
|
-
if (i >= insertionIndex) {
|
|
1165
|
-
break;
|
|
1166
|
-
}
|
|
1167
|
-
const gid = firstPanelToGroup.get(tab.panel.id);
|
|
1168
|
-
if (gid) {
|
|
1169
|
-
accUpTo += (_b = this._animState.chipPositions.get(gid)) !== null && _b !== void 0 ? _b : 0;
|
|
1170
|
-
}
|
|
1171
|
-
const origRect = this._animState.tabPositions.get(tab.panel.id);
|
|
1172
|
-
accUpTo += origRect
|
|
1173
|
-
? origRect.width
|
|
1174
|
-
: tab.element.getBoundingClientRect().width;
|
|
1175
|
-
}
|
|
1176
|
-
for (const tg of tabGroups) {
|
|
1177
|
-
// Build effective panel list: exclude the source tab
|
|
1178
|
-
// so that dragging a tab out of its own group doesn't
|
|
1179
|
-
// inflate the group's index range.
|
|
1180
|
-
const effectivePanelIds = tg.panelIds.filter((pid) => pid !== this._animState.sourceTabId &&
|
|
1181
|
-
!(sourceGroupPanelIds === null || sourceGroupPanelIds === void 0 ? void 0 : sourceGroupPanelIds.has(pid)));
|
|
1182
|
-
if (effectivePanelIds.length === 0) {
|
|
1183
|
-
continue;
|
|
1184
|
-
}
|
|
1185
|
-
const firstIdx = this._tabs.findIndex((t) => t.value.panel.id === effectivePanelIds[0]);
|
|
1186
|
-
const lastIdx = this._tabs.findIndex((t) => t.value.panel.id ===
|
|
1187
|
-
effectivePanelIds[effectivePanelIds.length - 1]);
|
|
1188
|
-
if (firstIdx === -1 || lastIdx === -1) {
|
|
1189
|
-
continue;
|
|
1190
|
-
}
|
|
1191
|
-
const isInsideRange = insertionIndex >= firstIdx && insertionIndex <= lastIdx;
|
|
1192
|
-
const isJustBeforeGroup = !isInsideRange && insertionIndex === firstIdx - 1;
|
|
1193
|
-
if (!isInsideRange && !isJustBeforeGroup) {
|
|
1194
|
-
continue;
|
|
1195
|
-
}
|
|
1196
|
-
if (isGroupDrag && isInsideRange) {
|
|
1197
|
-
// A group cannot be dropped inside another group.
|
|
1198
|
-
// Snap the insertion index to just before or just
|
|
1199
|
-
// after this group based on cursor position relative
|
|
1200
|
-
// to the group's midpoint. Only applies when the
|
|
1201
|
-
// insertion would land *inside* the group — for
|
|
1202
|
-
// `isJustBeforeGroup`, the index is already outside
|
|
1203
|
-
// (immediately left of the group) and is a valid
|
|
1204
|
-
// drop position, so leave it untouched (issue #1264).
|
|
1205
|
-
const groupMid = (firstIdx + lastIdx + 1) / 2;
|
|
1206
|
-
if (insertionIndex < groupMid) {
|
|
1207
|
-
insertionIndex = firstIdx;
|
|
1208
|
-
}
|
|
1209
|
-
else {
|
|
1210
|
-
insertionIndex = lastIdx + 1;
|
|
1211
|
-
}
|
|
1212
|
-
// targetTabGroupId stays null
|
|
1213
|
-
break;
|
|
1214
|
-
}
|
|
1215
|
-
if (isGroupDrag && isJustBeforeGroup) {
|
|
1216
|
-
// Cursor is just before the group — accept this
|
|
1217
|
-
// index as-is. Groups can be dropped at the slot
|
|
1218
|
-
// immediately left of another group's first tab.
|
|
1219
|
-
break;
|
|
1220
|
-
}
|
|
1221
|
-
if (isJustBeforeGroup) {
|
|
1222
|
-
// Check whether only the source tab (or source group
|
|
1223
|
-
// tabs) sits between insertionIndex and firstIdx.
|
|
1224
|
-
// If so, the source is being dragged away from that
|
|
1225
|
-
// slot, so we ARE effectively "just before" the group
|
|
1226
|
-
// and should still allow dropping into position 0.
|
|
1227
|
-
let allInBetweenAreSource = true;
|
|
1228
|
-
for (let j = insertionIndex; j < firstIdx; j++) {
|
|
1229
|
-
const pid = this._tabs[j].value.panel.id;
|
|
1230
|
-
if (pid !== this._animState.sourceTabId &&
|
|
1231
|
-
!(sourceGroupPanelIds === null || sourceGroupPanelIds === void 0 ? void 0 : sourceGroupPanelIds.has(pid))) {
|
|
1232
|
-
allInBetweenAreSource = false;
|
|
1233
|
-
break;
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
if (!allInBetweenAreSource) {
|
|
1237
|
-
continue;
|
|
1238
|
-
}
|
|
1239
|
-
const chipWidth = (_c = this._animState.chipPositions.get(tg.id)) !== null && _c !== void 0 ? _c : 0;
|
|
1240
|
-
const threshold = tg.collapsed
|
|
1241
|
-
? this._animState.containerLeft +
|
|
1242
|
-
accUpTo +
|
|
1243
|
-
chipWidth / 2
|
|
1244
|
-
: this._animState.containerLeft + accUpTo + chipWidth;
|
|
1245
|
-
if (mouseX >= threshold) {
|
|
1246
|
-
insertionIndex = firstIdx;
|
|
1247
|
-
targetTabGroupId = tg.id;
|
|
1248
|
-
}
|
|
1249
|
-
break;
|
|
1250
|
-
}
|
|
1251
|
-
if (isInsideRange) {
|
|
1252
|
-
const chipWidth = (_d = this._animState.chipPositions.get(tg.id)) !== null && _d !== void 0 ? _d : 0;
|
|
1253
|
-
const chipOriginalRight = this._animState.containerLeft + accUpTo + chipWidth;
|
|
1254
|
-
if (insertionIndex === firstIdx) {
|
|
1255
|
-
if (mouseX >= chipOriginalRight) {
|
|
1256
|
-
targetTabGroupId = tg.id;
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
else {
|
|
1260
|
-
targetTabGroupId = tg.id;
|
|
1261
|
-
}
|
|
1262
|
-
break;
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
if (insertionIndex === this._animState.currentInsertionIndex &&
|
|
1267
|
-
targetTabGroupId === this._animState.targetTabGroupId) {
|
|
1268
|
-
return;
|
|
1269
|
-
}
|
|
1270
|
-
this._animState.currentInsertionIndex = insertionIndex;
|
|
1271
|
-
this._animState.targetTabGroupId = targetTabGroupId;
|
|
1272
|
-
if (((_e = this.accessor.options.theme) === null || _e === void 0 ? void 0 : _e.tabAnimation) === 'smooth') {
|
|
1273
|
-
this.applyDragOverTransforms();
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
/**
|
|
1277
|
-
* Batch-remove a CSS class from multiple elements instantly,
|
|
1278
|
-
* forcing only a single reflow for the entire batch.
|
|
1279
|
-
*/
|
|
1280
|
-
_removeClassInstantlyBatch(elements, cls) {
|
|
1281
|
-
const affected = [];
|
|
1282
|
-
for (const el of elements) {
|
|
1283
|
-
if (el.classList.contains(cls)) {
|
|
1284
|
-
el.style.transition = 'none';
|
|
1285
|
-
toggleClass(el, cls, false);
|
|
1286
|
-
affected.push(el);
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
if (affected.length > 0) {
|
|
1290
|
-
void affected[0].offsetHeight; // single reflow for entire batch
|
|
1291
|
-
for (const el of affected) {
|
|
1292
|
-
el.style.removeProperty('transition');
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
/**
|
|
1297
|
-
* Remove `dv-tab--dragging` from the source tab instantly so it
|
|
1298
|
-
* regains its real width before FLIP snapshots.
|
|
1299
|
-
*/
|
|
1300
|
-
_uncollapsSourceTab(sourceTabId) {
|
|
1301
|
-
const entry = this._tabMap.get(sourceTabId);
|
|
1302
|
-
if (entry) {
|
|
1303
|
-
this._removeClassInstantlyBatch([entry.value.element], 'dv-tab--dragging');
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
applyDragOverTransforms(skipTransition = false) {
|
|
1307
|
-
if (!this._animState ||
|
|
1308
|
-
this._animState.currentInsertionIndex === null) {
|
|
1309
|
-
this.resetTabTransforms();
|
|
1310
|
-
return;
|
|
1311
|
-
}
|
|
1312
|
-
// Don't apply transforms until the source tab has been collapsed
|
|
1313
|
-
// in the rAF callback — otherwise the gap + visible source = jump.
|
|
1314
|
-
if (this._pendingCollapse) {
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
const insertionIndex = this._animState.currentInsertionIndex;
|
|
1318
|
-
// For group drags, gap = sum of all group member widths
|
|
1319
|
-
let gapWidth;
|
|
1320
|
-
const sourceGroupPanelIds = this._animState.sourceGroupPanelIds;
|
|
1321
|
-
if (this._animState.sourceTabGroupId && sourceGroupPanelIds) {
|
|
1322
|
-
gapWidth = this._animState.sourceGapWidth;
|
|
1323
|
-
}
|
|
1324
|
-
else {
|
|
1325
|
-
const sourceRect = this._animState.tabPositions.get(this._animState.sourceTabId);
|
|
1326
|
-
gapWidth = sourceRect
|
|
1327
|
-
? sourceRect.width
|
|
1328
|
-
: this.getAverageTabWidth();
|
|
1329
|
-
}
|
|
1330
|
-
// When the insertion lands at or before a group's first tab, shift
|
|
1331
|
-
// the chip so the gap appears before the entire group.
|
|
1332
|
-
//
|
|
1333
|
-
// Two cases:
|
|
1334
|
-
// 1. targetTabGroupId is null (standalone drop) — always shift chip.
|
|
1335
|
-
// 2. targetTabGroupId is set AND the group is collapsed — shift chip
|
|
1336
|
-
// because the collapsed tabs are invisible, so putting the gap on
|
|
1337
|
-
// them has no visual effect.
|
|
1338
|
-
let chipToShift = null;
|
|
1339
|
-
if (this._tabGroupManager.chipRenderers.size > 0) {
|
|
1340
|
-
const tabGroups = this.group.model.getTabGroups();
|
|
1341
|
-
for (const tg of tabGroups) {
|
|
1342
|
-
if (tg.id === this._animState.sourceTabGroupId)
|
|
1343
|
-
continue;
|
|
1344
|
-
// Skip the group that the dragged tab belongs to — the
|
|
1345
|
-
// gap should appear after the chip (where the tab was),
|
|
1346
|
-
// not before it.
|
|
1347
|
-
if (tg.panelIds.includes(this._animState.sourceTabId))
|
|
1348
|
-
continue;
|
|
1349
|
-
const effectivePids = tg.panelIds.filter((pid) => pid !== this._animState.sourceTabId &&
|
|
1350
|
-
!(sourceGroupPanelIds === null || sourceGroupPanelIds === void 0 ? void 0 : sourceGroupPanelIds.has(pid)));
|
|
1351
|
-
if (effectivePids.length === 0)
|
|
1352
|
-
continue;
|
|
1353
|
-
const firstIdx = this._tabs.findIndex((t) => t.value.panel.id === effectivePids[0]);
|
|
1354
|
-
// Only consider chip-shifting when dropping outside the
|
|
1355
|
-
// group, or when dropping inside a collapsed group (whose
|
|
1356
|
-
// tabs are invisible).
|
|
1357
|
-
const shouldShiftChip = !this._animState.targetTabGroupId ||
|
|
1358
|
-
(this._animState.targetTabGroupId === tg.id &&
|
|
1359
|
-
tg.collapsed);
|
|
1360
|
-
if (!shouldShiftChip)
|
|
1361
|
-
continue;
|
|
1362
|
-
if (firstIdx >= insertionIndex) {
|
|
1363
|
-
let hasTabs = false;
|
|
1364
|
-
for (let j = insertionIndex; j < firstIdx; j++) {
|
|
1365
|
-
const pid = this._tabs[j].value.panel.id;
|
|
1366
|
-
if (pid === this._animState.sourceTabId)
|
|
1367
|
-
continue;
|
|
1368
|
-
if (sourceGroupPanelIds === null || sourceGroupPanelIds === void 0 ? void 0 : sourceGroupPanelIds.has(pid))
|
|
1369
|
-
continue;
|
|
1370
|
-
hasTabs = true;
|
|
1371
|
-
break;
|
|
1372
|
-
}
|
|
1373
|
-
if (!hasTabs) {
|
|
1374
|
-
const chipEntry = this._tabGroupManager.chipRenderers.get(tg.id);
|
|
1375
|
-
if (chipEntry) {
|
|
1376
|
-
chipToShift = chipEntry.chip.element;
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
break;
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
// Helper: pick the correct shifting class for tabs vs chips.
|
|
1384
|
-
const shiftingClass = (el) => el.classList.contains('dv-tab-group-chip')
|
|
1385
|
-
? 'dv-tab-group-chip--shifting'
|
|
1386
|
-
: 'dv-tab--shifting';
|
|
1387
|
-
// Helper: apply a margin-left value to an element, optionally
|
|
1388
|
-
// bypassing CSS transitions for instant positioning.
|
|
1389
|
-
const setMargin = (el, value) => {
|
|
1390
|
-
if (skipTransition) {
|
|
1391
|
-
el.style.transition = 'none';
|
|
1392
|
-
el.style.marginLeft = value;
|
|
1393
|
-
void el.offsetHeight;
|
|
1394
|
-
el.style.removeProperty('transition');
|
|
1395
|
-
}
|
|
1396
|
-
else {
|
|
1397
|
-
el.style.marginLeft = value;
|
|
1398
|
-
}
|
|
1399
|
-
toggleClass(el, shiftingClass(el), true);
|
|
1400
|
-
};
|
|
1401
|
-
const clearMargin = (el) => {
|
|
1402
|
-
const cls = shiftingClass(el);
|
|
1403
|
-
// Remove any previous pending listener for this element
|
|
1404
|
-
const prev = this._pendingMarginCleanups.get(el);
|
|
1405
|
-
if (prev) {
|
|
1406
|
-
prev();
|
|
1407
|
-
}
|
|
1408
|
-
if (skipTransition || !el.style.marginLeft) {
|
|
1409
|
-
el.style.removeProperty('margin-left');
|
|
1410
|
-
toggleClass(el, cls, false);
|
|
1411
|
-
}
|
|
1412
|
-
else {
|
|
1413
|
-
el.style.marginLeft = '0px';
|
|
1414
|
-
toggleClass(el, cls, true);
|
|
1415
|
-
const onEnd = () => {
|
|
1416
|
-
el.style.removeProperty('margin-left');
|
|
1417
|
-
toggleClass(el, cls, false);
|
|
1418
|
-
el.removeEventListener('transitionend', onEnd);
|
|
1419
|
-
clearTimeout(fallbackTimer);
|
|
1420
|
-
this._pendingMarginCleanups.delete(el);
|
|
1421
|
-
};
|
|
1422
|
-
// Fallback in case transitionend never fires
|
|
1423
|
-
// (e.g. element removed from DOM mid-transition)
|
|
1424
|
-
const fallbackTimer = setTimeout(onEnd, 300);
|
|
1425
|
-
this._pendingMarginCleanups.set(el, onEnd);
|
|
1426
|
-
el.addEventListener('transitionend', onEnd);
|
|
1427
|
-
}
|
|
1428
|
-
};
|
|
1429
|
-
let gapApplied = false;
|
|
1430
|
-
// Reset all non-source chip margins first
|
|
1431
|
-
for (const [groupId, entry] of this._tabGroupManager.chipRenderers) {
|
|
1432
|
-
if (groupId === this._animState.sourceTabGroupId)
|
|
1433
|
-
continue;
|
|
1434
|
-
clearMargin(entry.chip.element);
|
|
1435
|
-
}
|
|
1436
|
-
// Apply gap to chip if insertion is before a group
|
|
1437
|
-
if (chipToShift) {
|
|
1438
|
-
setMargin(chipToShift, `${gapWidth}px`);
|
|
1439
|
-
gapApplied = true;
|
|
1440
|
-
}
|
|
1441
|
-
for (let i = 0; i < this._tabs.length; i++) {
|
|
1442
|
-
const tab = this._tabs[i].value;
|
|
1443
|
-
if (tab.panel.id === this._animState.sourceTabId) {
|
|
1444
|
-
continue;
|
|
1445
|
-
}
|
|
1446
|
-
if (sourceGroupPanelIds === null || sourceGroupPanelIds === void 0 ? void 0 : sourceGroupPanelIds.has(tab.panel.id)) {
|
|
1447
|
-
continue;
|
|
1448
|
-
}
|
|
1449
|
-
if (!gapApplied && i >= insertionIndex) {
|
|
1450
|
-
setMargin(tab.element, `${gapWidth}px`);
|
|
1451
|
-
gapApplied = true;
|
|
1452
|
-
}
|
|
1453
|
-
else {
|
|
1454
|
-
clearMargin(tab.element);
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
// Reposition underlines to follow shifted chips/tabs
|
|
1458
|
-
this._tabGroupManager.trackUnderlines();
|
|
1459
|
-
}
|
|
1460
|
-
resetTabTransforms() {
|
|
1461
|
-
// Cancel any pending margin transitionend listeners
|
|
1462
|
-
for (const [, cleanup] of this._pendingMarginCleanups) {
|
|
1463
|
-
cleanup();
|
|
1464
|
-
}
|
|
1465
|
-
this._pendingMarginCleanups.clear();
|
|
1466
|
-
for (const tab of this._tabs) {
|
|
1467
|
-
tab.value.element.style.removeProperty('margin-left');
|
|
1468
|
-
tab.value.element.style.removeProperty('margin-right');
|
|
1469
|
-
tab.value.element.style.removeProperty('margin-top');
|
|
1470
|
-
tab.value.element.style.removeProperty('margin-bottom');
|
|
1471
|
-
tab.value.element.style.removeProperty('transform');
|
|
1472
|
-
toggleClass(tab.value.element, 'dv-tab--shifting', false);
|
|
1473
|
-
}
|
|
1474
|
-
for (const [, entry] of this._tabGroupManager.chipRenderers) {
|
|
1475
|
-
entry.chip.element.style.removeProperty('margin-left');
|
|
1476
|
-
toggleClass(entry.chip.element, 'dv-tab-group-chip--shifting', false);
|
|
1477
|
-
}
|
|
1478
|
-
this._tabGroupManager.positionUnderlines();
|
|
1479
|
-
}
|
|
1480
|
-
/**
|
|
1481
|
-
* Commit a group-drag drop: clear drag classes, move the group
|
|
1482
|
-
* in the model, and run a FLIP animation.
|
|
1483
|
-
*/
|
|
1484
|
-
_commitGroupMove(sourceTabGroupId, insertionIndex) {
|
|
1485
|
-
var _a, _b;
|
|
1486
|
-
// Read transfer data first.
|
|
1487
|
-
const data = getPanelData();
|
|
1488
|
-
// Synchronously dispose the source chip's drag sources, which
|
|
1489
|
-
// clears the panelTransfer payload + iframe shield. Cross-group
|
|
1490
|
-
// moves dissolve the source chip on a microtask, which is too
|
|
1491
|
-
// late: a synchronous `getPanelData()` after this method (or any
|
|
1492
|
-
// sibling dragover handler firing in the same tick) would
|
|
1493
|
-
// otherwise see stale data still referencing the old tabGroupId.
|
|
1494
|
-
this._tabGroupManager.disposeChipDrag(sourceTabGroupId);
|
|
1495
|
-
// Check if the tab group exists in this group (within-group reorder)
|
|
1496
|
-
// or in another group (cross-group move).
|
|
1497
|
-
const isLocal = this.group.model
|
|
1498
|
-
.getTabGroups()
|
|
1499
|
-
.some((tg) => tg.id === sourceTabGroupId);
|
|
1500
|
-
if (isLocal) {
|
|
1501
|
-
if (((_a = this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) === 'smooth') {
|
|
1502
|
-
this._clearGroupDragClasses(sourceTabGroupId);
|
|
1503
|
-
const firstPositions = this.snapshotTabPositions();
|
|
1504
|
-
this.resetTabTransforms();
|
|
1505
|
-
this.group.model.moveTabGroup(sourceTabGroupId, insertionIndex);
|
|
1506
|
-
this.runFlipAnimation(firstPositions, '', false);
|
|
1507
|
-
}
|
|
1508
|
-
else {
|
|
1509
|
-
this._tabGroupManager.skipNextCollapseAnimation = true;
|
|
1510
|
-
this.group.model.moveTabGroup(sourceTabGroupId, insertionIndex);
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
else if (data) {
|
|
1514
|
-
// Cross-group: delegate to the component-level move which
|
|
1515
|
-
// handles panel transfer and tab group recreation.
|
|
1516
|
-
// Use the REAL tab group ID from transfer data, not the
|
|
1517
|
-
// potentially stale one from _animState.
|
|
1518
|
-
//
|
|
1519
|
-
// Clear any inline gap margin / shifting class applied to
|
|
1520
|
-
// destination tabs during dragover. Cross-group moves don't
|
|
1521
|
-
// run the FLIP path, and `moveGroupOrPanel` only inserts new
|
|
1522
|
-
// panels — it doesn't recreate existing destination tabs, so
|
|
1523
|
-
// their inline `margin-left` would otherwise persist as a
|
|
1524
|
-
// visible gap (issue #1243).
|
|
1525
|
-
this.resetTabTransforms();
|
|
1526
|
-
this.accessor.moveGroupOrPanel({
|
|
1527
|
-
from: {
|
|
1528
|
-
groupId: data.groupId,
|
|
1529
|
-
tabGroupId: (_b = data.tabGroupId) !== null && _b !== void 0 ? _b : sourceTabGroupId,
|
|
1530
|
-
},
|
|
1531
|
-
to: {
|
|
1532
|
-
group: this.group,
|
|
1533
|
-
position: 'center',
|
|
1534
|
-
index: insertionIndex,
|
|
1535
|
-
},
|
|
1536
|
-
});
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
_clearGroupDragClasses(sourceTabGroupId) {
|
|
1540
|
-
const chipEntry = this._tabGroupManager.chipRenderers.get(sourceTabGroupId);
|
|
1541
|
-
if (chipEntry) {
|
|
1542
|
-
this._removeClassInstantlyBatch([chipEntry.chip.element], 'dv-tab-group-chip--dragging');
|
|
1543
|
-
}
|
|
1544
|
-
this._removeClassInstantlyBatch(this._tabs.map((t) => t.value.element), 'dv-tab--dragging');
|
|
1545
|
-
// Restore underline
|
|
1546
|
-
const underline = this._tabGroupManager.groupUnderlines.get(sourceTabGroupId);
|
|
1547
|
-
if (underline) {
|
|
1548
|
-
underline.style.removeProperty('display');
|
|
1549
|
-
}
|
|
1550
|
-
// The subsequent moveTabGroup will re-create tabs and call
|
|
1551
|
-
// updateTabGroups → _updateTabGroupClasses. For collapsed groups
|
|
1552
|
-
// the new tabs don't have dv-tab--group-collapsed yet, which
|
|
1553
|
-
// would trigger the collapse animation. Skip it.
|
|
1554
|
-
this._tabGroupManager.skipNextCollapseAnimation = true;
|
|
1555
|
-
}
|
|
1556
|
-
resetDragAnimation() {
|
|
1557
|
-
this._pendingCollapse = false;
|
|
1558
|
-
// After a drop, `tab.onDrop` consumes _animState (sets it to null)
|
|
1559
|
-
// and immediately calls `runFlipAnimation`, which sets transforms
|
|
1560
|
-
// and queues an rAF to trigger the CSS transition. dragend fires
|
|
1561
|
-
// synchronously on the source element BEFORE that rAF runs — if
|
|
1562
|
-
// we cleared transforms here we'd clobber the in-flight FLIP, so
|
|
1563
|
-
// gate the cleanup on _animState still being set (i.e. drag was
|
|
1564
|
-
// cancelled rather than dropped).
|
|
1565
|
-
if (this._animState) {
|
|
1566
|
-
this.resetTabTransforms();
|
|
1567
|
-
if (this._animState.sourceTabGroupId) {
|
|
1568
|
-
this._clearGroupDragClasses(this._animState.sourceTabGroupId);
|
|
1569
|
-
}
|
|
1570
|
-
else {
|
|
1571
|
-
this._removeClassInstantlyBatch(this._tabs.map((t) => t.value.element), 'dv-tab--dragging');
|
|
1572
|
-
}
|
|
1573
|
-
this._animState = null;
|
|
1574
|
-
// Restore any hidden underlines from group drags.
|
|
1575
|
-
for (const [, el] of this._tabGroupManager.groupUnderlines) {
|
|
1576
|
-
el.style.removeProperty('display');
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
runFlipAnimation(firstPositions, sourceTabId, isCrossGroup = false, animRange) {
|
|
1581
|
-
const isVertical = this._direction === 'vertical';
|
|
1582
|
-
let hasAnimation = false;
|
|
1583
|
-
for (let i = 0; i < this._tabs.length; i++) {
|
|
1584
|
-
const tab = this._tabs[i];
|
|
1585
|
-
const panelId = tab.value.panel.id;
|
|
1586
|
-
if (panelId === sourceTabId) {
|
|
1587
|
-
if (isCrossGroup) {
|
|
1588
|
-
// Newly inserted tab: slide in from the end
|
|
1589
|
-
const rect = tab.value.element.getBoundingClientRect();
|
|
1590
|
-
tab.value.element.style.transform = isVertical
|
|
1591
|
-
? `translateY(${rect.height}px)`
|
|
1592
|
-
: `translateX(${rect.width}px)`;
|
|
1593
|
-
toggleClass(tab.value.element, 'dv-tab--shifting', true);
|
|
1594
|
-
hasAnimation = true;
|
|
1595
|
-
}
|
|
1596
|
-
continue;
|
|
1597
|
-
}
|
|
1598
|
-
// Skip tabs outside the affected range (they don't logically move)
|
|
1599
|
-
if (animRange !== undefined &&
|
|
1600
|
-
(i < animRange.from || i > animRange.to)) {
|
|
1601
|
-
continue;
|
|
1602
|
-
}
|
|
1603
|
-
const firstRect = firstPositions.get(panelId);
|
|
1604
|
-
if (!firstRect) {
|
|
1605
|
-
continue;
|
|
1606
|
-
}
|
|
1607
|
-
const lastRect = tab.value.element.getBoundingClientRect();
|
|
1608
|
-
const delta = isVertical
|
|
1609
|
-
? firstRect.top - lastRect.top
|
|
1610
|
-
: firstRect.left - lastRect.left;
|
|
1611
|
-
if (Math.abs(delta) < 1) {
|
|
1612
|
-
continue;
|
|
1613
|
-
}
|
|
1614
|
-
tab.value.element.style.transform = isVertical
|
|
1615
|
-
? `translateY(${delta}px)`
|
|
1616
|
-
: `translateX(${delta}px)`;
|
|
1617
|
-
toggleClass(tab.value.element, 'dv-tab--shifting', true);
|
|
1618
|
-
hasAnimation = true;
|
|
1619
|
-
}
|
|
1620
|
-
if (!hasAnimation) {
|
|
1621
|
-
return;
|
|
1622
|
-
}
|
|
1623
|
-
requestAnimationFrame(() => {
|
|
1624
|
-
var _a;
|
|
1625
|
-
for (const tab of this._tabs) {
|
|
1626
|
-
if (tab.value.element.style.transform) {
|
|
1627
|
-
tab.value.element.style.transform = '';
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
// Track underlines during the FLIP transition so they
|
|
1631
|
-
// follow tabs as they slide to their final positions.
|
|
1632
|
-
this._tabGroupManager.trackUnderlines();
|
|
1633
|
-
// Clean up any previous flip transition listener
|
|
1634
|
-
(_a = this._flipTransitionCleanup) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
1635
|
-
const onTransitionEnd = (event) => {
|
|
1636
|
-
if (event.propertyName === 'transform') {
|
|
1637
|
-
cleanup();
|
|
1638
|
-
for (const tab of this._tabs) {
|
|
1639
|
-
toggleClass(tab.value.element, 'dv-tab--shifting', false);
|
|
1640
|
-
}
|
|
1641
|
-
// Final reposition after animation settles
|
|
1642
|
-
this._tabGroupManager.positionUnderlines();
|
|
1643
|
-
}
|
|
1644
|
-
};
|
|
1645
|
-
const cleanup = () => {
|
|
1646
|
-
this._tabsList.removeEventListener('transitionend', onTransitionEnd);
|
|
1647
|
-
this._flipTransitionCleanup = null;
|
|
1648
|
-
};
|
|
1649
|
-
this._flipTransitionCleanup = cleanup;
|
|
1650
|
-
this._tabsList.addEventListener('transitionend', onTransitionEnd);
|
|
1651
|
-
});
|
|
1652
|
-
}
|
|
1653
|
-
}
|