Коммит
14cb562c76
|
@ -5,7 +5,7 @@
|
|||
<p align="center">Official React wrapper for the <a target="_blank" href="https://github.com/alvarotrigo/fullPage.js/">fullpage.js library</a></p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/react--fullpage-v0.1.2-brightgreen.svg" alt="react-fullpage version" />
|
||||
<img src="https://img.shields.io/badge/react--fullpage-v0.1.3-brightgreen.svg" alt="react-fullpage version" />
|
||||
</p>
|
||||
|
||||
- [Demo online](https://alvarotrigo.com/react-fullpage/) | [CodeSandbox](https://codesandbox.io/s/m34yq5q0qx)
|
||||
|
|
|
@ -25,52 +25,44 @@ class ReactFullpage extends React.Component {
|
|||
throw new Error('must provide render prop to <ReactFullpage />');
|
||||
}
|
||||
|
||||
this.state = { initialized: false };
|
||||
this.state = {
|
||||
initialized: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { $, v2compatible = false } = this.props;
|
||||
const opts = this.buildOptions();
|
||||
|
||||
if (v2compatible) {
|
||||
if (!$ || $ instanceof window.jQuery === false) {
|
||||
throw new Error('Must provide $ (jQuery) as a prop if using v2 API');
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
// eslint-disable-line
|
||||
$('#fullpage').fullpage(opts);
|
||||
});
|
||||
} else if (Fullpage) {
|
||||
if (Fullpage) {
|
||||
this.init(opts);
|
||||
this.markInitialized();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevState.initialized === this.state.initialized) {
|
||||
const newSectionCount = this.getSectionCount();
|
||||
const newSlideCount = this.getSlideCount();
|
||||
const { sectionCount, slideCount } = this.state;
|
||||
|
||||
/* TODO: add a list of fullpage.js specific props to subscribe too
|
||||
similar to how callbacks are handled)
|
||||
*/
|
||||
|
||||
if (this.props.sectionsColor !== prevProps.sectionsColor) {
|
||||
console.log('rebuilding due to a change in fullpage.js props');
|
||||
// NOTE: if fullpage props have changed we need to rebuild
|
||||
this.destroy();
|
||||
this.init(this.buildOptions());
|
||||
return;
|
||||
}
|
||||
|
||||
const { props, fpUtils } = this;
|
||||
const slideSelector = props.slideSelector || '.slide';
|
||||
const sectionSelector = props.sectionSelector || '.section';
|
||||
|
||||
const activeSection = document.querySelector(`${sectionSelector}.active`);
|
||||
const activeSectionIndex = activeSection ? fpUtils.index(activeSection): -1;
|
||||
const activeSlide = document.querySelector(`${sectionSelector}.active${slideSelector}.active`);
|
||||
const activeSlideIndex = activeSlide ? fpUtils.index(activeSlide) : -1;
|
||||
if (sectionCount === newSectionCount && slideCount === newSlideCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('rebuilding due to a change in fullpage.js sections/slides');
|
||||
// NOTE: if sections have changed we need to rebuild
|
||||
this.destroy();
|
||||
|
||||
if (activeSectionIndex > -1) {
|
||||
fpUtils.addClass(document.querySelectorAll(sectionSelector)[activeSectionIndex], 'active');
|
||||
}
|
||||
|
||||
if (activeSlideIndex > -1) {
|
||||
fpUtils.addClass(activeSlide, 'active');
|
||||
}
|
||||
|
||||
this.init(this.buildOptions());
|
||||
}
|
||||
|
||||
|
@ -78,6 +70,20 @@ class ReactFullpage extends React.Component {
|
|||
this.destroy();
|
||||
}
|
||||
|
||||
getSectionCount() {
|
||||
const { sectionSelector = '.section' } = this.props;
|
||||
return document
|
||||
.querySelectorAll(sectionSelector)
|
||||
.length;
|
||||
}
|
||||
|
||||
getSlideCount() {
|
||||
const { slideSelector = '.slide' } = this.props;
|
||||
return document
|
||||
.querySelectorAll(slideSelector)
|
||||
.length;
|
||||
}
|
||||
|
||||
init(opts) {
|
||||
new Fullpage('#fullpage', opts); // eslint-disable-line
|
||||
this.fullpageApi = window.fullpage_api;
|
||||
|
@ -87,22 +93,34 @@ class ReactFullpage extends React.Component {
|
|||
|
||||
destroy() {
|
||||
// NOTE: need to check for init to support SSR
|
||||
if (!this.state.initialized) return;
|
||||
|
||||
this.fullpageApi.destroy('all');
|
||||
if (typeof window !== 'undefined') {
|
||||
this
|
||||
.fullpageApi
|
||||
.destroy('all');
|
||||
}
|
||||
}
|
||||
|
||||
markInitialized() {
|
||||
this.setState({ initialized: true });
|
||||
this.setState({
|
||||
initialized: true,
|
||||
sectionCount: this.getSectionCount(),
|
||||
slideCount: this.getSlideCount(),
|
||||
});
|
||||
}
|
||||
|
||||
buildOptions() {
|
||||
const filterCb = key => !!Object.keys(this.props).find(cb => cb === key);
|
||||
const filterCb = key => !!Object
|
||||
.keys(this.props)
|
||||
.find(cb => cb === key);
|
||||
const registered = fullpageCallbacks.filter(filterCb);
|
||||
const listeners = registered.reduce((result, key) => {
|
||||
const agg = { ...result };
|
||||
const agg = {
|
||||
...result,
|
||||
};
|
||||
agg[key] = (...args) => {
|
||||
const newArgs = [key, ...args];
|
||||
const newArgs = [
|
||||
key, ...args,
|
||||
];
|
||||
this.update(...newArgs);
|
||||
};
|
||||
|
||||
|
@ -116,10 +134,10 @@ class ReactFullpage extends React.Component {
|
|||
}
|
||||
|
||||
update(lastEvent, ...args) {
|
||||
const { v2compatible = false } = this.props;
|
||||
|
||||
let state = {
|
||||
...this.state,
|
||||
sectionCount: this.getSectionCount(),
|
||||
getSlideCount: this.getSlideCount(),
|
||||
};
|
||||
|
||||
const makeState = callbackParameters => ({
|
||||
|
@ -128,89 +146,43 @@ class ReactFullpage extends React.Component {
|
|||
lastEvent,
|
||||
});
|
||||
|
||||
const fromArgs = argList =>
|
||||
argList.reduce((result, key, i) => {
|
||||
const value = args[i];
|
||||
result[key] = value; // eslint-disable-line
|
||||
return result;
|
||||
}, {});
|
||||
const fromArgs = argList => argList.reduce((result, key, i) => {
|
||||
const value = args[i];
|
||||
result[key] = value; // eslint-disable-line
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
// TODO: change all fromArgs to constants After-*
|
||||
if (v2compatible) {
|
||||
// NOTE: remapping callback args for v2
|
||||
// https://github.com/alvarotrigo/fullPage.js#callbacks
|
||||
switch (lastEvent) {
|
||||
// After-*
|
||||
case 'afterLoad':
|
||||
state = makeState(fromArgs(['anchorLink', 'index']));
|
||||
break;
|
||||
// NOTE: remapping callback args to v3
|
||||
// https://github.com/alvarotrigo/fullPage.js#callbacks
|
||||
switch (lastEvent) {
|
||||
// After-*
|
||||
case 'afterLoad':
|
||||
state = makeState(fromArgs(['origin', 'destination', 'direction']));
|
||||
break;
|
||||
|
||||
case 'afterResponsive':
|
||||
state = makeState(fromArgs(['isResponsive']));
|
||||
break;
|
||||
case 'afterResize':
|
||||
state = makeState(fromArgs(['']));
|
||||
break;
|
||||
|
||||
case 'afterSlideLoad':
|
||||
state = makeState(fromArgs(['anchorLink', 'index', 'slideAnchor', 'slideIndex']));
|
||||
break;
|
||||
case 'afterResponsive':
|
||||
state = makeState(fromArgs(['isResponsive']));
|
||||
break;
|
||||
|
||||
case 'afterSlideLoad':
|
||||
state = makeState(fromArgs(['section', 'origin', 'destination', 'direction']));
|
||||
break;
|
||||
|
||||
// On-*
|
||||
case 'onLeave':
|
||||
state = makeState(fromArgs(['index', 'nextIndex', 'direction']));
|
||||
break;
|
||||
case 'onLeave':
|
||||
state = makeState(fromArgs(['origin', 'destination', 'direction']));
|
||||
break;
|
||||
|
||||
case 'onSlideLeave':
|
||||
state = makeState(fromArgs([
|
||||
'anchorLink',
|
||||
'index',
|
||||
'slideIndex',
|
||||
'direction',
|
||||
'nextSlideIndex',
|
||||
]));
|
||||
break;
|
||||
case 'onSlideLeave':
|
||||
state = makeState(fromArgs(['section', 'origin', 'slideIndex', 'destination', 'direction']));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// NOTE: remapping callback args to v3
|
||||
// https://github.com/alvarotrigo/fullPage.js#callbacks
|
||||
switch (lastEvent) {
|
||||
// After-*
|
||||
case 'afterLoad':
|
||||
state = makeState(fromArgs(['origin', 'destination', 'direction']));
|
||||
break;
|
||||
|
||||
// TODO: update accoding to new API
|
||||
case 'afterResize':
|
||||
state = makeState(fromArgs(['']));
|
||||
break;
|
||||
|
||||
case 'afterResponsive':
|
||||
state = makeState(fromArgs(['isResponsive']));
|
||||
break;
|
||||
|
||||
case 'afterSlideLoad':
|
||||
state = makeState(fromArgs(['section', 'origin', 'destination', 'direction']));
|
||||
break;
|
||||
|
||||
// On-*
|
||||
case 'onLeave':
|
||||
state = makeState(fromArgs(['origin', 'destination', 'direction']));
|
||||
break;
|
||||
|
||||
case 'onSlideLeave':
|
||||
state = makeState(fromArgs([
|
||||
'section',
|
||||
'origin',
|
||||
'slideIndex',
|
||||
'destination',
|
||||
'direction',
|
||||
]));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this.setState(state, () => {
|
||||
|
@ -221,10 +193,7 @@ class ReactFullpage extends React.Component {
|
|||
render() {
|
||||
return (
|
||||
<div id="fullpage">
|
||||
{this.state.initialized
|
||||
? this.props.render(this)
|
||||
: <div className="section fp-section active" />
|
||||
}
|
||||
{this.props.render(this)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
const Wrapper = ({ children }) => <Fragment>{children}</Fragment>;
|
||||
const Wrapper = ({ children }) => <Fragment>{children}</Fragment>
|
||||
|
||||
export default Wrapper;
|
||||
|
|
|
@ -11,7 +11,6 @@ export default (() => {
|
|||
exported = require('./ReactFullpageShell').default;
|
||||
}
|
||||
|
||||
console.log({ exported })
|
||||
exported.Wrapper = Wrapper;
|
||||
|
||||
return exported;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -9,9 +9,6 @@
|
|||
<meta name="keywords" content="fullpage, react wrapper,react.js,react-fullpage,react-component,adapter,component,react,sections,slides,scrolling,snap,snapping,scroll">
|
||||
<meta name="Resource-type" content="Document" />
|
||||
|
||||
<!-- fullpage.js stylesheet -->
|
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/fullpage.js@3.0.1/dist/fullpage.min.css">
|
||||
|
||||
<!-- custom styles for the example -->
|
||||
<style>
|
||||
body {
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -14,7 +14,9 @@
|
|||
"babel-loader": "^7.1.5",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"css-loader": "^1.0.1",
|
||||
"html-loader": "^0.5.5",
|
||||
"style-loader": "^0.23.1",
|
||||
"webpack": "^4.20.2",
|
||||
"webpack-cli": "^3.1.1"
|
||||
}
|
||||
|
|
|
@ -1,47 +1,110 @@
|
|||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ReactFullpage from '../../components';
|
||||
|
||||
import 'fullpage.js/vendors/scrolloverflow'; // Optional. When using scrollOverflow:true
|
||||
//import 'fullpage.js/vendors/scrolloverflow'; // Optional. When using scrollOverflow:true
|
||||
|
||||
const originalColors = ['#282c34', '#ff5f45', '#0798ec'];
|
||||
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
sectionsColor: [...originalColors],
|
||||
fullpages: [
|
||||
{
|
||||
text: 'section 1',
|
||||
id: Math.random(),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
class Fullpage extends React.Component {
|
||||
onLeave(origin, destination, direction) {
|
||||
// arguments are mapped in order of fullpage.js callback arguments
|
||||
// do something with the event
|
||||
console.log('onLeave', { origin, destination, direction });
|
||||
// arguments are mapped in order of fullpage.js callback arguments do something
|
||||
// with the event
|
||||
}
|
||||
|
||||
handleChangeColors() {
|
||||
const newColors = this.state.sectionsColor[0] === 'yellow' ? [...originalColors] : ['yellow', 'blue', 'white']
|
||||
this.setState({
|
||||
sectionsColor: newColors,
|
||||
});
|
||||
}
|
||||
|
||||
handleAddSection() {
|
||||
this.setState((state) => {
|
||||
const { fullpages } = state;
|
||||
const { length } = fullpages;
|
||||
fullpages.push({
|
||||
text: `section ${length + 1}`,
|
||||
id: Math.random(),
|
||||
});
|
||||
|
||||
return {
|
||||
fullpages: [...fullpages],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
handleRemoveSection() {
|
||||
this.setState((state) => {
|
||||
const { fullpages } = state;
|
||||
const newPages = [...fullpages];
|
||||
newPages.pop();
|
||||
|
||||
return { fullpages: newPages };
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ReactFullpage
|
||||
anchors={['firstPage', 'secondPage', 'thirdPage']}
|
||||
sectionsColor={['#282c34', '#ff5f45', '#0798ec']}
|
||||
onLeave={this.onLeave.bind(this)}
|
||||
render={({ state, fullpageApi }) => {
|
||||
console.log('render prop change', state);
|
||||
const { fullpages } = this.state;
|
||||
|
||||
return (
|
||||
if (!fullpages.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const Menu = () => (
|
||||
<div
|
||||
className="menu"
|
||||
style={{
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
zIndex: 100,
|
||||
}}
|
||||
>
|
||||
<ul>
|
||||
<li>
|
||||
<button onClick={() => this.handleAddSection()}>+ Section</button>
|
||||
<button onClick={() => this.handleRemoveSection()}>- Section</button>
|
||||
<button onClick={() => this.handleChangeColors()}>Change colors</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<Menu />
|
||||
<ReactFullpage
|
||||
navigation
|
||||
onLeave={this.onLeave.bind(this)}
|
||||
sectionsColor={this.state.sectionsColor}
|
||||
render={comp => console.log('render prop change') || (
|
||||
<ReactFullpage.Wrapper>
|
||||
<div className="section">
|
||||
<h3>Section 1</h3>
|
||||
<button onClick={() => fullpageApi.moveSectionDown()}>
|
||||
Move down
|
||||
</button>
|
||||
</div>
|
||||
<div className="section">
|
||||
<div className="slide"> Slide 1 </div>
|
||||
<div className="slide"> Slide 2 </div>
|
||||
<div className="slide"> Slide 3 </div>
|
||||
</div>
|
||||
<div className="section">
|
||||
<h3>Section 3</h3>
|
||||
</div>
|
||||
{fullpages.map(({ text, id }) => (
|
||||
<div key={id} className="section">
|
||||
<h1>{text}</h1>
|
||||
</div>
|
||||
))}
|
||||
</ReactFullpage.Wrapper>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<Fullpage />, document.getElementById('react-root'));
|
||||
const rootElement = document.getElementById('react-root');
|
||||
ReactDOM.render(<App />, rootElement);
|
|
@ -14,6 +14,8 @@ module.exports = {
|
|||
|
||||
module: {
|
||||
rules: [
|
||||
|
||||
// BABEL
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
|
@ -21,6 +23,20 @@ module.exports = {
|
|||
loader: 'babel-loader',
|
||||
},
|
||||
},
|
||||
|
||||
// STYLES
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@fullpage/react-fullpage",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"description": "Official react wrapper for fullPage.js",
|
||||
"author": "cmswalker",
|
||||
"contributors": [
|
||||
|
|
Загрузка…
Ссылка в новой задаче