@@ -191,6 +191,9 @@ let workspaceTabRenameState = {
191191let workspaceTabAddMenuOpen = false
192192let isRenderingWorkspaceTabs = false
193193let hasPendingWorkspaceTabsRender = false
194+ let draggedWorkspaceTabId = ''
195+ let dragOverWorkspaceTabId = ''
196+ let suppressWorkspaceTabClick = false
194197const clipboardSupported = Boolean ( navigator . clipboard ?. writeText )
195198const githubPrOpenIcon = {
196199 viewBox : '0 0 16 16' ,
@@ -1623,6 +1626,11 @@ const setWorkspaceTabAddMenuOpen = isOpen => {
16231626 }
16241627}
16251628
1629+ const clearWorkspaceTabDragState = ( ) => {
1630+ draggedWorkspaceTabId = ''
1631+ dragOverWorkspaceTabId = ''
1632+ }
1633+
16261634const renderWorkspaceTabs = ( ) => {
16271635 if ( ! ( workspaceTabsStrip instanceof HTMLElement ) ) {
16281636 return
@@ -1647,7 +1655,15 @@ const renderWorkspaceTabs = () => {
16471655 tabContainer . className = 'workspace-tab'
16481656 tabContainer . dataset . active = isActive ? 'true' : 'false'
16491657 tabContainer . dataset . tabId = tab . id
1658+ tabContainer . draggable = true
1659+ tabContainer . dataset . dragOver =
1660+ dragOverWorkspaceTabId && dragOverWorkspaceTabId === tab . id ? 'true' : 'false'
16501661 tabContainer . addEventListener ( 'click' , event => {
1662+ if ( suppressWorkspaceTabClick ) {
1663+ suppressWorkspaceTabClick = false
1664+ return
1665+ }
1666+
16511667 const clickTarget = event . target
16521668 if ( ! ( clickTarget instanceof Element ) ) {
16531669 return
@@ -1661,6 +1677,68 @@ const renderWorkspaceTabs = () => {
16611677
16621678 setActiveWorkspaceTab ( tab . id )
16631679 } )
1680+ tabContainer . addEventListener ( 'dragstart' , event => {
1681+ draggedWorkspaceTabId = tab . id
1682+ dragOverWorkspaceTabId = ''
1683+ suppressWorkspaceTabClick = true
1684+ if ( event . dataTransfer ) {
1685+ event . dataTransfer . effectAllowed = 'move'
1686+ event . dataTransfer . setData ( 'text/plain' , tab . id )
1687+ }
1688+ } )
1689+ tabContainer . addEventListener ( 'dragend' , ( ) => {
1690+ clearWorkspaceTabDragState ( )
1691+ queueMicrotask ( ( ) => {
1692+ suppressWorkspaceTabClick = false
1693+ } )
1694+ renderWorkspaceTabs ( )
1695+ } )
1696+ tabContainer . addEventListener ( 'dragover' , event => {
1697+ if ( ! draggedWorkspaceTabId || draggedWorkspaceTabId === tab . id ) {
1698+ return
1699+ }
1700+
1701+ event . preventDefault ( )
1702+ if ( event . dataTransfer ) {
1703+ event . dataTransfer . dropEffect = 'move'
1704+ }
1705+
1706+ if ( dragOverWorkspaceTabId !== tab . id ) {
1707+ dragOverWorkspaceTabId = tab . id
1708+ tabContainer . dataset . dragOver = 'true'
1709+ }
1710+ } )
1711+ tabContainer . addEventListener ( 'dragleave' , event => {
1712+ const relatedTarget = event . relatedTarget
1713+ if ( relatedTarget instanceof Node && tabContainer . contains ( relatedTarget ) ) {
1714+ return
1715+ }
1716+
1717+ if ( dragOverWorkspaceTabId === tab . id ) {
1718+ dragOverWorkspaceTabId = ''
1719+ tabContainer . dataset . dragOver = 'false'
1720+ }
1721+ } )
1722+ tabContainer . addEventListener ( 'drop' , event => {
1723+ if ( ! draggedWorkspaceTabId || draggedWorkspaceTabId === tab . id ) {
1724+ clearWorkspaceTabDragState ( )
1725+ renderWorkspaceTabs ( )
1726+ return
1727+ }
1728+
1729+ event . preventDefault ( )
1730+ persistActiveTabEditorContent ( )
1731+
1732+ const moved = workspaceTabsState . moveTabBefore ( draggedWorkspaceTabId , tab . id )
1733+ clearWorkspaceTabDragState ( )
1734+ renderWorkspaceTabs ( )
1735+
1736+ if ( ! moved ) {
1737+ return
1738+ }
1739+
1740+ queueWorkspaceSave ( )
1741+ } )
16641742
16651743 const isRenaming = workspaceTabRenameState . tabId === tab . id
16661744 if ( isRenaming ) {
0 commit comments