mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-09-01 19:22:35 +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 Portal from 'react-portal'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import initialState from './state.json'
|
import initialState from './state.json'
|
||||||
import position from 'selection-position'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a schema.
|
* Define a schema.
|
||||||
@@ -185,7 +184,9 @@ class HoveringMenu extends React.Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const rect = position()
|
const selection = window.getSelection()
|
||||||
|
const range = selection.getRangeAt(0)
|
||||||
|
const rect = range.getBoundingClientRect()
|
||||||
menu.style.opacity = 1
|
menu.style.opacity = 1
|
||||||
menu.style.top = `${rect.top + window.scrollY - menu.offsetHeight}px`
|
menu.style.top = `${rect.top + window.scrollY - menu.offsetHeight}px`
|
||||||
menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px`
|
menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px`
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
"is-empty": "^1.0.0",
|
"is-empty": "^1.0.0",
|
||||||
"keycode": "^2.1.2",
|
"keycode": "^2.1.2",
|
||||||
"react-portal": "^3.0.0",
|
"react-portal": "^3.0.0",
|
||||||
|
"selection-is-backward": "^1.0.0",
|
||||||
"type-of": "^2.0.1"
|
"type-of": "^2.0.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@@ -63,7 +64,6 @@
|
|||||||
"react-router": "^2.5.1",
|
"react-router": "^2.5.1",
|
||||||
"read-metadata": "^1.0.0",
|
"read-metadata": "^1.0.0",
|
||||||
"read-yaml-promise": "^1.0.2",
|
"read-yaml-promise": "^1.0.2",
|
||||||
"selection-position": "^1.0.0",
|
|
||||||
"slate-auto-replace-text": "^0.3.0",
|
"slate-auto-replace-text": "^0.3.0",
|
||||||
"slate-collapse-on-escape": "^0.2.0",
|
"slate-collapse-on-escape": "^0.2.0",
|
||||||
"slate-soft-break": "^0.2.0",
|
"slate-soft-break": "^0.2.0",
|
||||||
|
@@ -6,7 +6,8 @@ import ReactDOM from 'react-dom'
|
|||||||
import TYPES from '../constants/types'
|
import TYPES from '../constants/types'
|
||||||
import Leaf from './leaf'
|
import Leaf from './leaf'
|
||||||
import Void from './void'
|
import Void from './void'
|
||||||
import scrollTo from '../utils/scroll-to'
|
import getWindow from 'get-window'
|
||||||
|
import scrollToSelection from '../utils/scroll-to-selection'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug.
|
* Debug.
|
||||||
@@ -207,7 +208,9 @@ class Node extends React.Component {
|
|||||||
if (!selection.hasEndIn(node)) return
|
if (!selection.hasEndIn(node)) return
|
||||||
|
|
||||||
const el = ReactDOM.findDOMNode(this)
|
const el = ReactDOM.findDOMNode(this)
|
||||||
scrollTo(el)
|
const window = getWindow(el)
|
||||||
|
const native = window.getSelection()
|
||||||
|
scrollToSelection(native)
|
||||||
|
|
||||||
this.debug('updateScroll', el)
|
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