feat(editor): drag result grid columns into the SQL editor
This commit is contained in:
1 parent
9e4fe8ce56
commit
ab4e747bf9
17 files changed
+911
-25
No files matched your search
@@ -97,14 +97,18 @@ import { analyzeMysqlRoutineSyntax, supportsMysqlRoutineSyntaxDiagnostics } from
|
||||
import {
|
||||
DBX_TABLE_REFERENCE_MIME,
|
||||
DBX_TABLE_REFERENCE_DROP_EVENT,
|
||||
DBX_TABLE_REFERENCE_HOVER_EVENT,
|
||||
DBX_TABLE_REFERENCE_DRAG_END_EVENT,
|
||||
activeTableReferencePayloadValue,
|
||||
clearActiveTableReferencePayload,
|
||||
hasTableReferencePayloadType,
|
||||
parseTableReferencePayload,
|
||||
tableReferenceInsertText,
|
||||
type QueryEditorTableReferenceDropDetail,
|
||||
type QueryEditorTableReferenceHoverDetail,
|
||||
type QueryEditorTableReferencePayload,
|
||||
} from "@/lib/editor/queryEditorTableDrop";
|
||||
import { isPointOverElementRoot } from "@/lib/editor/tableReferenceDragFeedback";
|
||||
import type { SqlHighlighter } from "@/lib/sql/sqlHighlighter";
|
||||
import { EDITOR_FONT_FAMILY_CSS_VAR, EDITOR_FONT_SIZE_CSS_VAR, editorDiagnosticColors, editorThemeAppearanceFor, loadEditorTheme, editorFontTheme, shellLineCommentTheme, sqlCompletionTheme, sqlSemanticHighlightTheme } from "@/lib/editor/editorThemes";
|
||||
import { createStatementGutterMarkerDom, shouldShowStatementGutter } from "@/lib/editor/codemirrorStatementGutter";
|
||||
@@ -3295,6 +3299,7 @@ function insertTableReferencePayload(currentView: EditorViewType, payload: Query
|
||||
userEvent: "input.drop",
|
||||
});
|
||||
clearActiveTableReferencePayload(payload);
|
||||
hideQueryEditorDropCaret();
|
||||
currentView.focus();
|
||||
return true;
|
||||
}
|
||||
@@ -3316,21 +3321,77 @@ function onTableReferenceDropEvent(event: Event) {
|
||||
if (!currentView || props.readOnly || !(event instanceof CustomEvent)) return;
|
||||
const detail = event.detail as QueryEditorTableReferenceDropDetail | undefined;
|
||||
if (!detail?.payload) return;
|
||||
const target = document.elementFromPoint(detail.clientX, detail.clientY);
|
||||
if (target instanceof Element && editorRef.value?.contains(target)) {
|
||||
// elementFromPoint 被透明覆盖层拦截时回退为编辑器根节点包围盒判定(见 isPointOverElementRoot)。
|
||||
if (isPointOverElementRoot(detail.clientX, detail.clientY, editorRef.value)) {
|
||||
insertTableReferencePayload(currentView, detail.payload, detail);
|
||||
}
|
||||
}
|
||||
|
||||
// --- 表引用拖拽悬停时的插入光标线(指针模拟拖拽经 window 事件驱动) ---
|
||||
const queryEditorDropCaret = ref<{ left: number; top: number; height: number } | null>(null);
|
||||
const queryEditorDropCaretStyle = computed(() => {
|
||||
const caret = queryEditorDropCaret.value;
|
||||
return caret ? { left: `${caret.left}px`, top: `${caret.top}px`, height: `${caret.height}px` } : {};
|
||||
});
|
||||
|
||||
function showQueryEditorDropCaretAt(clientX: number, clientY: number) {
|
||||
const currentView = view.value;
|
||||
if (!currentView || props.readOnly || !editorRef.value) {
|
||||
hideQueryEditorDropCaret();
|
||||
return;
|
||||
}
|
||||
let dropPos: number | null = null;
|
||||
try {
|
||||
dropPos = currentView.posAtCoords({ x: clientX, y: clientY });
|
||||
} catch {
|
||||
dropPos = null;
|
||||
}
|
||||
if (dropPos == null) {
|
||||
hideQueryEditorDropCaret();
|
||||
return;
|
||||
}
|
||||
const coords = currentView.coordsAtPos(dropPos);
|
||||
if (!coords) {
|
||||
hideQueryEditorDropCaret();
|
||||
return;
|
||||
}
|
||||
const rect = editorRef.value.getBoundingClientRect();
|
||||
queryEditorDropCaret.value = { left: coords.left - rect.left, top: coords.top - rect.top, height: Math.max(coords.bottom - coords.top, 0) };
|
||||
}
|
||||
|
||||
function hideQueryEditorDropCaret() {
|
||||
queryEditorDropCaret.value = null;
|
||||
}
|
||||
|
||||
function onTableReferenceHoverEvent(event: Event) {
|
||||
if (!(event instanceof CustomEvent)) return;
|
||||
const detail = event.detail as QueryEditorTableReferenceHoverDetail | undefined;
|
||||
if (!detail) return;
|
||||
// elementFromPoint 被透明覆盖层拦截时回退为编辑器根节点包围盒判定(见 isPointOverElementRoot)。
|
||||
if (!isPointOverElementRoot(detail.clientX, detail.clientY, editorRef.value)) {
|
||||
hideQueryEditorDropCaret();
|
||||
return;
|
||||
}
|
||||
showQueryEditorDropCaretAt(detail.clientX, detail.clientY);
|
||||
}
|
||||
|
||||
function onTableReferenceDragEndEvent() {
|
||||
hideQueryEditorDropCaret();
|
||||
}
|
||||
|
||||
function registerTableReferenceDropListener() {
|
||||
if (tableReferenceDropListenerRegistered) return;
|
||||
window.addEventListener(DBX_TABLE_REFERENCE_DROP_EVENT, onTableReferenceDropEvent);
|
||||
window.addEventListener(DBX_TABLE_REFERENCE_HOVER_EVENT, onTableReferenceHoverEvent);
|
||||
window.addEventListener(DBX_TABLE_REFERENCE_DRAG_END_EVENT, onTableReferenceDragEndEvent);
|
||||
tableReferenceDropListenerRegistered = true;
|
||||
}
|
||||
|
||||
function unregisterTableReferenceDropListener() {
|
||||
if (!tableReferenceDropListenerRegistered) return;
|
||||
window.removeEventListener(DBX_TABLE_REFERENCE_DROP_EVENT, onTableReferenceDropEvent);
|
||||
window.removeEventListener(DBX_TABLE_REFERENCE_HOVER_EVENT, onTableReferenceHoverEvent);
|
||||
window.removeEventListener(DBX_TABLE_REFERENCE_DRAG_END_EVENT, onTableReferenceDragEndEvent);
|
||||
tableReferenceDropListenerRegistered = false;
|
||||
}
|
||||
|
||||
@@ -5374,12 +5435,21 @@ onMounted(async () => {
|
||||
return recoverLargeTauriPaste(event, currentView);
|
||||
},
|
||||
dragover(event) {
|
||||
if (props.readOnly || !hasDroppedTableReference(event)) return false;
|
||||
if (props.readOnly || !hasDroppedTableReference(event)) {
|
||||
hideQueryEditorDropCaret();
|
||||
return false;
|
||||
}
|
||||
event.preventDefault();
|
||||
if (event.dataTransfer) event.dataTransfer.dropEffect = "copy";
|
||||
showQueryEditorDropCaretAt(event.clientX, event.clientY);
|
||||
return true;
|
||||
},
|
||||
dragleave() {
|
||||
hideQueryEditorDropCaret();
|
||||
return false;
|
||||
},
|
||||
drop(event, currentView) {
|
||||
hideQueryEditorDropCaret();
|
||||
return insertDroppedTableReference(currentView, event);
|
||||
},
|
||||
blur(_event, currentView) {
|
||||
@@ -6187,6 +6257,7 @@ defineExpose({
|
||||
"
|
||||
/>
|
||||
</CustomContextMenu>
|
||||
<div v-show="queryEditorDropCaret" data-query-editor-drop-caret class="pointer-events-none absolute z-20 w-0.5 rounded-full bg-primary/70" :style="queryEditorDropCaretStyle" />
|
||||
<EditorSearchPanel ref="searchPanelRef" :view="view" />
|
||||
<SqlExecutionTargetPicker v-if="pickerVisible" :candidates="pickerCandidates" :active-index="pickerActiveIndex" :anchor="pickerAnchor" @update:active-index="onPickerActiveIndexChange" @confirm="onPickerConfirm" @cancel="closePicker" />
|
||||
<DelimitedListDialog v-model:open="delimitedListOpen" :selected-text="delimitedListSelectedText" @confirm="applyDelimitedListResult" />
|
||||
|
||||
Reference in new issue
Block a user