mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-25 23:24:03 +00:00
Major additions: - Complete Next.js studio application with 1600+ components - Docker support (Dockerfile.combined, docker-compose.yml) - GCP deployment documentation and benchmarks - SQL benchmark scripts for performance testing - Sentry integration for monitoring - Comprehensive test suite and mocks Studio features: - Dashboard and admin interfaces - Data visualization components - Authentication and user management - API integration with RuVector backend - Static data and public assets 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
76 lines
2.1 KiB
TypeScript
76 lines
2.1 KiB
TypeScript
import { type DragEvent, useCallback, useState } from 'react'
|
|
|
|
import { type ImportDataFileDroppedEvent } from 'common/telemetry-constants'
|
|
import { flagInvalidFileImport } from 'components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.utils'
|
|
|
|
interface UseCsvFileDropOptions {
|
|
enabled: boolean
|
|
onFileDropped: (file: File) => void
|
|
onTelemetryEvent?: (eventName: ImportDataFileDroppedEvent['action']) => void
|
|
}
|
|
|
|
interface UseCsvFileDropReturn {
|
|
isDraggedOver: boolean
|
|
isValidFile: 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 [isValidFile, setIsValidFile] = 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)
|
|
setIsValidFile(item.type === 'text/csv')
|
|
} else if (event.type === 'dragleave' || event.type === 'drop') {
|
|
setIsDraggedOver(false)
|
|
setIsValidFile(false)
|
|
}
|
|
event.stopPropagation()
|
|
event.preventDefault()
|
|
},
|
|
[enabled, isDraggedOver, isValidFile]
|
|
)
|
|
|
|
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 {
|
|
isValidFile: isValidFile && isDraggedOver,
|
|
isDraggedOver,
|
|
onDragOver,
|
|
onFileDrop,
|
|
}
|
|
}
|