mirror of
https://github.com/supabase/supabase.git
synced 2026-10-07 02:15:05 +03:00
## Context Addresses an error when drag and dropping a CSV in the Table Editor when the table is empty, specifically on Safari leading to a `undefined is not an object (evaluating 'n.type')` error For context, Safari obscures the item data from the drag event and only exposes it on the drop event ([ref](https://github.com/mdn/browser-compat-data/issues/24898)) hence why this issue ## Changes involved Am opting to change the UX instead of fixing this browser specific behaviour - Ignore file validity when dragging, let the on drop handle validate the type and reject unsupported files instead - This is better either way as currently our Table Editor shows "CSV files only", when we actually also support TSV files - Also made a slight adjustment to the drag over UI - border around the grid empty area, rather than the whole grid - Before: <img width="1151" height="911" alt="image" src="https://github.com/user-attachments/assets/049199aa-86bc-4e88-8444-5a7ee236c8d0" /> - After: <img width="1150" height="912" alt="image" src="https://github.com/user-attachments/assets/698ca8f3-a326-4a82-b1b4-4448aa8d777a" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Simplified the empty-table display and CSV import interface for a more consistent user experience. * Import button and drag-and-drop hints now remain visible when the table is empty, removing prior conditional hiding during drag. * Streamlined empty-state styling and messaging for a cleaner, more predictable appearance. * **Tests** * Updated end-to-end test expectations to reflect the persistent empty-state message during drag-over. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
71 lines
1.9 KiB
TypeScript
71 lines
1.9 KiB
TypeScript
import { type ImportDataFileDroppedEvent } from 'common/telemetry-constants'
|
|
import { flagInvalidFileImport } from 'components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.utils'
|
|
import { useCallback, useState, type DragEvent } from 'react'
|
|
|
|
interface UseCsvFileDropOptions {
|
|
enabled: boolean
|
|
onFileDropped: (file: File) => void
|
|
onTelemetryEvent?: (eventName: ImportDataFileDroppedEvent['action']) => void
|
|
}
|
|
|
|
interface UseCsvFileDropReturn {
|
|
isDraggedOver: boolean
|
|
onDragOver: (event: DragEvent<HTMLDivElement>) => void
|
|
onFileDrop: (event: DragEvent<HTMLDivElement>) => void
|
|
}
|
|
|
|
export function useCsvFileDrop({
|
|
enabled,
|
|
onFileDropped,
|
|
onTelemetryEvent,
|
|
}: UseCsvFileDropOptions): UseCsvFileDropReturn {
|
|
const [isDraggedOver, setIsDraggedOver] = useState(false)
|
|
|
|
const onDragOver = useCallback(
|
|
(event: DragEvent<HTMLDivElement>) => {
|
|
if (!enabled) return
|
|
|
|
const [item] = event.dataTransfer.items
|
|
|
|
// ignore non files drop, like column headers
|
|
if (item && item.kind !== 'file') return
|
|
|
|
if (event.type === 'dragover' && !isDraggedOver) {
|
|
setIsDraggedOver(true)
|
|
} else if (event.type === 'dragleave' || event.type === 'drop') {
|
|
setIsDraggedOver(false)
|
|
}
|
|
event.stopPropagation()
|
|
event.preventDefault()
|
|
},
|
|
[enabled, isDraggedOver]
|
|
)
|
|
|
|
const onFileDrop = useCallback(
|
|
(event: DragEvent<HTMLDivElement>) => {
|
|
if (!enabled) return
|
|
|
|
onDragOver(event)
|
|
|
|
const [file] = event.dataTransfer.files
|
|
const [item] = event.dataTransfer.items
|
|
|
|
// ignore non files drop, like column headers
|
|
if (item && item.kind !== 'file') return
|
|
|
|
if (flagInvalidFileImport(file)) return
|
|
|
|
onFileDropped(file)
|
|
|
|
onTelemetryEvent?.('import_data_dropzone_file_added')
|
|
},
|
|
[enabled, onDragOver, onFileDropped, onTelemetryEvent]
|
|
)
|
|
|
|
return {
|
|
isDraggedOver,
|
|
onDragOver,
|
|
onFileDrop,
|
|
}
|
|
}
|