Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | import { ViewPlugin, EditorView, type ViewUpdate } from '@codemirror/view' import { StateField, StateEffect, type Extension } from '@codemirror/state' import { useDragAndDrop } from '@/composables/ui/useDragAndDrop' /** * State field to track drop cursor position */ const dropCursorPos = StateField.define<number | null>({ create() { return null }, update(value, tr) { for (const effect of tr.effects) { if (effect.is(setDropCursor)) { return effect.value } } return value } }) const setDropCursor = StateEffect.define<number | null>() /** * CodeMirror plugin that integrates with global drag & drop system * Allows inserting dragged variables into the editor */ export const dragAndDropPlugin = (): Extension => { const { isDragging, dragData, endDrag } = useDragAndDrop() return [ dropCursorPos, ViewPlugin.fromClass( class { dropPos: number | null = null view: EditorView constructor(view: EditorView) { this.view = view // Add global mouseup listener to handle drop document.addEventListener('mouseup', this.handleGlobalMouseUp) } update(update: ViewUpdate) { // Update drop cursor if position changed const pos = update.state.field(dropCursorPos) if (pos !== this.dropPos) { this.dropPos = pos } } handleGlobalMouseUp = (e: MouseEvent) => { if (!isDragging.value || !dragData.value) return // Check if drop target is this editor const editorElement = this.view.dom const rect = editorElement.getBoundingClientRect() const isInEditor = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom if (isInEditor && this.dropPos !== null) { // Insert dragged data at cursor position const data = dragData.value.data this.view.dispatch({ changes: { from: this.dropPos, to: this.dropPos, insert: data }, selection: { anchor: this.dropPos + data.length } }) } // Clear drop cursor this.view.dispatch({ effects: setDropCursor.of(null) }) endDrag() } destroy() { document.removeEventListener('mouseup', this.handleGlobalMouseUp) } }, { eventHandlers: { mousemove(event, view) { if (!isDragging.value) return // Calculate drop position const pos = view.posAtCoords({ x: event.clientX, y: event.clientY }) if (pos !== null) { view.dispatch({ effects: setDropCursor.of(pos) }) } }, mouseleave(_event, view) { // Clear drop cursor when leaving editor view.dispatch({ effects: setDropCursor.of(null) }) } } } ) ] } export { dropCursorPos } |