@@ -71,7 +71,7 @@ export default class Demo extends Component {
{'{'}
{
- Object.entries(scroll)
+ Object.entries(this.state.scroll)
.filter(([key, value]) => typeof value !== 'function')
.filter(([key, value]) => typeof value !== 'object')
.map(([key, value]) =>
diff --git a/demo/index.css b/demo/index.css
index 4d6d5c4..f94eb93 100644
--- a/demo/index.css
+++ b/demo/index.css
@@ -41,6 +41,7 @@ nav {
left: 0;
width: 100%;
padding: 0.5em;
+ z-index: 10;
}
h1 {
diff --git a/package-lock.json b/package-lock.json
index c85221b..ed15e95 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
- "name": "react-skroll",
- "version": "0.7.1",
+ "name": "@arturmiglio/react-skroll",
+ "version": "0.7.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -2428,7 +2428,8 @@
"core-js": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz",
- "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg=="
+ "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==",
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -3681,15 +3682,13 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -3706,22 +3705,19 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -3852,8 +3848,7 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -3867,7 +3862,6 @@
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -3884,7 +3878,6 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -3893,15 +3886,13 @@
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz",
"integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -3922,7 +3913,6 @@
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -4011,8 +4001,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -4026,7 +4015,6 @@
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -4164,7 +4152,6 @@
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
diff --git a/package.json b/package.json
index 902c6e2..492215c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
- "name": "react-skroll",
+ "name": "@arturmiglio/react-skroll",
"description": "Reactive Scrolling",
- "version": "0.7.3",
+ "version": "0.8.0",
"main": "lib/index.js",
"scripts": {
"clean": "rm -rf dist lib && mkdir dist lib",
@@ -16,14 +16,14 @@
"test": "jest"
},
"license": "MIT",
- "homepage": "https://github.com/du5rte/react-skroll#readme",
+ "homepage": "https://github.com/arturmiglio/react-skroll#readme",
"repository": {
"type": "git",
- "url": "git+https://github.com/du5rte/react-skroll.git"
+ "url": "git+https://github.com/arturmiglio/react-skroll.git"
},
- "author": "Duarte Monteiro
(http://du5rte.com)",
+ "author": "Artur Miglio (http://arturmiglio.com)",
"bugs": {
- "url": "https://github.com/du5rte/react-skroll/issues"
+ "url": "https://github.com/arturmiglio/react-skroll/issues"
},
"keywords": [
"react",
@@ -70,5 +70,8 @@
"webpack": "^4.28.0",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
+ },
+ "directories": {
+ "lib": "lib"
}
}
diff --git a/src/Scroller.js b/src/Scroller.js
index 8ae039f..559d182 100644
--- a/src/Scroller.js
+++ b/src/Scroller.js
@@ -10,6 +10,9 @@ import scrollInitalState from './scrollInitalState'
import nodeToScrollState from './nodeToScrollState'
import nodeChildrenToScrollState from './nodeChildrenToScrollState'
+const START_TRANSLATE_3D = 'translate3d(0px,0px,0px)'
+const START_TRANSLATE = 'translate(0px,0px)'
+
const View = Globals.defaultElement
export default class Scroller extends Component {
@@ -26,17 +29,19 @@ export default class Scroller extends Component {
scroll: scrollInitalState
}
+ this.targetY = 0
+
// debounce is used to mimiques start, move and end events that don't have this functions
this.handleScrollStart = debounce(500, true, this.handleScrollStart)
this.handleResizeMove = throttle(50, this.handleResizeMove)
- this.handleScrollEnd = debounce(500, this.handleScrollEnd)
+ this.handleScrollEnd = debounce(50, this.handleScrollEnd)
this.handleWheelStart = debounce(100, true, this.handleWheelStart)
this.handleWheelEnd = debounce(100, this.handleWheelEnd)
this.handleResizeStart = debounce(250, true, this.handleResizeStart)
this.handleResizeEnd = debounce(250, this.handleResizeEnd)
- this.scrollToPrevDebounced = debounce(250, true, this.scrollToPrev)
- this.scrollToNextDebounced = debounce(250, true, this.scrollToNext)
+ this.scrollToPrevThrottled = throttle(700, true, this.scrollToPrev)
+ this.scrollToNextThrottled = throttle(700, true, this.scrollToNext)
this.controller = new Controller({ scroll: 0 })
}
@@ -50,7 +55,7 @@ export default class Scroller extends Component {
// add component to resize observer to detect changes on resize
this.resizeObserver = new ResizeObserver((entries, observer) => {
- if (this.state.ready) {
+ if (this.state.scroll.ready) {
this.handleResize()
} else {
this.setStateScroll({
@@ -147,8 +152,10 @@ export default class Scroller extends Component {
findChildOnView = () => {
const { children } = this.state.scroll
+ // return child on view, or the last one (when resizing ends up outside of the target)
+ const onView = children.find((child) => child.onView) || children[children.length - 1]
- return children.find((child) => child.onView)
+ return onView
}
findChildIndexOnView = () => {
@@ -159,8 +166,17 @@ export default class Scroller extends Component {
scrollToPosition = (position) => {
this.controller.update({
- scroll: position,
- onFrame: ({ scroll }) => (this.target.scrollTop = scroll),
+ scroll: -position,
+ config: config.default,
+ onFrame: ({ scroll }) => {
+ this.setState((prevState) => ({
+ scroll: {
+ ...prevState.scroll,
+ position: Math.abs(scroll),
+ }
+ }), this.handleScroll())
+ return this.target.style.transform = `translate3d(0, ${scroll}px, 0)`
+ },
})
}
@@ -218,6 +234,7 @@ export default class Scroller extends Component {
let newPosition = this.findChildOnView().start
this.scrollToPosition(newPosition)
+ this.targetY = newPosition
}
handleScroll = () => {
@@ -263,10 +280,6 @@ export default class Scroller extends Component {
handleWheel = (e) => {
const { autoScroll } = this.props
- if (autoScroll) {
- e.preventDefault()
- }
-
this.handleWheelStart(e)
this.handleWheelMove(e)
this.handleWheelEnd(e)
@@ -285,13 +298,15 @@ export default class Scroller extends Component {
const movingUpwards = e.deltaY > 0
const movingDownwards = e.deltaY < 0
- if (movingDownwards) this.scrollToPrevDebounced()
- if (movingUpwards) this.scrollToNextDebounced()
+ if (movingDownwards) this.scrollToPrevThrottled()
+ if (movingUpwards) this.scrollToNextThrottled()
}
}
handleWheelMove = (e) => {
- const { autoScroll } = this.props
+ const { autoScroll, autoFrame } = this.props
+ const { scroll } = this.state
+ const { viewHeight, scrollHeight } = scroll
if (autoScroll) {
const prev = this.state.deltaY
@@ -304,26 +319,33 @@ export default class Scroller extends Component {
const movingDownwards = next < 0
if (movingDownwards) {
- this.scrollToPrevDebounced()
+ this.scrollToPrevThrottled()
}
if (movingUpwards) {
- this.scrollToNextDebounced()
+ this.scrollToNextThrottled()
}
}
+ } else {
+ this.targetY += e.deltaY
+ this.targetY = Math.max(0, Math.min(this.targetY, scrollHeight - viewHeight))
+
+ this.scrollToPosition(this.targetY)
}
this.setState({ deltaY: e.deltaY })
}
handleWheelEnd = (e) => {
- const { autoFrame } = this.state.scroll
+ const { autoFrame } = this.props
this.setStateScrollEnd({
wheeling: false,
deltaY: null
})
- if (autoFrame) this.scrollToActive()
+ if (autoFrame) {
+ this.scrollToActive()
+ }
}
handleTouchStart = (e) => {
@@ -334,12 +356,15 @@ export default class Scroller extends Component {
}
handleTouchMove = (e) => {
- const { touches, originalPosition } = this.state.scroll
+ const { autoScroll } = this.props
+ const { touches, originalPosition, moving } = this.state.scroll
let distanceFromTouchStart = e.changedTouches[0].clientY - touches[0].clientY
let touchPosition = originalPosition - distanceFromTouchStart
- this.scrollToPosition(touchPosition)
+ if (!autoScroll) {
+ this.scrollToPosition(touchPosition)
+ }
}
handleTouchEnd = (e) => {
@@ -347,12 +372,16 @@ export default class Scroller extends Component {
const timeLapse = Date.now() - timeStamp
- if (timeLapse < 200) {
+ if (timeLapse < 500) {
const movingUpwards = e.changedTouches[0].clientY < touches[0].clientY
const movingDownwards = e.changedTouches[0].clientY > touches[0].clientY
- if (movingDownwards) this.scrollToPrev()
- if (movingUpwards) this.scrollToNext()
+ if (movingDownwards) {
+ this.scrollToPrevThrottled()
+ }
+ if (movingUpwards) {
+ this.scrollToNextThrottled()
+ }
} else {
this.scrollToActive()
}
@@ -378,6 +407,7 @@ export default class Scroller extends Component {
scroll={scroll}
/>