Skip to content

Commit 8f5bb2d

Browse files
committed
bump version 4.0.0
1 parent 7bd2739 commit 8f5bb2d

File tree

7 files changed

+125
-74
lines changed

7 files changed

+125
-74
lines changed

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
.DS_Store
2-
3-
node_modules
41
lib
52

63
# npm debug file
74
npm-debug.log
85

6+
node_modules
97
package-lock.json*

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
## master (unreleased)
22

3+
## 4.0.0
4+
5+
- Add support to changeable props. All props become responsive
6+
- Add simulateClick API for animate scroll programmatically
7+
- On childrenless Scrollchor render to `null`, useful for programmatically scroll
8+
- Add track to `window.location.bash` needed by browser history, `back/forward` buttons
9+
- Source refactored
10+
- Update Example and Demo
11+
- Update Doc
12+
313
## 3.0.0
414

515
- Add React 15.5.x support

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
ISC License
22

3-
Copyright (c) 2016 bySabi Files <[email protected]>
3+
Copyright (c) 2017 bySabi Files <[email protected]>
44

55
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
66

README.md

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
[![bitHound Overall Score](https://www.bithound.io/github/bySabi/react-scrollchor/badges/score.svg)](https://www.bithound.io/github/bySabi/react-scrollchor)
66
[![Donate](https://img.shields.io/badge/$-support-green.svg?style=flat-square)](https://paypal.me/bySabi/10)
77

8-
> A React component for scroll to `#hash` links with smooth animations. Scrollchor is a mix of `Scroll` and `Anchor`, a joke name for a useful component.
8+
> A React component for scroll to `#hash` links with smooth animations.
9+
> Scrollchor is a mix of `Scroll` and `Anchor`, a joke name for a useful component.
910
1011
See it in action:
1112
* demo [video](https://github.com/bySabi/react-scrollchor/blob/example/demo/scrollchor.webm?raw=true)
1213
* example [page](https://bySabi.github.com/react-scrollchor/) and [source code](https://github.com/bySabi/react-scrollchor/tree/example)
1314

1415

15-
## hash
16-
`hash` is the `id` of a HTML tag on current page
16+
`hash` is the `id` of a HTML tag on current page.
17+
18+
1719

1820
## Installation
1921

@@ -24,7 +26,7 @@ npm install react-scrollchor --save
2426
```
2527

2628
### Dependencies
27-
* User should provide its own `React` package
29+
* User should provide their own `React` package
2830

2931

3032
#### `fbjs` package
@@ -33,10 +35,10 @@ npm install react-scrollchor --save
3335

3436
## Usage
3537

36-
```javascript
38+
```js
3739
import Scrollchor from 'react-scrollchor';
3840
```
39-
```javascript
41+
```js
4042
export default (props) => (
4143
<Page>
4244

@@ -63,63 +65,92 @@ export default (props) => (
6365
</Page>
6466
```
6567
66-
# Prop types
67-
```javascript
68+
## Prop types
69+
```js
6870
propTypes: {
6971

7072
/**
71-
* id of tag scroll target node
72-
* - starting `#` can be omited
73-
* - this prop is required
73+
* id attribute of target DOM node
74+
* - `#` can be omited
7475
* - let it blank, `to = ''`, for scroll to page top
75-
*/
76+
* - this prop it's required
77+
*/
7678
to: PropTypes.string.isRequired,
7779

7880
/**
7981
* scroll smooth animation can be customize
80-
* Accepted options:
82+
* Accepted options, Ex: (default)
8183
* { offset: 0, duration: 400, easing: easeOutQuad }
8284
*/
8385
animate: PropTypes.object,
8486

8587
/**
8688
* callback function triggered before scroll to #hash
89+
* @param1 Received click event
8790
*/
8891
beforeAnimate: PropTypes.func,
8992

9093
/**
9194
* callback function triggered after scroll to #hash
95+
* @param1 Received click event
9296
*/
9397
afterAnimate: PropTypes.func
9498
}
9599
```
100+
### Resposive `props`
101+
Update `props` will re-render `Scrollchor` element
96102
97-
# Custom animation
103+
Ex: [updating "to" props](https://github.com/bySabi/react-scrollchor/blob/example/src/App.js#L28)
98104
99-
Animated behavior can be customize on each `#hash link` instance.
105+
## Custom animation
100106
101-
```javascript
107+
Animated behavior can be customize:
108+
109+
```js
102110
<Scrollchor to="#aboutus" animate={{offset: 20, duration: 600}} className="nav-link">Home</Scrollchor>
103111
```
104112
105-
## default animation config
106-
```javascript
113+
### default animation settings
114+
```js
107115
{ offset: 0, duration: 400, easing: easeOutQuad }
108116
```
109117
This setting is equivalent to default jQuery.animate `easing: swing`
110118
111-
## more `Easing` functions
119+
### more `Easing` functions
112120
113121
* [jQuery easings](http://api.jqueryui.com/easings/)
114122
* [Robert Penner's Easing Functions](http://robertpenner.com/easing/)
115123
* [Javascript source code](https://github.com/danro/jquery-easing/blob/master/jquery.easing.js)
116124
117-
## `before` and `after` animate callbacks
125+
126+
## `before` and `after` Animate callbacks
118127
Use this callbacks to trigger behaviours like, for example, update state, load async stuffs, etc.
119-
```javascript
128+
```js
120129
<Scrollchor to="#aboutus" afterAnimate={() => updateState(this)}>Home</Scrollchor>
121130
```
122131
132+
## Simulate click API
133+
Scrollchor include a dedicate API for init animate scroll programmatically that works like normal click events using `simulateClick()`
134+
135+
Ex: [using simulateClick](https://github.com/bySabi/react-scrollchor/blob/example/src/App.js#L17)
136+
137+
When used programmatically some use-case don't need `anchor tags`. On this cases use childrenless `Scrollchor`
138+
139+
### Childrenless `Scrollchor`
140+
This component will render `null` and the user it's reponsible of store the component [reference](https://facebook.github.io/react/docs/refs-and-the-dom.html)
141+
Ex: [(childrenless)](https://github.com/bySabi/react-scrollchor/blob/example/src/App.js#L24)
142+
```js
143+
<Scrollchor ref={ref => (this._back = ref)} to="_back" />
144+
```
145+
Ex: [(calling `simulateClick()` on childrenless `ref`)](https://github.com/bySabi/react-scrollchor/blob/example/src/App.js#L17)
146+
```js
147+
_afterAnimate = () => {
148+
this.setState({ to: this._iterator.next().value });
149+
setTimeout(() => this._back.simulateClick(), 1000);
150+
};
151+
```
152+
153+
123154
## Example
124155
125156
[react-scrollchor--example](https://github.com/bySabi/react-scrollchor/tree/example)

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-scrollchor",
3-
"version": "3.0.0",
3+
"version": "4.0.0",
44
"description": "A React component for scroll to #hash links with smooth animations",
55
"files": [
66
"lib"
@@ -16,7 +16,8 @@
1616
"testonly": "echo \"Error: no test specified\" && exit 1",
1717
"test": "npm run lint && npm run testonly",
1818
"prepare": "npm run build-npm",
19-
"clean-install": "rm -rf node_modules && rm -rf package-lock.json && npm cache clean --force && npm install"
19+
"clean-install": "npmclean && npm install",
20+
"format": "prettier-eslint --write 'src/**/*.js*'"
2021
},
2122
"keywords": [
2223
"react",
@@ -41,7 +42,6 @@
4142
"babel-preset-react": "6.x.x",
4243
"babel-preset-stage-3": "6.x.x",
4344
"babel-eslint": "7.x.x",
44-
"prettier-eslint-cli": "4.x.x",
4545
"semistandard": "*",
4646
"snazzy": "7.x.x",
4747
"fbjs": "*",

src/scrollchor.jsx

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
import React from 'react';
2-
import PropTypes from 'prop-types';
3-
import warning from 'fbjs/lib/warning';
4-
import { getScrollTop, setScrollTop, getOffsetTop } from './utils';
1+
import React from "react";
2+
import PropTypes from "prop-types";
3+
import { animateScroll } from "./utils";
54

65
export default class Scrollchor extends React.Component {
7-
constructor (props) {
6+
constructor(props) {
87
super(props);
9-
this._to = props.to && props.to.replace(/^#/, '') || '';
10-
const {
11-
offset = 0, duration = 400, easing = easeOutQuad
12-
} = props.animate || {};
13-
this._animate = { offset, duration, easing };
14-
this._beforeAnimate = props.beforeAnimate || function () {};
15-
this._afterAnimate = props.afterAnimate || function () {};
8+
this._setup(props);
9+
this.simulateClick = this._handleClick;
1610
}
1711

1812
static propTypes = {
@@ -26,47 +20,42 @@ export default class Scrollchor extends React.Component {
2620
afterAnimate: PropTypes.func
2721
};
2822

29-
handleClick = (event) => {
23+
_setup = props => {
24+
this._to = (props.to && props.to.replace(/^#/, "")) || "";
25+
const {
26+
// default animate object
27+
offset = 0,
28+
duration = 400,
29+
easing = easeOutQuad
30+
} =
31+
props.animate || {};
32+
this._animate = { offset, duration, easing };
33+
this._beforeAnimate = props.beforeAnimate || function() {};
34+
this._afterAnimate = props.afterAnimate || function() {};
35+
};
36+
37+
_handleClick = event => {
3038
this._beforeAnimate(event);
31-
event.preventDefault();
39+
event && event.preventDefault();
3240
animateScroll(this._to, this._animate);
3341
this._afterAnimate(event);
34-
}
42+
};
3543

36-
render () {
37-
const { to, animate, beforeAnimate, afterAnimate, ...props } = this.props; // eslint-disable-line no-unused-vars
38-
return <a {...props} href={'#' + this._to} onClick={this.handleClick} />;
44+
componentWillReceiveProps(props) {
45+
this._setup(props);
3946
}
40-
}
4147

42-
function animateScroll (id, animate) {
43-
const element = id ? document.getElementById(id) : document.body;
44-
warning(element, `Cannot find element: #${id}`);
45-
scrollTo(element, animate);
46-
}
47-
48-
function scrollTo (element, { offset, duration, easing }) {
49-
const start = getScrollTop();
50-
const to = getOffsetTop(element) + offset;
51-
const change = to - start;
52-
const increment = 20;
48+
render() {
49+
const { to, animate, beforeAnimate, afterAnimate, ...props } = this.props; // eslint-disable-line no-unused-vars
5350

54-
function animate (elapsedTime) {
55-
const elapsed = elapsedTime + increment;
56-
const position = easing(null, elapsed, start, change, duration);
57-
setScrollTop(position);
58-
if (elapsed < duration) {
59-
setTimeout(function () {
60-
animate(elapsed);
61-
}, increment);
62-
}
51+
return !this.props.children
52+
? null
53+
: <a {...props} href={"#" + this._to} onClick={this._handleClick} />;
6354
}
64-
65-
animate(0);
6655
}
6756

6857
// Default easing function
6958
// jQuery easing 'swing'
70-
function easeOutQuad (x, t, b, c, d) {
59+
function easeOutQuad(x, t, b, c, d) {
7160
return -c * (t /= d) * (t - 2) + b;
7261
}

src/utils.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,36 @@
1-
export function getScrollTop () {
2-
// jQuery => $('html, body').scrollTop
1+
import warning from "fbjs/lib/warning";
2+
3+
export function animateScroll(id, animate) {
4+
const element = id ? document.getElementById(id) : document.body;
5+
warning(element, `Cannot find element: #${id}`);
6+
7+
const { offset, duration, easing } = animate;
8+
const start = getScrollTop();
9+
const to = getOffsetTop(element) + offset;
10+
const change = to - start;
11+
12+
function animateFn(elapsedTime = 0) {
13+
const increment = 20;
14+
const elapsed = elapsedTime + increment;
15+
const position = easing(null, elapsed, start, change, duration);
16+
setScrollTop(position);
17+
elapsed < duration && setTimeout(() => animateFn(elapsed), increment);
18+
}
19+
20+
animateFn();
21+
window.location.hash = id;
22+
}
23+
24+
function getScrollTop() {
25+
// like jQuery -> $('html, body').scrollTop
326
return document.documentElement.scrollTop || document.body.scrollTop;
427
}
528

6-
export function setScrollTop (position) {
29+
function setScrollTop(position) {
730
document.documentElement.scrollTop = document.body.scrollTop = position;
831
}
932

10-
export function getOffsetTop (element) {
33+
function getOffsetTop(element) {
1134
const { top } = element.getBoundingClientRect();
1235
return top + getScrollTop();
1336
}

0 commit comments

Comments
 (0)