draggable-cursor.ts 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { Extension } from '@codemirror/state'
  2. import { EditorView, ViewPlugin } from '@codemirror/view'
  3. import { isInPrimarySelection } from './visual/utils/selection'
  4. const showDraggable = { style: 'cursor: move' }
  5. /**
  6. * An extension that changes the cursor style to "move" when the main mouse button
  7. * is held down on the primary selection for a short amount of time.
  8. */
  9. export const draggableCursor = (): Extension => {
  10. let timer: number | undefined
  11. const plugin = ViewPlugin.define(
  12. view => {
  13. return {
  14. isActive: false,
  15. set(isActive: boolean) {
  16. if (this.isActive !== isActive) {
  17. this.isActive = isActive
  18. view.update([])
  19. }
  20. },
  21. }
  22. },
  23. {
  24. eventHandlers: {
  25. mousedown(event, view) {
  26. if (timer) {
  27. window.clearTimeout(timer)
  28. }
  29. // single click with the main mouse button
  30. if (event.detail === 1 && event.button === 0) {
  31. timer = window.setTimeout(() => {
  32. timer = undefined
  33. if (isInPrimarySelection(event, view)) {
  34. this.set(true)
  35. }
  36. }, 50)
  37. }
  38. },
  39. mouseup() {
  40. if (timer) {
  41. window.clearTimeout(timer)
  42. }
  43. this.set(false)
  44. },
  45. dragstart() {
  46. if (timer) {
  47. window.clearTimeout(timer)
  48. }
  49. this.set(false)
  50. },
  51. },
  52. }
  53. )
  54. return [
  55. plugin,
  56. EditorView.contentAttributes.of(view =>
  57. view.plugin(plugin)?.isActive ? showDraggable : null
  58. ),
  59. ]
  60. }