@@ -237,6 +237,7 @@ export function Table({
237237 const ghostRef = useRef < HTMLDivElement > ( null )
238238 const tableFilterRef = useRef < TableFilterHandle > ( null )
239239 const isDraggingRef = useRef ( false )
240+ const dragEscapeCleanupRef = useRef < ( ( ) => void ) | null > ( null )
240241
241242 const { tableData, isLoadingTable, rows, isLoadingRows } = useTableData ( {
242243 workspaceId,
@@ -715,7 +716,6 @@ export function Table({
715716 const scrollRect = scroll . getBoundingClientRect ( )
716717 const tableEl = element . closest ( 'table' )
717718
718- // Position the ghost at the dragged column's location
719719 ghost . style . left = `${ dragged . left } px`
720720 ghost . style . width = `${ dragged . width } px`
721721 ghost . style . height = `${ tableEl ? tableEl . offsetHeight : scroll . scrollHeight } px`
@@ -746,6 +746,7 @@ export function Table({
746746 element . removeEventListener ( 'pointercancel' , handleCancel )
747747 document . removeEventListener ( 'keydown' , handleKeyDown )
748748 element . releasePointerCapture ( pointerId )
749+ dragEscapeCleanupRef . current = null
749750 if ( shouldCommit ) commit ( )
750751 ghost . style . display = 'none'
751752 ghost . style . transform = 'translateX(0)'
@@ -758,7 +759,6 @@ export function Table({
758759 const delta = ev . clientX - startX
759760 ghost . style . transform = `translateX(${ delta } px)`
760761
761- // Determine which column the cursor is over
762762 const tableX = ev . clientX - scrollRect . left + scroll . scrollLeft
763763 let target = boundaries [ boundaries . length - 1 ]
764764 let side : 'left' | 'right' = 'right'
@@ -771,7 +771,6 @@ export function Table({
771771 }
772772
773773 if ( target . name === columnName ) {
774- // Hovering over self — suppress the indicator
775774 if ( dropTargetColumnNameRef . current !== null ) {
776775 setDropTargetColumnName ( null )
777776 }
@@ -795,6 +794,7 @@ export function Table({
795794 element . addEventListener ( 'pointerup' , handleUp )
796795 element . addEventListener ( 'pointercancel' , handleCancel )
797796 document . addEventListener ( 'keydown' , handleKeyDown )
797+ dragEscapeCleanupRef . current = ( ) => cleanup ( false )
798798 } ,
799799 [ ]
800800 )
@@ -833,6 +833,12 @@ export function Table({
833833 return ( ) => document . removeEventListener ( 'mouseup' , handleMouseUp )
834834 } , [ ] )
835835
836+ useEffect ( ( ) => {
837+ return ( ) => {
838+ dragEscapeCleanupRef . current ?.( )
839+ }
840+ } , [ ] )
841+
836842 useEffect ( ( ) => {
837843 if ( ! selectionAnchor ) return
838844 const { rowIndex, colIndex } = selectionAnchor
@@ -1466,10 +1472,10 @@ export function Table({
14661472 } , [ ] )
14671473
14681474 const generateColumnName = useCallback ( ( ) => {
1469- const existing = schemaColumnsRef . current . map ( ( c ) => c . name . toLowerCase ( ) )
1475+ const existing = new Set ( schemaColumnsRef . current . map ( ( c ) => c . name . toLowerCase ( ) ) )
14701476 let name = 'untitled'
14711477 let i = 2
1472- while ( existing . includes ( name . toLowerCase ( ) ) ) {
1478+ while ( existing . has ( name ) ) {
14731479 name = `untitled_${ i } `
14741480 i ++
14751481 }
@@ -2906,10 +2912,9 @@ const ColumnHeaderMenu = React.memo(function ColumnHeaderMenu({
29062912 const renameInputRef = useRef < HTMLInputElement > ( null )
29072913
29082914 useEffect ( ( ) => {
2909- if ( isRenaming && renameInputRef . current ) {
2910- renameInputRef . current . focus ( )
2911- renameInputRef . current . select ( )
2912- }
2915+ if ( ! isRenaming || ! renameInputRef . current ) return
2916+ renameInputRef . current . focus ( )
2917+ renameInputRef . current . select ( )
29132918 } , [ isRenaming ] )
29142919
29152920 const handleResizePointerDown = useCallback (
@@ -2958,7 +2963,6 @@ const ColumnHeaderMenu = React.memo(function ColumnHeaderMenu({
29582963 const handleThPointerDown = useCallback (
29592964 ( e : React . PointerEvent ) => {
29602965 if ( isRenaming || e . button !== 0 ) return
2961- if ( ( e . target as HTMLElement ) . closest ( 'button' ) ) return
29622966 e . preventDefault ( )
29632967
29642968 const th = e . currentTarget as HTMLElement
@@ -3042,24 +3046,25 @@ const ColumnHeaderMenu = React.memo(function ColumnHeaderMenu({
30423046 ) }
30433047 </ div >
30443048 ) : (
3045- < div className = 'flex h-full w-full min-w-0 items-center' >
3049+ < div className = 'flex h-full w-full min-w-0 items-center px-2 py-[7px]' >
3050+ < ColumnTypeIcon type = { column . type } />
3051+ < span className = 'ml-1.5 min-w-0 overflow-clip text-ellipsis whitespace-nowrap font-medium text-[var(--text-primary)] text-small' >
3052+ { column . name }
3053+ </ span >
3054+ { sortDirection && (
3055+ < span className = 'ml-1 shrink-0' >
3056+ < SortDirectionIndicator direction = { sortDirection } />
3057+ </ span >
3058+ ) }
30463059 < DropdownMenu open = { menuOpen } onOpenChange = { setMenuOpen } >
30473060 < DropdownMenuTrigger asChild >
30483061 < button
30493062 type = 'button'
3050- onClick = { ( e ) => onColumnSelect ?.( colIndex , e . shiftKey ) }
3051- className = 'flex min-w-0 flex-1 cursor-pointer items-center px-2 py-[7px] outline-none'
3063+ onPointerDown = { ( e ) => e . stopPropagation ( ) }
3064+ onClick = { ( ) => onColumnSelect ?.( colIndex , false ) }
3065+ className = 'ml-1 flex shrink-0 cursor-pointer items-center opacity-0 outline-none transition-opacity group-hover:opacity-100'
30523066 >
3053- < ColumnTypeIcon type = { column . type } />
3054- < span className = 'ml-1.5 min-w-0 overflow-clip text-ellipsis whitespace-nowrap font-medium text-[var(--text-primary)] text-small' >
3055- { column . name }
3056- </ span >
3057- { sortDirection && (
3058- < span className = 'ml-1 shrink-0' >
3059- < SortDirectionIndicator direction = { sortDirection } />
3060- </ span >
3061- ) }
3062- < ChevronDown className = 'ml-1 h-[7px] w-[9px] shrink-0 text-[var(--text-muted)] opacity-0 transition-opacity group-hover:opacity-100' />
3067+ < ChevronDown className = 'h-[7px] w-[9px] text-[var(--text-muted)]' />
30633068 </ button >
30643069 </ DropdownMenuTrigger >
30653070 < DropdownMenuContent align = 'start' sideOffset = { 0 } >
0 commit comments