mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-30 18:39:51 +02:00
fix scrolling to selection
This commit is contained in:
@@ -3,7 +3,6 @@ import { Editor, Raw } from '../..'
|
||||
import Portal from 'react-portal'
|
||||
import React from 'react'
|
||||
import initialState from './state.json'
|
||||
import position from 'selection-position'
|
||||
|
||||
/**
|
||||
* Define a schema.
|
||||
@@ -185,7 +184,9 @@ class HoveringMenu extends React.Component {
|
||||
return
|
||||
}
|
||||
|
||||
const rect = position()
|
||||
const selection = window.getSelection()
|
||||
const range = selection.getRangeAt(0)
|
||||
const rect = range.getBoundingClientRect()
|
||||
menu.style.opacity = 1
|
||||
menu.style.top = `${rect.top + window.scrollY - menu.offsetHeight}px`
|
||||
menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px`
|
||||
|
@@ -16,6 +16,7 @@
|
||||
"is-empty": "^1.0.0",
|
||||
"keycode": "^2.1.2",
|
||||
"react-portal": "^3.0.0",
|
||||
"selection-is-backward": "^1.0.0",
|
||||
"type-of": "^2.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -63,7 +64,6 @@
|
||||
"react-router": "^2.5.1",
|
||||
"read-metadata": "^1.0.0",
|
||||
"read-yaml-promise": "^1.0.2",
|
||||
"selection-position": "^1.0.0",
|
||||
"slate-auto-replace-text": "^0.3.0",
|
||||
"slate-collapse-on-escape": "^0.2.0",
|
||||
"slate-soft-break": "^0.2.0",
|
||||
|
@@ -6,7 +6,8 @@ import ReactDOM from 'react-dom'
|
||||
import TYPES from '../constants/types'
|
||||
import Leaf from './leaf'
|
||||
import Void from './void'
|
||||
import scrollTo from '../utils/scroll-to'
|
||||
import getWindow from 'get-window'
|
||||
import scrollToSelection from '../utils/scroll-to-selection'
|
||||
|
||||
/**
|
||||
* Debug.
|
||||
@@ -207,7 +208,9 @@ class Node extends React.Component {
|
||||
if (!selection.hasEndIn(node)) return
|
||||
|
||||
const el = ReactDOM.findDOMNode(this)
|
||||
scrollTo(el)
|
||||
const window = getWindow(el)
|
||||
const native = window.getSelection()
|
||||
scrollToSelection(native)
|
||||
|
||||
this.debug('updateScroll', el)
|
||||
}
|
||||
|
37
src/utils/scroll-to-selection.js
Normal file
37
src/utils/scroll-to-selection.js
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
import getWindow from 'get-window'
|
||||
import isBackward from 'selection-is-backward'
|
||||
|
||||
/**
|
||||
* Scroll the current selection's focus point into view if needed.
|
||||
*
|
||||
* @param {Selection} selection
|
||||
*/
|
||||
|
||||
function scrollToSelection(selection) {
|
||||
const window = getWindow(selection.anchorNode)
|
||||
const backward = isBackward(selection)
|
||||
const range = selection.getRangeAt(0)
|
||||
const rect = range.getBoundingClientRect()
|
||||
const { innerWidth, innerHeight, scrollY, scrollX } = window
|
||||
const top = (backward ? rect.top : rect.bottom) + scrollY
|
||||
const left = (backward ? rect.left : rect.right) + scrollX
|
||||
|
||||
const x = left < scrollX || innerWidth + scrollX < left
|
||||
? left - innerWidth / 2
|
||||
: scrollX
|
||||
|
||||
const y = top < scrollY || innerHeight + scrollY < top
|
||||
? top - innerHeight / 2
|
||||
: scrollY
|
||||
|
||||
window.scrollTo(x, y)
|
||||
}
|
||||
|
||||
/**
|
||||
* Export.
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
|
||||
export default scrollToSelection
|
@@ -1,58 +0,0 @@
|
||||
|
||||
/**
|
||||
* Helps scroll the cursor into the middle of view if it isn't in view
|
||||
*/
|
||||
|
||||
import getWindow from 'get-window'
|
||||
|
||||
function scrollWindow(window, cursorTop, cursorLeft, cursorHeight) {
|
||||
let scrollX = window.scrollX
|
||||
let scrollY = window.scrollY
|
||||
const cursorBottom = cursorTop + cursorHeight
|
||||
|
||||
if (cursorTop < 0 || cursorBottom > window.innerHeight) {
|
||||
scrollY += cursorTop - window.innerHeight / 2 + cursorHeight / 2
|
||||
}
|
||||
|
||||
if (cursorLeft < 0 || cursorLeft > window.innerWidth) {
|
||||
scrollX += cursorLeft - window.innerWidth / 2
|
||||
}
|
||||
|
||||
window.scrollTo(scrollX, scrollY)
|
||||
}
|
||||
|
||||
function scrollTo(element) {
|
||||
const window = getWindow(element)
|
||||
const s = window.getSelection()
|
||||
if (s.rangeCount > 0) {
|
||||
const selectionRect = s.getRangeAt(0).getBoundingClientRect()
|
||||
let innerRect = selectionRect
|
||||
let wrapper = element
|
||||
const cursorHeight = innerRect.height
|
||||
let cursorTop = innerRect.top
|
||||
let cursorLeft = innerRect.left
|
||||
|
||||
while (wrapper != window.document.body) {
|
||||
const wrapperRect = wrapper.getBoundingClientRect()
|
||||
const currentY = cursorTop
|
||||
const cursorBottom = cursorTop + cursorHeight
|
||||
if (cursorTop < wrapperRect.top || cursorBottom > wrapperRect.top + wrapper.offsetHeight) {
|
||||
cursorTop = wrapperRect.top + wrapperRect.height / 2 - cursorHeight / 2
|
||||
wrapper.scrollTop += currentY - cursorTop
|
||||
}
|
||||
|
||||
const currentLeft = cursorLeft
|
||||
if (cursorLeft < wrapperRect.left || cursorLeft > wrapperRect.right) {
|
||||
cursorLeft = wrapperRect.left + wrapperRect.width / 2
|
||||
wrapper.scrollLeft += currentLeft - cursorLeft
|
||||
}
|
||||
|
||||
innerRect = wrapperRect
|
||||
wrapper = wrapper.parentNode
|
||||
}
|
||||
|
||||
scrollWindow(window, cursorTop, cursorLeft, cursorHeight)
|
||||
}
|
||||
}
|
||||
|
||||
export default scrollTo
|
Reference in New Issue
Block a user