├── .gitignore ├── README.md ├── examples ├── README.md ├── components │ ├── App.jsx │ ├── Home.jsx │ ├── Menu.jsx │ ├── modifiers │ │ └── Draggable │ │ │ └── App.jsx │ ├── surfaces │ │ ├── CanvasSurface │ │ │ └── App.jsx │ │ ├── ContainerSurface │ │ │ └── App.jsx │ │ ├── ImageSurface │ │ │ └── App.jsx │ │ └── VideoSurface │ │ │ └── App.jsx │ ├── test │ │ ├── Animations │ │ │ ├── App.jsx │ │ │ ├── BouncyBox.jsx │ │ │ ├── CrazyBox.jsx │ │ │ ├── DraggableBox.jsx │ │ │ ├── DroppingBox.jsx │ │ │ ├── RotatingBox.jsx │ │ │ └── index.js │ │ ├── CommentBox │ │ │ ├── App.jsx │ │ │ ├── Comment.jsx │ │ │ ├── CommentBox.jsx │ │ │ ├── CommentForm.jsx │ │ │ └── CommentList.jsx │ │ ├── HelloWorld │ │ │ └── App.jsx │ │ ├── HelloWorldDynamic │ │ │ └── App.jsx │ │ ├── Layout │ │ │ └── App.jsx │ │ ├── ReactNode │ │ │ └── App.jsx │ │ └── Seed │ │ │ └── App.jsx │ └── views │ │ ├── Deck │ │ └── App.jsx │ │ ├── EdgeSwapper │ │ └── App.jsx │ │ ├── FlexibleLayout │ │ └── App.jsx │ │ ├── Flipper │ │ └── App.jsx │ │ ├── GridLayout │ │ └── App.jsx │ │ ├── HeaderFooterLayout │ │ └── App.jsx │ │ ├── Lightbox │ │ └── App.jsx │ │ ├── RenderController │ │ └── App.jsx │ │ ├── ScrollContainer │ │ └── App.jsx │ │ ├── Scrollview │ │ └── App.jsx │ │ ├── SequentialLayout │ │ └── App.jsx │ │ └── SizeAwareView │ │ └── App.jsx ├── index.html ├── index.js ├── lib │ ├── createContent.jsx │ └── overscroll.js ├── routes.jsx ├── routes │ └── Pass.jsx ├── styles │ └── index.less ├── webpack.config.js └── webpack.config.prod.js ├── gulpfile.js ├── package.json ├── src ├── core │ ├── Context.jsx │ ├── Engine.js │ ├── Modifier.jsx │ ├── RenderNode.jsx │ ├── Surface.jsx │ └── View.jsx ├── index.js ├── lib │ ├── FamousComponent.js │ ├── FamousConstants.js │ ├── FamousMixin.js │ ├── FamousNodeMixin.js │ ├── FamousPatch.js │ ├── FamousScheduler.js │ ├── FamousUtil.js │ └── ReactNode.jsx ├── modifiers │ ├── Draggable.jsx │ ├── ModifierChain.jsx │ └── StateModifier.jsx ├── surfaces │ ├── CanvasSurface.jsx │ ├── ContainerSurface.jsx │ ├── FormContainerSurface.jsx │ ├── ImageSurface.jsx │ ├── InputSurface.jsx │ ├── SubmitInputSurface.jsx │ ├── TextareaSurface.jsx │ └── VideoSurface.jsx └── views │ ├── ContextualView.jsx │ ├── Deck.jsx │ ├── DrawerLayout.jsx │ ├── EdgeSwapper.jsx │ ├── FlexibleLayout.jsx │ ├── Flipper.jsx │ ├── GridLayout.jsx │ ├── HeaderFooterLayout.jsx │ ├── Lightbox.jsx │ ├── RenderController.jsx │ ├── ScrollContainer.jsx │ ├── Scroller.jsx │ ├── Scrollview.jsx │ ├── SequentialLayout.jsx │ └── SizeAwareView.jsx └── tools └── publish ├── amd ├── README.md └── package.json ├── cjs ├── README.md └── package.json └── examples └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | /node_modules/ 3 | /npm-debug.log 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-famous 2 | 3 | 4 | Add [Famo.us](http://famo.us) interactions and animations to any [React](http://facebook.github.io/react/) application and build **Famo.us** applications with **React**. 5 | 6 | Using `react-famous`, you can: 7 | 8 | * Create **Famo.us** apps using familiar **React** component specs and lifecycle. 9 | * Bring rich **Famo.us** animations to new or existing **React** apps. 10 | * Easily integrate **Famo.us** and **React** apps. 11 | 12 | `react-famous` is similar to [famous-angular](https://github.com/Famous/famous-angular) for [AngularJS](https://angularjs.org/) and [famous-views](http://famous-views.meteor.com/) for [Meteor](https://www.meteor.com/). 13 | 14 | 15 | ## Demo 16 | 17 | * [Examples App](http://react-famous.github.io/) ([source code](https://github.com/pilwon/react-famous/tree/master/examples)) 18 | 19 | 20 | ## Requirements 21 | 22 | * [Famo.us](http://famo.us) v0.3.5 23 | * [React](http://facebook.github.io/react/) v0.13 24 | 25 | 26 | ## Installation 27 | 28 | npm install react-famous 29 | 30 | 31 | ## Try it out 32 | 33 | * [react-famous-seed](https://github.com/pilwon/react-famous-seed): seed project for `react-famous` 34 | 35 | ### Running examples locally 36 | 37 | git clone git@github.com:pilwon/react-famous.git 38 | cd react-famous 39 | npm install 40 | gulp examples 41 | 42 | * [http://localhost:8080](http://localhost:8080) 43 | 44 | 45 | ## License 46 | 47 |
48 | The MIT License (MIT)
49 | 
50 | Copyright (c) 2015 Pilwon Huh
51 | 
52 | Permission is hereby granted, free of charge, to any person obtaining a copy
53 | of this software and associated documentation files (the "Software"), to deal
54 | in the Software without restriction, including without limitation the rights
55 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56 | copies of the Software, and to permit persons to whom the Software is
57 | furnished to do so, subject to the following conditions:
58 | 
59 | The above copyright notice and this permission notice shall be included in
60 | all copies or substantial portions of the Software.
61 | 
62 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
65 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68 | THE SOFTWARE.
69 | 
70 | 71 | [![Analytics](https://ga-beacon.appspot.com/UA-47034562-26/react-famous/readme?pixel)](https://github.com/pilwon/react-famous) 72 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | gulp examples --port 8080 4 | 5 | * [http://localhost:8080](http://localhost:8080) 6 | -------------------------------------------------------------------------------- /examples/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { RouteHandler } from 'react-router'; 3 | 4 | import Menu from './Menu'; 5 | 6 | const EXAMPLES = { 7 | modifiers: [ 8 | 'Draggable' 9 | ], 10 | surfaces: [ 11 | 'CanvasSurface', 12 | 'ContainerSurface', 13 | 'ImageSurface', 14 | 'VideoSurface' 15 | ], 16 | views: [ 17 | 'Deck', 18 | 'EdgeSwapper', 19 | 'FlexibleLayout', 20 | 'Flipper', 21 | 'GridLayout', 22 | 'HeaderFooterLayout', 23 | 'Lightbox', 24 | 'RenderController', 25 | 'ScrollContainer', 26 | 'Scrollview', 27 | 'SequentialLayout', 28 | 'SizeAwareView' 29 | ], 30 | test: [ 31 | 'Animations', 32 | 'CommentBox', 33 | 'HelloWorld', 34 | 'HelloWorldDynamic', 35 | 'Layout', 36 | 'ReactNode', 37 | 'Seed' 38 | ] 39 | }; 40 | 41 | export default class extends React.Component { 42 | render() { 43 | return ( 44 |
45 | 46 |
47 | 48 |
49 |
50 | ); 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /examples/components/Home.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import Easing from 'famous/transitions/Easing'; 3 | import Timer from 'famous/utilities/Timer'; 4 | import React from 'react'; 5 | import Context from 'react-famous/core/Context'; 6 | import Modifier from 'react-famous/core/Modifier'; 7 | import Surface from 'react-famous/core/Surface'; 8 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 9 | import StateModifier from 'react-famous/modifiers/StateModifier'; 10 | 11 | class Home extends React.Component { 12 | componentDidMount() { 13 | let stateModifier = this.refs.stateModifier.getFamous(); 14 | 15 | FamousScheduler.schedule(() => { 16 | function animate() { 17 | stateModifier.halt(); 18 | stateModifier.setTransform(Transform.translate(-50, 0), { 19 | duration: 250 20 | }, () => { 21 | stateModifier.setTransform(Transform.translate(0, 0), { 22 | duration: 500 23 | }, () => { 24 | Timer.setTimeout(animate, 1250); 25 | }); 26 | }); 27 | } 28 | 29 | animate(); 30 | }); 31 | } 32 | 33 | render() { 34 | return ( 35 |
36 | 37 | 38 | 39 | react-famous 40 | examples 41 | 42 | 43 | 44 | 45 | ←   Please select an example. 46 | 47 | 48 | 49 |
50 | ); 51 | } 52 | } 53 | 54 | export default Home; 55 | -------------------------------------------------------------------------------- /examples/components/Menu.jsx: -------------------------------------------------------------------------------- 1 | import isEqual from 'lodash/lang/isEqual'; 2 | import React from 'react'; 3 | import { Link } from 'react-router'; 4 | 5 | class Menu extends React.Component { 6 | shouldComponentUpdate(nextProps, nextState) { 7 | return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState); 8 | } 9 | 10 | render() { 11 | let examples = Object.keys(this.props.examples).reduce((result, group, idx) => { 12 | let listItems = this.props.examples[group].map((member, idx) => { 13 | return ( 14 |
  • 15 | {member} 16 |
  • 17 | ); 18 | }); 19 | result.push( 20 |
    21 |
    {group}
    22 | 25 |
    26 | ); 27 | return result; 28 | }, []); 29 | 30 | return ( 31 |
    32 | 35 | {examples} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | Menu.propTypes = { 42 | examples: React.PropTypes.object.isRequired 43 | }; 44 | 45 | export default Menu; 46 | -------------------------------------------------------------------------------- /examples/components/modifiers/Draggable/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import Draggable from 'react-famous/modifiers/Draggable'; 6 | 7 | export default class extends React.Component { 8 | componentDidMount() { 9 | let draggable = this.refs.draggable.getFamous(); 10 | let surface = this.refs.surface.getFamous(); 11 | 12 | draggable.subscribe(surface); 13 | } 14 | 15 | render() { 16 | let draggableOptions = { 17 | snapX: 40, 18 | snapY: 40, 19 | xRange: [-220, 220], 20 | yRange: [-220, 220] 21 | }; 22 | 23 | let gridOptions = { 24 | size: [481, 481], 25 | properties: { 26 | backgroundColor: 'black', 27 | backgroundImage: 'linear-gradient(rgba(255, 255, 255, 0.25) 1px, transparent 1px), linear-gradient(white 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, 0.25) 1px, transparent 1px), linear-gradient(90deg, white 1px, transparent 1px), linear-gradient(transparent 3px, black 3px, black 238px, transparent 238px), linear-gradient(90deg, white 3px, transparent 3px, transparent 238px, white 238px)', 28 | backgroundSize: '40px 40px, 240px 240px, 40px 40px, 240px 240px, 240px 240px, 240px 240px' 29 | } 30 | }; 31 | 32 | let surfaceOptions = { 33 | size: [40, 40], 34 | content: 'drag', 35 | properties: { 36 | backgroundColor: 'red', 37 | color: 'white', 38 | cursor: 'pointer', 39 | lineHeight: '40px', 40 | textAlign: 'center' 41 | } 42 | }; 43 | 44 | return ( 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /examples/components/surfaces/CanvasSurface/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import CanvasSurface from 'react-famous/surfaces/CanvasSurface'; 6 | 7 | let CANVAS_SIZE = [400, 400]; 8 | 9 | export default class extends React.Component { 10 | componentDidMount() { 11 | let canvas = this.refs.canvas.getFamous(); 12 | let ctx = canvas.getContext('2d'); 13 | 14 | ctx.fillStyle = 'rgb(200, 0, 0)'; 15 | ctx.fillRect(50, 50, 200, 200); 16 | 17 | ctx.fillStyle = 'rgba(0, 0, 200, 0.5)'; 18 | ctx.fillRect(150, 150, 200, 200); 19 | } 20 | 21 | render() { 22 | return ( 23 | 24 | 25 | Shapes are drawn on a canvas surface. 26 | 27 | 28 | 29 | 30 | 31 | ); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /examples/components/surfaces/ContainerSurface/App.jsx: -------------------------------------------------------------------------------- 1 | import startsWith from 'lodash/string/startsWith'; 2 | import range from 'lodash/utility/range'; 3 | import React from 'react'; 4 | import Context from 'react-famous/core/Context'; 5 | import Modifier from 'react-famous/core/Modifier'; 6 | import Surface from 'react-famous/core/Surface'; 7 | import ContainerSurface from 'react-famous/surfaces/ContainerSurface'; 8 | import Scrollview from 'react-famous/views/Scrollview'; 9 | 10 | const NUM_SURFACES = 100; 11 | const SURFACE_REF_PREFIX = 'surface_'; 12 | 13 | export default class extends React.Component { 14 | componentDidMount() { 15 | let scrollview = this.refs.scrollview.getFamous(); 16 | 17 | Object.keys(this.refs) 18 | .filter((key) => startsWith(key, SURFACE_REF_PREFIX)) 19 | .map((key) => this.refs[key].getFamous()) 20 | .forEach((surface) => surface.pipe(scrollview)); 21 | } 22 | 23 | render() { 24 | let surfaces = range(NUM_SURFACES).map((idx) => { 25 | let options = { 26 | properties: { 27 | backgroundColor: 'rgba(255, 0, 0, 0.5)', 28 | color: 'white', 29 | lineHeight: '50px', 30 | textAlign: 'center' 31 | }, 32 | size: [undefined, 50] 33 | }; 34 | return ( 35 | 36 | I am surface: {idx + 1} 37 | 38 | ); 39 | }); 40 | 41 | return ( 42 | 43 | 44 | Scrollview is created inside a container surface. 45 | 46 | 47 | 48 | 49 | {surfaces} 50 | 51 | 52 | 53 | 54 | ); 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /examples/components/surfaces/ImageSurface/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import ImageSurface from 'react-famous/surfaces/ImageSurface'; 6 | 7 | const IMAGE_URL = 'http://code.famo.us/assets/famous.jpg'; 8 | 9 | export default class extends React.Component { 10 | render() { 11 | return ( 12 | 13 | 14 | The image is created with ImageSurface. 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /examples/components/surfaces/VideoSurface/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import VideoSurface from 'react-famous/surfaces/VideoSurface'; 6 | 7 | const VIDEO_URL = 'http://video.webmfiles.org/big-buck-bunny_trailer.webm'; 8 | 9 | export default class extends React.Component { 10 | render() { 11 | return ( 12 | 13 | 14 | The video is created with VideoSurface. 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /examples/components/test/Animations/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | 5 | import BouncyBox from './BouncyBox'; 6 | import CrazyBox from './CrazyBox'; 7 | import DraggableBox from './DraggableBox'; 8 | import DroppingBox from './DroppingBox'; 9 | import RotatingBox from './RotatingBox'; 10 | 11 | export default class extends React.Component { 12 | render() { 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /examples/components/test/Animations/BouncyBox.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import GenericSync from 'famous/inputs/GenericSync'; 3 | import MouseSync from 'famous/inputs/MouseSync'; 4 | import TouchSync from 'famous/inputs/TouchSync'; 5 | import SnapTransition from 'famous/transitions/SnapTransition'; 6 | import Transitionable from 'famous/transitions/Transitionable'; 7 | import React from 'react'; 8 | import Modifier from 'react-famous/core/Modifier'; 9 | import Surface from 'react-famous/core/Surface'; 10 | 11 | GenericSync.register({ 12 | mouse: MouseSync, 13 | touch: TouchSync 14 | }); 15 | 16 | Transitionable.registerMethod('spring', SnapTransition); 17 | 18 | export default class extends React.Component { 19 | componentWillMount() { 20 | this._position = new Transitionable([0, 0]); 21 | } 22 | 23 | componentDidMount() { 24 | let position = this._position; 25 | let clickSurface = this.refs.clickSurface.getFamous(); 26 | let sync = new GenericSync({ 27 | mouse: {}, 28 | touch: {} 29 | }); 30 | 31 | sync.on('update', (data) => { 32 | let currentPosition = position.get(); 33 | position.set([ 34 | currentPosition[0] + data.delta[0], 35 | currentPosition[1] + data.delta[1] 36 | ]); 37 | }); 38 | 39 | sync.on('end', (data) => { 40 | let velocity = data.velocity; 41 | position.set([0, 0], { 42 | method: 'spring', 43 | period: 150, 44 | velocity: data.velocity 45 | }); 46 | }); 47 | 48 | clickSurface.pipe(sync); 49 | } 50 | 51 | render() { 52 | let position = this._position; 53 | 54 | let modifierOptions = { 55 | proportions: [0.2, 0.2], 56 | transform: () => { 57 | let currentPosition = position.get(); 58 | return Transform.translate(currentPosition[0], currentPosition[1]); 59 | } 60 | }; 61 | 62 | return ( 63 | 64 | 65 | 66 | 67 | Bouncy 68 | 69 | 70 | 71 | 72 | 73 | 74 | ); 75 | } 76 | }; 77 | -------------------------------------------------------------------------------- /examples/components/test/Animations/CrazyBox.jsx: -------------------------------------------------------------------------------- 1 | import random from 'lodash/number/random'; 2 | import Transform from 'famous/core/Transform'; 3 | import Easing from 'famous/transitions/Easing'; 4 | import TweenTransition from 'famous/transitions/TweenTransition'; 5 | import React from 'react'; 6 | import Modifier from 'react-famous/core/Modifier'; 7 | import Surface from 'react-famous/core/Surface'; 8 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 9 | import StateModifier from 'react-famous/modifiers/StateModifier'; 10 | 11 | const EASING_NAMES = Object.keys(Easing); 12 | 13 | EASING_NAMES.forEach((name) => TweenTransition.registerCurve(name, Easing[name])); 14 | 15 | export default class extends React.Component { 16 | componentDidMount() { 17 | let stateModifier = this.refs.stateModifier.getFamous(); 18 | 19 | function rotate() { 20 | stateModifier.setTransform(Transform.rotate(Math.random(), Math.random(), Math.random()), { 21 | curve: EASING_NAMES[random(EASING_NAMES.length)], 22 | duration: 300 23 | }, () => { 24 | stateModifier.setTransform(Transform.rotate(0, 0, 0), { 25 | duration: 50 26 | }, rotate); 27 | }); 28 | } 29 | 30 | FamousScheduler.schedule(rotate); 31 | } 32 | 33 | render() { 34 | return ( 35 | 36 | 37 | 38 | 39 | Crazy 40 | 41 | 42 | 43 | ); 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /examples/components/test/Animations/DraggableBox.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import GenericSync from 'famous/inputs/GenericSync'; 3 | import MouseSync from 'famous/inputs/MouseSync'; 4 | import TouchSync from 'famous/inputs/TouchSync'; 5 | import React from 'react'; 6 | import Modifier from 'react-famous/core/Modifier'; 7 | import Surface from 'react-famous/core/Surface'; 8 | 9 | GenericSync.register({ 10 | mouse: MouseSync, 11 | touch: TouchSync 12 | }); 13 | 14 | export default class extends React.Component { 15 | componentWillMount() { 16 | this._position = [0, 0]; 17 | } 18 | 19 | componentDidMount() { 20 | let position = this._position; 21 | let clickSurface = this.refs.clickSurface.getFamous(); 22 | let sync = new GenericSync({ 23 | mouse: {}, 24 | touch: {} 25 | }); 26 | 27 | sync.on('update', (data) => { 28 | position[0] += data.delta[0]; 29 | position[1] += data.delta[1]; 30 | }); 31 | 32 | clickSurface.pipe(sync); 33 | } 34 | 35 | render() { 36 | let position = this._position; 37 | 38 | let modifierOptions = { 39 | proportions: [0.2, 0.2], 40 | transform: () => { 41 | return Transform.translate(position[0], position[1]); 42 | } 43 | }; 44 | 45 | return ( 46 | 47 | 48 | 49 | 50 | Draggable 51 | 52 | 53 | 54 | 55 | 56 | 57 | ); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /examples/components/test/Animations/DroppingBox.jsx: -------------------------------------------------------------------------------- 1 | import Transitionable from 'famous/transitions/Transitionable'; 2 | import React from 'react'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 6 | 7 | export default class extends React.Component { 8 | componentWillMount() { 9 | this._transitionable = new Transitionable([0, 0]); 10 | } 11 | 12 | componentDidMount() { 13 | FamousScheduler.schedule(() => { 14 | this._transitionable.set([0, 1], { 15 | duration: 1000, 16 | curve: 'easeInOut' 17 | }); 18 | }); 19 | } 20 | 21 | render() { 22 | let transitionable = this._transitionable; 23 | 24 | let modifierOptions = { 25 | align: () => transitionable.get(), 26 | opacity: 0.7, 27 | origin: () => transitionable.get(), 28 | proportions: [1, 0.1] 29 | }; 30 | 31 | return ( 32 | 33 | 34 | 35 | 36 | Dropping 37 | 38 | 39 | 40 | ); 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /examples/components/test/Animations/RotatingBox.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import React from 'react'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 6 | 7 | export default class extends React.Component { 8 | componentDidMount() { 9 | let modifier = this.refs.modifier.getFamous(); 10 | let angle = 0; 11 | 12 | FamousScheduler.schedule(() => { 13 | modifier.transformFrom(() => { 14 | angle += 0.03; 15 | return Transform.rotateZ(angle); 16 | }); 17 | }); 18 | } 19 | 20 | render() { 21 | return ( 22 | 23 | 24 | 25 | 26 | Rotating 27 | 28 | 29 | 30 | ); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /examples/components/test/Animations/index.js: -------------------------------------------------------------------------------- 1 | import 'famous/core/famous.css'; 2 | import React from 'react'; 3 | 4 | import App from './components/App'; 5 | 6 | React.render(React.createElement(App), document.body); 7 | -------------------------------------------------------------------------------- /examples/components/test/CommentBox/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | 4 | import CommentBox from './CommentBox'; 5 | 6 | export default class extends React.Component { 7 | render() { 8 | return ( 9 | 10 | 11 | 12 | ); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /examples/components/test/CommentBox/Comment.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Modifier from 'react-famous/core/Modifier'; 3 | import Surface from 'react-famous/core/Surface'; 4 | import FlexibleLayout from 'react-famous/views/FlexibleLayout'; 5 | 6 | class Component extends React.Component { 7 | render() { 8 | return ( 9 | 10 | 11 | 12 | {this.props.author} 13 | 14 | 15 | 16 | 17 | 18 | {this.props.text} 19 | 20 | 21 | 22 | ); 23 | } 24 | } 25 | 26 | Component.propTypes = { 27 | author: React.PropTypes.string, 28 | text: React.PropTypes.string 29 | }; 30 | 31 | export default Component; 32 | -------------------------------------------------------------------------------- /examples/components/test/CommentBox/CommentBox.jsx: -------------------------------------------------------------------------------- 1 | import range from 'lodash/utility/range'; 2 | import React from 'react'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import FlexibleLayout from 'react-famous/views/FlexibleLayout'; 6 | 7 | import CommentForm from './CommentForm'; 8 | import CommentList from './CommentList'; 9 | 10 | export default class extends React.Component { 11 | constructor(...args) { 12 | super(...args); 13 | 14 | this.state = { 15 | data: range(5).map(() => { 16 | return { 17 | author: '@pilwon', 18 | text: 'Hello react-famous!' 19 | }; 20 | }) 21 | }; 22 | } 23 | 24 | render() { 25 | return ( 26 | 27 | 28 | 29 | Comments 30 | 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /examples/components/test/CommentBox/CommentForm.jsx: -------------------------------------------------------------------------------- 1 | import Utility from 'famous/utilities/Utility'; 2 | import React from 'react'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import FormContainerSurface from 'react-famous/surfaces/FormContainerSurface'; 6 | import InputSurface from 'react-famous/surfaces/InputSurface'; 7 | import SubmitInputSurface from 'react-famous/surfaces/SubmitInputSurface'; 8 | import SequentialLayout from 'react-famous/views/SequentialLayout'; 9 | 10 | export default class extends React.Component { 11 | render() { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /examples/components/test/CommentBox/CommentList.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import Transitionable from 'famous/transitions/Transitionable'; 3 | import React from 'react'; 4 | import Modifier from 'react-famous/core/Modifier'; 5 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 6 | import Scrollview from 'react-famous/views/Scrollview'; 7 | 8 | import Comment from './Comment'; 9 | 10 | class Component extends React.Component { 11 | componentWillMount() { 12 | this._transitionables = this.props.data.map(() => new Transitionable(0)); 13 | } 14 | 15 | componentDidMount() { 16 | let transitionables = this._transitionables; 17 | 18 | FamousScheduler.schedule(() => { 19 | this.props.data.forEach((comment, idx) => { 20 | let modifier = this.refs[`modifier_${idx}`].getFamous(); 21 | let transitionable = transitionables[idx]; 22 | transitionable.set(1, { 23 | curve: 'easeInOut', 24 | duration: (idx + 1) * (1500 / this.props.data.length) 25 | }); 26 | }); 27 | }); 28 | } 29 | 30 | render() { 31 | let transitionables = this._transitionables; 32 | 33 | let commentNodes = this.props.data.map((comment, idx) => { 34 | let transitionable = transitionables[idx]; 35 | let modifierOptions = { 36 | opacity: () => { 37 | return transitionable.get(); 38 | }, 39 | size: [undefined, 50], 40 | transform: () => { 41 | return Transform.translate(300 * (1 - transitionable.get()), 0); 42 | } 43 | }; 44 | 45 | return ( 46 | 47 | 48 | 49 | ); 50 | }); 51 | 52 | return ( 53 | 54 | 55 | 56 | {commentNodes} 57 | 58 | 59 | 60 | ); 61 | } 62 | } 63 | 64 | Component.propTypes = { 65 | data: React.PropTypes.array 66 | }; 67 | 68 | export default Component; 69 | -------------------------------------------------------------------------------- /examples/components/test/HelloWorld/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | 6 | export default class extends React.Component { 7 | render() { 8 | let options = { 9 | size: [150, 100], 10 | properties: { 11 | backgroundColor: '#000099', 12 | color: '#fff', 13 | textAlign: 'center', 14 | lineHeight: '100px' 15 | } 16 | }; 17 | 18 | return ( 19 | 20 | 21 | 22 | Hello World 23 | 24 | 25 | 26 | ); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /examples/components/test/HelloWorldDynamic/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 6 | 7 | export default class extends React.Component { 8 | constructor(...args) { 9 | super(...args); 10 | 11 | this.state = { 12 | count: 0 13 | }; 14 | } 15 | 16 | componentWillUnmount() { 17 | clearInterval(this._intervalId); 18 | } 19 | 20 | componentDidMount() { 21 | FamousScheduler.schedule(() => { 22 | this._intervalId = setInterval(() => { 23 | this.setState((state) => ({ 24 | count: state.count + 1 25 | })); 26 | }, 100); 27 | }); 28 | } 29 | 30 | _textCharUpper(text, position) { 31 | let str = text.toLowerCase(); 32 | let idx = position % str.length; 33 | return str.substr(0, idx) + str[idx].toUpperCase() + str.substr(idx + 1); 34 | } 35 | 36 | render() { 37 | let properties = { 38 | backgroundColor: this.state.count % 2 ? '#990000' : '#ff0000', 39 | color: '#fff', 40 | textAlign: 'center', 41 | lineHeight: '100px' 42 | }; 43 | let text = this._textCharUpper('Hello World', this.state.count); 44 | 45 | return ( 46 | 47 | 48 | 49 | {text} 50 | 51 | 52 | 53 | ); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /examples/components/test/Layout/App.jsx: -------------------------------------------------------------------------------- 1 | import range from 'lodash/utility/range'; 2 | import React from 'react'; 3 | import Context from 'react-famous/core/Context'; 4 | import Modifier from 'react-famous/core/Modifier'; 5 | import Surface from 'react-famous/core/Surface'; 6 | import GridLayout from 'react-famous/views/GridLayout'; 7 | import HeaderFooterLayout from 'react-famous/views/HeaderFooterLayout'; 8 | 9 | export default class extends React.Component { 10 | render() { 11 | let views = range(2).map((i) => { 12 | let options = { 13 | size: [100, 100], 14 | properties: { 15 | backgroundColor: '#fa5c4f', 16 | color: 'white', 17 | lineHeight: '100px', 18 | textAlign: 'center' 19 | } 20 | }; 21 | 22 | return ( 23 | 24 | 25 | content {i + 1} 26 | 27 | 28 | ); 29 | }); 30 | 31 | return ( 32 | 33 | 34 | 35 | 36 | Header 37 | 38 | 39 | 40 | 41 | {views} 42 | 43 | 44 | 45 | 46 | Footer 47 | 48 | 49 | 50 | 51 | ); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /examples/components/test/ReactNode/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import RenderNode from 'react-famous/core/RenderNode'; 5 | import Surface from 'react-famous/core/Surface'; 6 | import ReactNode from 'react-famous/lib/ReactNode'; 7 | import GridLayout from 'react-famous/views/GridLayout'; 8 | 9 | import EdgeSwapperApp from '../../views/EdgeSwapper/App'; 10 | import FlexibleLayoutApp from '../../views/FlexibleLayout/App'; 11 | import FlipperApp from '../../views/Flipper/App'; 12 | import GridLayoutApp from '../../views/GridLayout/App'; 13 | import HeaderFooterLayoutApp from '../../views/HeaderFooterLayout/App'; 14 | import ScrollviewApp from '../../views/Scrollview/App'; 15 | import AnimationsApp from '../Animations/App'; 16 | import CommentBoxApp from '../CommentBox/App'; 17 | import HelloWorldDynamicApp from '../HelloWorldDynamic/App'; 18 | 19 | export default class extends React.Component { 20 | render() { 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /examples/components/test/Seed/App.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import Easing from 'famous/transitions/Easing'; 3 | import React from 'react'; 4 | import Context from 'react-famous/core/Context'; 5 | import Modifier from 'react-famous/core/Modifier'; 6 | import Surface from 'react-famous/core/Surface'; 7 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 8 | import StateModifier from 'react-famous/modifiers/StateModifier'; 9 | 10 | const GROUND_RATIO = 0.35; 11 | const INITIAL_MODIFIER_OPTIONS = {align: [0.5, 0], origin: [0.5, 1]}; 12 | const URL = 'https://github.com/pilwon/react-famous'; 13 | 14 | export default class extends React.Component { 15 | componentDidMount() { 16 | let beanModifier = this.refs.beanModifier.getFamous(); 17 | 18 | function drop() { 19 | return new Promise((resolve) => { 20 | beanModifier.setAlign([0.5, 1 - GROUND_RATIO], { 21 | curve: Easing.outBounce, 22 | duration: 2500 23 | }, resolve); 24 | }); 25 | } 26 | 27 | function moveLeft() { 28 | return new Promise((resolve) => { 29 | return Promise.all([ 30 | new Promise((resolve) => { 31 | beanModifier.setAlign([0.05, 1 - GROUND_RATIO], { 32 | curve: Easing.outElastic, 33 | duration: 1000 34 | }, resolve); 35 | }), 36 | new Promise((resolve) => { 37 | beanModifier.setOrigin([0, 1], { 38 | curve: Easing.outElastic, 39 | duration: 1000 40 | }, resolve); 41 | }) 42 | ]).then(() => setTimeout(resolve, 300)); 43 | }); 44 | } 45 | 46 | function disappear() { 47 | return new Promise((resolve) => { 48 | beanModifier.setAlign([1, 1 - GROUND_RATIO], { 49 | curve: Easing.inExpo, 50 | duration: 500 51 | }, () => setTimeout(resolve, 1000)); 52 | }); 53 | } 54 | 55 | function reset() { 56 | beanModifier.setAlign(INITIAL_MODIFIER_OPTIONS.align); 57 | beanModifier.setOrigin(INITIAL_MODIFIER_OPTIONS.origin); 58 | return Promise.resolve(); 59 | } 60 | 61 | FamousScheduler.schedule(function loop() { 62 | drop().then(moveLeft).then(disappear).then(reset).then(loop); 63 | }); 64 | } 65 | 66 | render() { 67 | let beanOptions = { 68 | properties: { 69 | backgroundColor: '#F2EEB3', 70 | borderRadius: '50px', 71 | fontSize: '2em', 72 | fontWeight: 'bold', 73 | padding: '30px 50px' 74 | }, 75 | size: [true, true] 76 | }; 77 | 78 | let groundOptions = { 79 | properties: { 80 | backgroundColor: '#8C6954', 81 | borderBottom: '25px solid #260126', 82 | borderRadius: '200px 200px 0 0', 83 | borderTop: '30px solid #59323C' 84 | } 85 | }; 86 | 87 | return ( 88 | 89 | 90 | 91 | Hello react-famous! 92 | 93 | 94 | 95 | 96 | 97 | 98 | ); 99 | } 100 | }; 101 | -------------------------------------------------------------------------------- /examples/components/views/Deck/App.jsx: -------------------------------------------------------------------------------- 1 | import range from 'lodash/utility/range'; 2 | import SpringTransition from 'famous/transitions/SpringTransition'; 3 | import Transitionable from 'famous/transitions/Transitionable'; 4 | import Timer from 'famous/utilities/Timer'; 5 | import React from 'react'; 6 | import Context from 'react-famous/core/Context'; 7 | import Modifier from 'react-famous/core/Modifier'; 8 | import Surface from 'react-famous/core/Surface'; 9 | import Deck from 'react-famous/views/Deck'; 10 | 11 | Transitionable.registerMethod('spring', SpringTransition); 12 | 13 | export default class extends React.Component { 14 | constructor(...args) { 15 | super(...args); 16 | 17 | this._onSurfaceClick = this._onSurfaceClick.bind(this); 18 | } 19 | 20 | _onSurfaceClick(eventKey) { 21 | let deck = this.refs.deck.getFamous(); 22 | 23 | console.log('Clicked surface #' + eventKey); 24 | deck.toggle(); 25 | } 26 | 27 | render() { 28 | let surfaces = range(5).map((i) => { 29 | let options = { 30 | properties: { 31 | backgroundColor: 'hsla(' + ((i * 5 + i) * 15 % 360) + ', 60%, 50%, 0.8)', 32 | color: 'white', 33 | lineHeight: '200px', 34 | textAlign: 'center' 35 | }, 36 | size: [100, 200] 37 | }; 38 | return ( 39 | 40 | {i} 41 | 42 | ); 43 | }); 44 | 45 | let deckOptions = { 46 | itemSpacing: 10, 47 | transition: { 48 | method: 'spring', 49 | period: 300, 50 | dampingRatio: 0.5 51 | }, 52 | stackRotation: 0.02 53 | }; 54 | 55 | return ( 56 | 57 | 58 | Open the developer console, then click the deck. 59 | 60 | 61 | 62 | {surfaces} 63 | 64 | 65 | 66 | ); 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /examples/components/views/EdgeSwapper/App.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import GenericSync from 'famous/inputs/GenericSync'; 3 | import MouseSync from 'famous/inputs/MouseSync'; 4 | import TouchSync from 'famous/inputs/TouchSync'; 5 | import React from 'react'; 6 | import Context from 'react-famous/core/Context'; 7 | import Modifier from 'react-famous/core/Modifier'; 8 | import RenderNode from 'react-famous/core/RenderNode'; 9 | import Surface from 'react-famous/core/Surface'; 10 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 11 | import EdgeSwapper from 'react-famous/views/EdgeSwapper'; 12 | 13 | GenericSync.register({ 14 | mouse: MouseSync, 15 | touch: TouchSync 16 | }); 17 | 18 | export default class extends React.Component { 19 | componentDidMount() { 20 | let clickSurface = this.refs.clickSurface.getFamous(); 21 | let edgeSwapper = this.refs.edgeSwapper.getFamous(); 22 | let primary = this.refs.primary.getFamous(); 23 | let secondary = this.refs.secondary.getFamous(); 24 | let showing = true; 25 | let sync = new GenericSync({ 26 | mouse: {}, 27 | touch: {} 28 | }); 29 | 30 | sync.on('end', (data) => { 31 | if (showing) { 32 | edgeSwapper.show(secondary); 33 | } else { 34 | edgeSwapper.show(primary); 35 | } 36 | showing = !showing; 37 | }); 38 | 39 | clickSurface.pipe(sync); 40 | 41 | FamousScheduler.schedule(() => { 42 | edgeSwapper.show(primary); 43 | }); 44 | } 45 | 46 | render() { 47 | let surfaceOptions = { 48 | size: [true, true], 49 | properties: { 50 | color: 'white', 51 | fontSize: '2em' 52 | } 53 | }; 54 | 55 | return ( 56 | 57 | 58 | 59 | 60 | 61 | 62 | Primary 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | Secondary 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | ); 80 | } 81 | }; 82 | -------------------------------------------------------------------------------- /examples/components/views/FlexibleLayout/App.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import GenericSync from 'famous/inputs/GenericSync'; 3 | import MouseSync from 'famous/inputs/MouseSync'; 4 | import TouchSync from 'famous/inputs/TouchSync'; 5 | import range from 'lodash/utility/range'; 6 | import React from 'react'; 7 | import Context from 'react-famous/core/Context'; 8 | import Modifier from 'react-famous/core/Modifier'; 9 | import Surface from 'react-famous/core/Surface'; 10 | import FlexibleLayout from 'react-famous/views/FlexibleLayout'; 11 | 12 | const COLORS = [ 13 | 'rgba(255, 0, 0, .7)', 14 | 'rgba(0, 255, 0, .7)', 15 | 'rgba(0, 0, 255, .7)', 16 | 'rgba(255, 0, 0, .7)', 17 | 'rgba(0, 255, 0, .7)', 18 | 'rgba(0, 0, 255, .7)', 19 | 'rgba(255, 0, 0, .7)', 20 | 'rgba(0, 255, 0, .7)' 21 | ]; 22 | const INITIAL_RATIOS = [1, true, 1, true, 1, true, 1, true]; 23 | const FINAL_RATIOS = [4, true, 1, true, 0, true, 7, true]; 24 | 25 | GenericSync.register({ 26 | mouse: MouseSync, 27 | touch: TouchSync 28 | }); 29 | 30 | export default class extends React.Component { 31 | componentDidMount() { 32 | let clickSurface = this.refs.clickSurface.getFamous(); 33 | let flexibleLayout = this.refs.flexibleLayout.getFamous(); 34 | let sync = new GenericSync({ 35 | mouse: {}, 36 | touch: {} 37 | }); 38 | let toggle = false; 39 | 40 | sync.on('end', (data) => { 41 | let ratios = toggle ? INITIAL_RATIOS : FINAL_RATIOS; 42 | flexibleLayout.setRatios(ratios, { 43 | curve: 'easeOut', 44 | duration: 500 45 | }); 46 | toggle = !toggle; 47 | }); 48 | 49 | clickSurface.pipe(sync); 50 | } 51 | 52 | render() { 53 | let surfaces = range(COLORS.length).map((idx) => { 54 | let options = { 55 | properties: { 56 | backgroundColor: COLORS[idx] 57 | }, 58 | size: (idx % 2 === 0) ? [undefined, undefined] : [10, undefined] 59 | }; 60 | return ( 61 | 62 | ); 63 | }); 64 | 65 | return ( 66 | 67 | 68 | 69 | {surfaces} 70 | 71 | 72 | 73 | 74 | 75 | 76 | ); 77 | } 78 | }; 79 | -------------------------------------------------------------------------------- /examples/components/views/Flipper/App.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import GenericSync from 'famous/inputs/GenericSync'; 3 | import MouseSync from 'famous/inputs/MouseSync'; 4 | import TouchSync from 'famous/inputs/TouchSync'; 5 | import React from 'react'; 6 | import Context from 'react-famous/core/Context'; 7 | import Modifier from 'react-famous/core/Modifier'; 8 | import Surface from 'react-famous/core/Surface'; 9 | import Flipper from 'react-famous/views/Flipper'; 10 | 11 | GenericSync.register({ 12 | mouse: MouseSync, 13 | touch: TouchSync 14 | }); 15 | 16 | export default class extends React.Component { 17 | componentDidMount() { 18 | let clickSurface = this.refs.clickSurface.getFamous(); 19 | let flipper = this.refs.flipper.getFamous(); 20 | let sync = new GenericSync({ 21 | mouse: {}, 22 | touch: {} 23 | }); 24 | let toggle = false; 25 | 26 | sync.on('end', (data) => { 27 | let angle = toggle ? 0 : Math.PI; 28 | flipper.setAngle(angle, { 29 | curve: 'easeOutBounce', 30 | duration: 500 31 | }); 32 | toggle = !toggle; 33 | }); 34 | 35 | clickSurface.pipe(sync); 36 | } 37 | 38 | render() { 39 | return ( 40 | 41 | 42 | Click anywhere on the screen. 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Front 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Back 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | ); 73 | } 74 | }; 75 | -------------------------------------------------------------------------------- /examples/components/views/GridLayout/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import RenderNode from 'react-famous/core/RenderNode'; 5 | import Surface from 'react-famous/core/Surface'; 6 | import GridLayout from 'react-famous/views/GridLayout'; 7 | 8 | export default class extends React.Component { 9 | render() { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 |

    Red

    18 |
    19 |
    20 |
    21 | 22 | Green 23 | 24 | 25 | Blue 26 | 27 | 28 | Pink 29 | 30 | 31 | Purple 32 | 33 | 34 | 35 | Navy 36 | 37 | 38 | Brown 39 | 40 | 41 | Khaki 42 | 43 | 44 | Maroon 45 | 46 | 47 |
    48 |
    49 | ); 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /examples/components/views/HeaderFooterLayout/App.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import React from 'react'; 3 | import Context from 'react-famous/core/Context'; 4 | import Modifier from 'react-famous/core/Modifier'; 5 | import Surface from 'react-famous/core/Surface'; 6 | import HeaderFooterLayout from 'react-famous/views/HeaderFooterLayout'; 7 | 8 | export default class extends React.Component { 9 | render() { 10 | let modifierOptions = { 11 | align: [.5, .5], 12 | origin: [.5, .5], 13 | proportions: [0.5, 0.7], 14 | transform: Transform.rotateZ(.2) 15 | }; 16 | 17 | return ( 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Header 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | Content 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | Footer 42 | 43 | 44 | 45 | 46 | 47 | 48 | ); 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /examples/components/views/Lightbox/App.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import React from 'react'; 3 | import Context from 'react-famous/core/Context'; 4 | import Modifier from 'react-famous/core/Modifier'; 5 | import Surface from 'react-famous/core/Surface'; 6 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 7 | import Lightbox from 'react-famous/views/Lightbox'; 8 | 9 | export default class extends React.Component { 10 | componentDidMount() { 11 | let lightbox = this.refs.lightbox.getFamous(); 12 | let red = this.refs.red.getFamous(); 13 | let green = this.refs.green.getFamous(); 14 | let blue = this.refs.blue.getFamous(); 15 | 16 | function showRed() { 17 | lightbox.show(red, {duration: 1500}, showGreen); 18 | } 19 | 20 | function showGreen() { 21 | lightbox.show(green, {duration: 1500}, showBlue); 22 | } 23 | 24 | function showBlue() { 25 | lightbox.show(blue, {duration: 1500}, showRed); 26 | } 27 | 28 | FamousScheduler.schedule(showRed); 29 | } 30 | 31 | render() { 32 | let lightboxOptions = { 33 | inAlign: [0, 0.5], 34 | inOpacity: 0.5, 35 | inOrigin: [0, 0.5], 36 | inTransform: Transform.scale(0.5, 0.5, 0.5), 37 | outAlign: [1, 0.5], 38 | outOpacity: 0, 39 | outOrigin: [1, 0.5], 40 | outTransform: Transform.scale(0.001, 0.001, 0.001), 41 | overlap: true 42 | }; 43 | 44 | return ( 45 | 46 | 47 | Lightbox showing and hiding renderables. 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /examples/components/views/RenderController/App.jsx: -------------------------------------------------------------------------------- 1 | import Transform from 'famous/core/Transform'; 2 | import GenericSync from 'famous/inputs/GenericSync'; 3 | import MouseSync from 'famous/inputs/MouseSync'; 4 | import TouchSync from 'famous/inputs/TouchSync'; 5 | import startsWith from 'lodash/string/startsWith'; 6 | import range from 'lodash/utility/range'; 7 | import React from 'react'; 8 | import Context from 'react-famous/core/Context'; 9 | import Modifier from 'react-famous/core/Modifier'; 10 | import Surface from 'react-famous/core/Surface'; 11 | import FamousScheduler from 'react-famous/lib/FamousScheduler'; 12 | import RenderController from 'react-famous/views/RenderController'; 13 | 14 | const NUM_SURFACES = 10; 15 | const SURFACE_REF_PREFIX = 'surface_'; 16 | 17 | GenericSync.register({ 18 | mouse: MouseSync, 19 | touch: TouchSync 20 | }); 21 | 22 | export default class extends React.Component { 23 | componentDidMount() { 24 | let clickSurface = this.refs.clickSurface.getFamous(); 25 | let renderController = this.refs.renderController.getFamous(); 26 | let surfaces = Object.keys(this.refs) 27 | .filter((key) => startsWith(key, SURFACE_REF_PREFIX)) 28 | .map((key) => this.refs[key].getFamous()); 29 | let sync = new GenericSync({ 30 | mouse: {}, 31 | touch: {} 32 | }); 33 | let counter = 0; 34 | 35 | sync.on('end', (data) => { 36 | let next = (counter + 1) % surfaces.length; 37 | renderController.show(surfaces[next]); 38 | counter += 1; 39 | }); 40 | 41 | clickSurface.pipe(sync); 42 | 43 | FamousScheduler.schedule(() => { 44 | if (surfaces[0]) { 45 | renderController.show(surfaces[0]); 46 | } 47 | }); 48 | } 49 | 50 | render() { 51 | let surfaces = range(NUM_SURFACES).map((i) => { 52 | let options = { 53 | size: [200, 200], 54 | properties: { 55 | backgroundColor: 'hsl(' + (i * 360 / NUM_SURFACES) + ', 100%, 50%)', 56 | lineHeight: '200px', 57 | textAlign: 'center' 58 | } 59 | }; 60 | return ( 61 | 62 | Surface: {i + 1} 63 | 64 | ); 65 | }); 66 | 67 | return ( 68 | 69 | 70 | Click anywhere on the screen. 71 | 72 | 73 | 74 | {surfaces} 75 | 76 | 77 | 78 | 79 | 80 | 81 | ); 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /examples/components/views/ScrollContainer/App.jsx: -------------------------------------------------------------------------------- 1 | import startsWith from 'lodash/string/startsWith'; 2 | import range from 'lodash/utility/range'; 3 | import React from 'react'; 4 | import Context from 'react-famous/core/Context'; 5 | import Modifier from 'react-famous/core/Modifier'; 6 | import Surface from 'react-famous/core/Surface'; 7 | import ScrollContainer from 'react-famous/views/ScrollContainer'; 8 | 9 | const NUM_SURFACES = 40; 10 | const SURFACE_REF_PREFIX = 'surface_'; 11 | 12 | export default class extends React.Component { 13 | componentDidMount() { 14 | let scrollContainer = this.refs.scrollContainer.getFamous(); 15 | 16 | Object.keys(this.refs) 17 | .filter((key) => startsWith(key, SURFACE_REF_PREFIX)) 18 | .map((key) => this.refs[key].getFamous()) 19 | .forEach((surface) => surface.pipe(scrollContainer.scrollview)); 20 | } 21 | 22 | render() { 23 | let surfaces = range(NUM_SURFACES).map((idx) => { 24 | let surfaceOptions = { 25 | size: [undefined, 50], 26 | properties: { 27 | backgroundColor: 'hsl(' + (idx * 360 / NUM_SURFACES) + ', 100%, 50%)', 28 | lineHeight: '50px', 29 | textAlign: 'center' 30 | } 31 | }; 32 | return ( 33 | 34 | Surface {idx + 1} 35 | 36 | ); 37 | }); 38 | 39 | return ( 40 | 41 | 42 | Surfaces are clipped by ScrollContainer. 43 | 44 | 45 | 46 | {surfaces} 47 | 48 | 49 | 50 | ); 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /examples/components/views/Scrollview/App.jsx: -------------------------------------------------------------------------------- 1 | import startsWith from 'lodash/string/startsWith'; 2 | import range from 'lodash/utility/range'; 3 | import React from 'react'; 4 | import Context from 'react-famous/core/Context'; 5 | import Surface from 'react-famous/core/Surface'; 6 | import Scrollview from 'react-famous/views/Scrollview'; 7 | 8 | const NUM_SURFACES = 40; 9 | const SURFACE_REF_PREFIX = 'surface_'; 10 | 11 | export default class extends React.Component { 12 | componentDidMount() { 13 | let scrollview = this.refs.scrollview.getFamous(); 14 | 15 | Object.keys(this.refs) 16 | .filter((key) => startsWith(key, SURFACE_REF_PREFIX)) 17 | .map((key) => this.refs[key].getFamous()) 18 | .forEach((surface) => surface.pipe(scrollview)); 19 | } 20 | 21 | render() { 22 | let surfaces = range(NUM_SURFACES).map((idx) => { 23 | let options = { 24 | properties: { 25 | backgroundColor: 'hsl(' + (idx * 360 / NUM_SURFACES) + ', 100%, 50%)', 26 | lineHeight: '100px', 27 | textAlign: 'center' 28 | }, 29 | size: [undefined, 100] 30 | }; 31 | return ( 32 | 33 | Surface {idx + 1} 34 | 35 | ); 36 | }); 37 | 38 | return ( 39 | 40 | 41 | {surfaces} 42 | 43 | 44 | ); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /examples/components/views/SequentialLayout/App.jsx: -------------------------------------------------------------------------------- 1 | import Utility from 'famous/utilities/Utility'; 2 | import React from 'react'; 3 | import Context from 'react-famous/core/Context'; 4 | import Modifier from 'react-famous/core/Modifier'; 5 | import RenderNode from 'react-famous/core/RenderNode'; 6 | import Surface from 'react-famous/core/Surface'; 7 | import SequentialLayout from 'react-famous/views/SequentialLayout'; 8 | 9 | export default class extends React.Component { 10 | render() { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |

    Red

    20 |
    21 |
    22 |
    23 |
    24 | 25 | Green 26 | 27 | 28 | 29 | Blue 30 | 31 | 32 | 33 | 34 | 35 | Navy 36 | 37 | 38 | Brown 39 | 40 | 41 | 42 | Khaki 43 | 44 | 45 | 46 | 47 | Maroon 48 | 49 | 50 | 51 | 52 |
    53 |
    54 | ); 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /examples/components/views/SizeAwareView/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Context from 'react-famous/core/Context'; 3 | import Modifier from 'react-famous/core/Modifier'; 4 | import Surface from 'react-famous/core/Surface'; 5 | import SizeAwareView from 'react-famous/views/SizeAwareView'; 6 | 7 | export default class extends React.Component { 8 | componentDidMount() { 9 | let sizeAwareView = this.refs.sizeAwareView.getFamous(); 10 | let surface = this.refs.surface.getFamous(); 11 | 12 | sizeAwareView._eventInput.on('parentResize', ([width, height]) => { 13 | surface.setContent(`Parent Size: ${width}px x ${height}px`); 14 | }); 15 | } 16 | 17 | render() { 18 | return ( 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | react-famous: React bridge to Famo.us 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | import './styles/index.less'; 2 | 3 | import 'famous/inputs/FastClick'; 4 | import './lib/overscroll'; 5 | 6 | import React from 'react'; 7 | import Router from 'react-router'; 8 | 9 | import routes from './routes'; 10 | 11 | Router.run(routes, function (Handler) { 12 | React.render(React.createElement(Handler), document.body); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/lib/createContent.jsx: -------------------------------------------------------------------------------- 1 | import isEqual from 'lodash/lang/isEqual'; 2 | import React from 'react'; 3 | 4 | export default (group, member) => { 5 | return class extends React.Component { 6 | shouldComponentUpdate(nextProps, nextState) { 7 | return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState); 8 | } 9 | 10 | render() { 11 | let Component = require(`react-proxy!../components/${group}/${member}/App`); 12 | 13 | return ( 14 |
    15 |
    16 | 17 | Source Code 18 | 19 |
    20 | 21 |
    22 | ); 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /examples/lib/overscroll.js: -------------------------------------------------------------------------------- 1 | // 2 | // A workarround to prevent iOS overscroll but allows overscroll on children elements. 3 | // https://github.com/pinadesign/overscroll 4 | // 5 | 6 | // JavaScript Document 7 | (function(){ 8 | // Declare variables 9 | var touch_x, touch_y, obj_x, obj_y, speed_x=0, speed_y=0, scrollanim; 10 | 11 | document.addEventListener('touchstart', function(e) { 12 | clearInterval(scrollanim); 13 | // Get Touch target 14 | obj_x = e.target 15 | obj_y = e.target 16 | // Get the target parent that is scrollable 17 | while ((window.getComputedStyle(obj_x)['overflow-x'] != "auto" && window.getComputedStyle(obj_x)['overflow-x'] != "scroll") || obj_x.parentNode == null) { 18 | obj_x = obj_x.parentNode 19 | } 20 | while ((window.getComputedStyle(obj_y)['overflow-y'] != "auto" && window.getComputedStyle(obj_y)['overflow-y'] != "auto") || obj_y.parentNode == null) { 21 | obj_y = obj_y.parentNode 22 | } 23 | // Get if no scrollable parents are present set null 24 | if (obj_x.parentNode == null) obj_x = null; 25 | if (obj_y.parentNode == null) obj_y = null; 26 | 27 | // Get the touch starting point 28 | var touch = e.touches[0]; 29 | touch_x = touch.pageX; 30 | touch_y = touch.pageY; 31 | }, false); 32 | 33 | document.addEventListener('touchmove', function(e) { 34 | // Clear animation 35 | clearInterval(scrollanim); 36 | 37 | // Prevent window scrolling 38 | e.preventDefault(); 39 | 40 | // Scroll according to movement 41 | var touch = e.touches[0]; 42 | obj_x.scrollLeft = obj_x.scrollLeft - (touch.pageX - touch_x) 43 | obj_y.scrollTop = obj_y.scrollTop - (touch.pageY - touch_y) 44 | 45 | // Set speed speed 46 | speed_x = (touch.pageX - touch_x) 47 | speed_y = (touch.pageY - touch_y) 48 | 49 | // Set new positon 50 | touch_x = touch.pageX; 51 | touch_y = touch.pageY; 52 | }, false); 53 | 54 | // Add a final animation as in iOS 55 | document.addEventListener('touchend', function(e) { 56 | // Clear previous animations 57 | clearInterval(scrollanim); 58 | 59 | // Animate 60 | scrollanim = setInterval(function() { 61 | obj_x.scrollLeft = obj_x.scrollLeft - speed_x 62 | obj_y.scrollTop = obj_y.scrollTop - speed_y 63 | // Decelerate 64 | speed_x = speed_x * 0.9; 65 | speed_y = speed_y * 0.9; 66 | 67 | // Stop animation at the end 68 | if (speed_x < 1 && speed_x > -1 && speed_y < 1 && speed_y > -1) clearInterval(scrollanim) 69 | },15) 70 | 71 | }, false); 72 | })(); -------------------------------------------------------------------------------- /examples/routes.jsx: -------------------------------------------------------------------------------- 1 | import { Route, DefaultRoute } from 'react-router'; 2 | 3 | import App from './components/App'; 4 | import Home from './components/Home'; 5 | import createContent from './lib/createContent'; 6 | import Pass from './routes/Pass'; 7 | 8 | export default ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ); 45 | -------------------------------------------------------------------------------- /examples/routes/Pass.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { RouteHandler } from 'react-router'; 3 | 4 | export default class extends React.Component { 5 | render() { 6 | return ; 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /examples/styles/index.less: -------------------------------------------------------------------------------- 1 | @import '~famous/core/famous.css'; 2 | 3 | html, body { 4 | height: 100%; 5 | margin: 0; 6 | padding: 0; 7 | width: 100%; 8 | } 9 | 10 | body { 11 | font-family: Tahoma, Geneva, sans-serif; 12 | font-size: 14px; 13 | overflow: hidden; 14 | opacity: .999999; /* ios8 hotfix */ 15 | -webkit-transform-style: preserve-3d; 16 | transform-style: preserve-3d; 17 | } 18 | 19 | a { 20 | color: #111; 21 | text-decoration: none; 22 | 23 | &:hover { 24 | text-decoration: underline; 25 | } 26 | } 27 | 28 | .app { 29 | > .menu { 30 | background-color: #eee; 31 | border-right: 1px solid #c8c8c8; 32 | bottom: 0; 33 | height: 100%; 34 | left: 0; 35 | overflow-y: auto; 36 | position: absolute; 37 | top: 0; 38 | width: 170px; 39 | z-index: 1000; 40 | 41 | > nav { 42 | font-size: 1.5em; 43 | font-weight: bold; 44 | padding: 17px 0; 45 | text-align: center; 46 | } 47 | 48 | section.group { 49 | margin-bottom: 10px; 50 | 51 | > header { 52 | background-color: #c8c8c8; 53 | font-size: 1.2em; 54 | text-align: center; 55 | padding: 5px; 56 | } 57 | 58 | > ul { 59 | list-style-type: none; 60 | padding: 0; 61 | 62 | > li { 63 | padding: 3px 15px; 64 | } 65 | } 66 | } 67 | } 68 | 69 | > .content { 70 | height: 100%; 71 | left: 170px; 72 | position: absolute; 73 | right: 0; 74 | 75 | .home { 76 | a { 77 | background-color: #eee; 78 | padding: 7px 15px; 79 | } 80 | } 81 | 82 | .example { 83 | .source-code { 84 | background-color: rgba(0, 0, 0, 0.5); 85 | padding: 10px 15px; 86 | position: absolute; 87 | right: 0; 88 | text-align: center; 89 | top: 0; 90 | z-index: 999; 91 | 92 | a { 93 | color: #eee; 94 | } 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /examples/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | var webpack = require('webpack'); 4 | 5 | module.exports = { 6 | debug: true, 7 | devtool: 'source-map', 8 | entry: { 9 | main: path.join(__dirname, 'index.js') 10 | }, 11 | module: { 12 | loaders: [ 13 | {test: /\.js$/, loader: 'babel?blacklist[]=react', exclude: /node_modules/}, 14 | {test: /\.jsx$/, loaders: ['imports?React=react', 'react-hot', 'babel']}, 15 | {test: /\.css$/, loader: 'style!css'}, 16 | {test: /\.less$/, loader: 'style!css!less'} 17 | ] 18 | }, 19 | output: { 20 | filename: '[name].js', 21 | path: path.join(__dirname, '../dist/examples'), 22 | publicPath: '/_assets/' 23 | }, 24 | plugins: [ 25 | new webpack.DefinePlugin({ 26 | __DEV__: true 27 | }) 28 | ], 29 | resolve: { 30 | alias: { 31 | 'react-famous': path.join(__dirname, '../src') 32 | }, 33 | extensions: [ 34 | '', 35 | '.js', 36 | '.jsx' 37 | ], 38 | root: __dirname 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /examples/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | var webpack = require('webpack'); 5 | 6 | module.exports = { 7 | entry: { 8 | main: path.join(__dirname, 'index.js') 9 | }, 10 | module: { 11 | loaders: [ 12 | {test: /\.js$/, loader: 'babel?blacklist[]=react', exclude: /node_modules/}, 13 | {test: /\.jsx$/, loaders: ['imports?React=react', 'react-hot', 'babel']}, 14 | {test: /\.css$/, loader: ExtractTextPlugin.extract('style', 'css')}, 15 | {test: /\.less$/, loader: ExtractTextPlugin.extract('style', 'css!less')} 16 | ] 17 | }, 18 | output: { 19 | chunkFilename: 'js/[name].js?[chunkhash]', 20 | filename: 'js/[name].js?[chunkhash]', 21 | path: path.join(__dirname, '../dist/examples') 22 | }, 23 | plugins: [ 24 | new webpack.DefinePlugin({ 25 | '__DEV__': false, 26 | 'process.env': { 27 | NODE_ENV: JSON.stringify('production') 28 | } 29 | }), 30 | new webpack.optimize.UglifyJsPlugin({ 31 | output: { 32 | comments: false 33 | } 34 | }), 35 | new webpack.optimize.DedupePlugin(), 36 | new webpack.NoErrorsPlugin(), 37 | new ExtractTextPlugin('css/[name].css?[contenthash]') 38 | ], 39 | resolve: { 40 | alias: { 41 | 'react-famous': path.join(__dirname, '../src') 42 | }, 43 | extensions: [ 44 | '', 45 | '.js', 46 | '.jsx' 47 | ], 48 | root: __dirname 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var util = require('util'); 3 | 4 | var gulp = require('gulp-help')(require('gulp')); 5 | var gulpBabel = require('gulp-babel'); 6 | var gulpRename = require('gulp-rename'); 7 | var gulpShell = require('gulp-shell'); 8 | var gulpUtil = require('gulp-util'); 9 | var mergeStream = require('merge-stream'); 10 | var merge = require('lodash/object/merge'); 11 | var minimist = require('minimist'); 12 | 13 | gulp.task('clean', 'Clean built files.', function (cb) { 14 | var del = require('del'); 15 | del('dist', cb); 16 | }); 17 | 18 | gulp.task('build', 'Build for all targets.', [ 19 | 'build-amd', 20 | 'build-cjs', 21 | 'build-examples' 22 | ]); 23 | 24 | gulp.task('build-amd', 'Build for AMD.', function () { 25 | var gulpWrapAMD = require('gulp-wrap-amd'); 26 | 27 | var copy = gulp 28 | .src('tools/copy/amd/**') 29 | .pipe(gulp.dest('dist/amd')); 30 | 31 | var src = gulp 32 | .src('src/**/*.{js,jsx}') 33 | .pipe(gulpBabel()) 34 | .pipe(gulpWrapAMD()) 35 | .pipe(gulpRename({extname: '.js'})) 36 | .pipe(gulp.dest('dist/amd')); 37 | 38 | return mergeStream(copy, src); 39 | }); 40 | 41 | gulp.task('build-cjs', 'Build for CommonJS.', function () { 42 | var copy = gulp 43 | .src('tools/publish/cjs/**') 44 | .pipe(gulp.dest('dist/cjs')); 45 | 46 | var src = gulp 47 | .src('src/**/*.{js,jsx}') 48 | .pipe(gulpBabel()) 49 | .pipe(gulpRename({extname: '.js'})) 50 | .pipe(gulp.dest('dist/cjs')); 51 | 52 | return mergeStream(copy, src); 53 | }); 54 | 55 | gulp.task('build-examples', 'Build examples.', function () { 56 | var build = gulp.src('') 57 | .pipe(gulpShell([ 58 | 'node_modules/.bin/webpack', 59 | '--colors', 60 | '--config examples/webpack.config.prod.js', 61 | '--profile', 62 | '--progress' 63 | ].join(' '), {cwd: __dirname})); 64 | 65 | var copy = gulp 66 | .src('tools/publish/examples/**') 67 | .pipe(gulp.dest('dist/examples')); 68 | 69 | return mergeStream(build, copy); 70 | }); 71 | 72 | gulp.task('examples', 'Run examples.', function () { 73 | var options = minimist(process.argv.slice(2), { 74 | alias: { 75 | p: 'port' 76 | }, 77 | default: { 78 | port: 8080 79 | } 80 | }); 81 | 82 | gulpUtil.log('[webpack-dev-server]', util.format('http://localhost:%d/', options.port)); 83 | 84 | return gulp.src('') 85 | .pipe(gulpShell([ 86 | 'node_modules/.bin/webpack-dev-server', 87 | '--colors', 88 | '--config examples/webpack.config.js', 89 | '--content-base examples', 90 | '--hot', 91 | '--inline', 92 | util.format('--port %d', options.port), 93 | '--progress' 94 | ].join(' '), {cwd: __dirname})); 95 | }, { 96 | options: { 97 | 'port ': 'port (default: 8080)' 98 | } 99 | }); 100 | 101 | gulp.task('publish', 'Publish all targets.', [ 102 | 'publish-amd', 103 | 'publish-cjs' 104 | ]); 105 | 106 | gulp.task('publish-amd', 'Publish AMD.', function () { 107 | }); 108 | 109 | gulp.task('publish-cjs', 'Publish CommonJS.', function () { 110 | return gulp.src('') 111 | .pipe(gulpShell([ 112 | 'npm publish dist/cjs' 113 | ], {cwd: __dirname})); 114 | }); 115 | 116 | gulp.task('publish-examples', 'Publish Examples.', function () { 117 | return gulp.src('') 118 | .pipe(gulpShell([ 119 | 'git init', 120 | 'git add .', 121 | 'git commit -m Publish', 122 | 'git remote add origin git@github.com:react-famous/react-famous.github.io.git', 123 | 'git push -fu origin master' 124 | ].join('&&'), {cwd: path.join(__dirname, 'dist/examples')})); 125 | }); 126 | 127 | gulp.task('default', false, ['help']); 128 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "babel": "^4.7.3", 5 | "babel-core": "^4.7.3", 6 | "babel-loader": "^4.1.0", 7 | "css-loader": "^0.9.1", 8 | "del": "^1.1.1", 9 | "extract-text-webpack-plugin": "^0.3.8", 10 | "famous": "^0.3.5", 11 | "gulp": "^3.8.11", 12 | "gulp-babel": "^4.0.0", 13 | "gulp-help": "^1.3.3", 14 | "gulp-rename": "^1.2.0", 15 | "gulp-shell": "^0.3.0", 16 | "gulp-util": "^3.0.4", 17 | "gulp-wrap-amd": "^0.4.1", 18 | "imports-loader": "^0.6.3", 19 | "less": "^2.4.0", 20 | "less-loader": "^2.1.0", 21 | "lodash": "^3.4.0", 22 | "merge-stream": "^0.1.7", 23 | "minimist": "^1.1.0", 24 | "react": "^0.13.1", 25 | "react-hot-loader": "^1.1.7", 26 | "react-proxy-loader": "^0.3.3", 27 | "react-router": "^0.13.2", 28 | "style-loader": "^0.8.3", 29 | "webpack": "^1.7.2", 30 | "webpack-dev-server": "^1.7.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/core/Context.jsx: -------------------------------------------------------------------------------- 1 | import FamousContext from 'famous/core/Context'; 2 | import isUndefined from 'lodash/lang/isUndefined'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | import Engine from './Engine'; 8 | 9 | class Context extends FamousComponent { 10 | constructor(...args) { 11 | super(...args); 12 | 13 | this.famousContext = true; 14 | } 15 | 16 | famousCreate() { 17 | return Engine.createContext(React.findDOMNode(this.refs.container)); 18 | } 19 | 20 | famousCreateNode() { 21 | let context = this.getFamous(); 22 | let node = context; 23 | let next = this.getFamousChildrenRef().map((child) => [child, context]); 24 | return [node, next]; 25 | } 26 | 27 | famousDelete() { 28 | Engine.deregisterContext(this.getFamousNode()); 29 | } 30 | 31 | famousUpdate(nextProps) { 32 | let context = this.getFamous(); 33 | 34 | if (!isUndefined(nextProps.perspective)) { 35 | context.setPerspective(nextProps.perspective); 36 | } 37 | } 38 | 39 | render() { 40 | return ( 41 |
    42 |
    43 | {this.getFamousChildren()} 44 |
    45 |
    46 |
    47 | ); 48 | } 49 | } 50 | 51 | defaults(Context, FamousContext); 52 | 53 | Context.propTypes = { 54 | perspective: React.PropTypes.number 55 | }; 56 | 57 | export default Context; 58 | -------------------------------------------------------------------------------- /src/core/Engine.js: -------------------------------------------------------------------------------- 1 | import FamousEngine from 'famous/core/Engine'; 2 | // import ReactUpdates from 'react/lib/ReactUpdates'; 3 | 4 | import '../lib/FamousPatch'; 5 | 6 | // ReactUpdates.injection.injectBatchingStrategy({ 7 | // isBatchingUpdates: true, 8 | // batchedUpdates(callback, param) { 9 | // callback(param); 10 | // } 11 | // }); 12 | // FamousEngine.on('prerender', ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)); 13 | 14 | FamousEngine.setOptions({ 15 | appMode: false 16 | }); 17 | 18 | export default FamousEngine; 19 | -------------------------------------------------------------------------------- /src/core/Modifier.jsx: -------------------------------------------------------------------------------- 1 | import FamousModifier from 'famous/core/Modifier'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class Modifier extends FamousComponent { 8 | famousCreate() { 9 | return new FamousModifier(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let modifier = this.getFamous(); 14 | let node = parentNode.add(modifier); 15 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 16 | return [node, next]; 17 | } 18 | 19 | famousUpdate(nextProps) { 20 | let modifier = this.getFamous(); 21 | 22 | if (nextProps.options.transform) { 23 | modifier.setTransform(nextProps.options.transform); 24 | } 25 | if (nextProps.options.opacity !== undefined) { 26 | modifier.setOpacity(nextProps.options.opacity); 27 | } 28 | if (nextProps.options.origin) { 29 | modifier.setOrigin(nextProps.options.origin); 30 | } 31 | if (nextProps.options.align) { 32 | modifier.setAlign(nextProps.options.align); 33 | } 34 | if (nextProps.options.size) { 35 | modifier.setSize(nextProps.options.size); 36 | } 37 | if (nextProps.options.proportions) { 38 | modifier.setProportions(nextProps.options.proportions); 39 | } 40 | } 41 | 42 | render() { 43 | return ( 44 |
    45 | {this.getFamousChildren()} 46 |
    47 | ); 48 | } 49 | } 50 | 51 | defaults(Modifier, FamousModifier); 52 | 53 | export default Modifier; 54 | -------------------------------------------------------------------------------- /src/core/RenderNode.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class RenderNode extends FamousComponent { 8 | famousCreate() { 9 | return new FamousRenderNode(); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let renderNode = this.getFamous(); 14 | let node = parentNode.add(renderNode); 15 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 16 | return [node, next]; 17 | } 18 | 19 | render() { 20 | return ( 21 |
    22 | {this.getFamousChildren()} 23 |
    24 | ); 25 | } 26 | } 27 | 28 | defaults(RenderNode, FamousRenderNode); 29 | 30 | export default RenderNode; 31 | -------------------------------------------------------------------------------- /src/core/Surface.jsx: -------------------------------------------------------------------------------- 1 | import FamousSurface from 'famous/core/Surface'; 2 | import isUndefined from 'lodash/lang/isUndefined'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | import FamousConstants from '../lib/FamousConstants'; 8 | import FamousUtil from '../lib/FamousUtil'; 9 | 10 | class Surface extends FamousComponent { 11 | famousCreate() { 12 | let surface = new FamousSurface(this.props.options); 13 | 14 | FamousConstants.SURFACE_EVENTS.forEach((event) => { 15 | if (this.props[event.prop]) { 16 | surface.on(event.type, () => { 17 | this.props[event.prop](this.props.eventKey); 18 | }); 19 | } 20 | }); 21 | 22 | return surface; 23 | } 24 | 25 | famousCreateNode(parentNode) { 26 | let surface = this.getFamous(); 27 | let node = parentNode.add(surface); 28 | return [node, null]; 29 | } 30 | 31 | famousUpdate(nextProps) { 32 | let surface = this.getFamous(); 33 | let content; 34 | 35 | if (!isUndefined(nextProps.children)) { 36 | content = FamousUtil.renderContent(nextProps.children); 37 | } 38 | 39 | surface.setOptions(defaults({}, nextProps.options, {content})); 40 | } 41 | 42 | render() { 43 | return ( 44 |
    45 | ); 46 | } 47 | } 48 | 49 | defaults(Surface, FamousSurface); 50 | 51 | Surface.propTypes = defaults({}, FamousConstants.SURFACE_PROPTYPES); 52 | 53 | export default Surface; 54 | -------------------------------------------------------------------------------- /src/core/View.jsx: -------------------------------------------------------------------------------- 1 | import FamousView from 'famous/core/View'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class View extends FamousComponent { 8 | famousCreate() { 9 | return new FamousView(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let view = this.getFamous(); 14 | parentNode.add(view); 15 | let next = this.getFamousChildrenRef().map((child, idx) => [child, view]); 16 | return [view, next]; 17 | } 18 | 19 | famousUpdate(nextProps) { 20 | let view = this.getFamous(); 21 | 22 | view.setOptions(nextProps.options); 23 | } 24 | 25 | render() { 26 | return ( 27 |
    28 | {this.getFamousChildren()} 29 |
    30 | ); 31 | } 32 | } 33 | 34 | defaults(View, FamousView); 35 | 36 | export default View; 37 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export default { 2 | core: { 3 | Context: require('./core/Context'), 4 | Engine: require('./core/Engine'), 5 | Modifier: require('./core/Modifier'), 6 | RenderNode: require('./core/RenderNode'), 7 | Surface: require('./core/Surface'), 8 | View: require('./core/View') 9 | }, 10 | lib: { 11 | FamousComponent: require('./lib/FamousComponent'), 12 | FamousConstants: require('./lib/FamousConstants'), 13 | FamousMixin: require('./lib/FamousMixin'), 14 | FamousNodeMixin: require('./lib/FamousNodeMixin'), 15 | FamousPatch: require('./lib/FamousPatch'), 16 | FamousScheduler: require('./lib/FamousScheduler'), 17 | FamousUtil: require('./lib/FamousUtil'), 18 | ReactNode: require('./lib/ReactNode') 19 | }, 20 | modifiers: { 21 | Draggable: require('./modifiers/Draggable'), 22 | ModifierChain: require('./modifiers/ModifierChain'), 23 | StateModifier: require('./modifiers/StateModifier') 24 | }, 25 | surfaces: { 26 | CanvasSurface: require('./surfaces/CanvasSurface'), 27 | ContainerSurface: require('./surfaces/ContainerSurface'), 28 | FormContainerSurface: require('./surfaces/FormContainerSurface'), 29 | ImageSurface: require('./surfaces/ImageSurface'), 30 | InputSurface: require('./surfaces/InputSurface'), 31 | SubmitInputSurface: require('./surfaces/SubmitInputSurface'), 32 | TextareaSurface: require('./surfaces/TextareaSurface'), 33 | VideoSurface: require('./surfaces/VideoSurface') 34 | }, 35 | views: { 36 | ContextualView: require('./views/ContextualView'), 37 | Deck: require('./views/Deck'), 38 | DrawerLayout: require('./views/DrawerLayout'), 39 | EdgeSwapper: require('./views/EdgeSwapper'), 40 | FlexibleLayout: require('./views/FlexibleLayout'), 41 | Flipper: require('./views/Flipper'), 42 | GridLayout: require('./views/GridLayout'), 43 | HeaderFooterLayout: require('./views/HeaderFooterLayout'), 44 | Lightbox: require('./views/Lightbox'), 45 | RenderController: require('./views/RenderController'), 46 | ScrollContainer: require('./views/ScrollContainer'), 47 | Scroller: require('./views/Scroller'), 48 | Scrollview: require('./views/Scrollview'), 49 | SequentialLayout: require('./views/SequentialLayout'), 50 | SizeAwareView: require('./views/SizeAwareView') 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /src/lib/FamousComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import FamousMixin from './FamousMixin'; 4 | 5 | export default React.createClass({ 6 | mixins: [FamousMixin], 7 | 8 | render() { 9 | // Override me 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /src/lib/FamousConstants.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const SURFACE_EVENTS = [ 4 | {prop: 'onClick', type: 'click'}, 5 | {prop: 'onKeyDown', type: 'keydown'}, 6 | {prop: 'onKeyPress', type: 'keypress'}, 7 | {prop: 'onKeyUp', type: 'keyup'}, 8 | {prop: 'onMouseDown', type: 'mousedown'}, 9 | {prop: 'onMouseMove', type: 'mousemove'}, 10 | {prop: 'onMouseOut', type: 'mouseout'}, 11 | {prop: 'onMouseOver', type: 'mouseover'}, 12 | {prop: 'onMouseUp', type: 'mouseup'}, 13 | {prop: 'onTouchCancel', type: 'touchcancel'}, 14 | {prop: 'onTouchEnd', type: 'touchend'}, 15 | {prop: 'onTouchMove', type: 'touchmove'}, 16 | {prop: 'onTouchStart', type: 'touchstart'} 17 | ]; 18 | 19 | export const SURFACE_PROPTYPES = { 20 | eventKey: React.PropTypes.any, 21 | onClick: React.PropTypes.func, 22 | onKeyDown: React.PropTypes.func, 23 | onKeyPress: React.PropTypes.func, 24 | onKeyUp: React.PropTypes.func, 25 | onMouseDown: React.PropTypes.func, 26 | onMouseMove: React.PropTypes.func, 27 | onMouseOut: React.PropTypes.func, 28 | onMouseOver: React.PropTypes.func, 29 | onMouseUp: React.PropTypes.func, 30 | onTouchCancel: React.PropTypes.func, 31 | onTouchEnd: React.PropTypes.func, 32 | onTouchMove: React.PropTypes.func, 33 | onTouchStart: React.PropTypes.func 34 | }; 35 | 36 | export default { 37 | SURFACE_EVENTS, 38 | SURFACE_PROPTYPES 39 | }; 40 | -------------------------------------------------------------------------------- /src/lib/FamousMixin.js: -------------------------------------------------------------------------------- 1 | import isEqual from 'lodash/lang/isEqual'; 2 | import isFunction from 'lodash/lang/isFunction'; 3 | import values from 'lodash/object/values'; 4 | import React from 'react'; 5 | import shallowEqual from 'react/lib/shallowEqual'; 6 | 7 | import FamousNodeMixin from './FamousNodeMixin'; 8 | import FamousScheduler from './FamousScheduler'; 9 | import FamousUtil from './FamousUtil'; 10 | 11 | export default { 12 | mixins: [FamousNodeMixin], 13 | 14 | propTypes: { 15 | options: React.PropTypes.object 16 | }, 17 | 18 | getDefaultProps() { 19 | return { 20 | options: {} 21 | }; 22 | }, 23 | 24 | componentWillMount() { 25 | if (!this.famousContext) { 26 | if (isFunction(this.famousCreate)) { 27 | this.setFamous(this.famousCreate()); 28 | } 29 | if (isFunction(this.famousUpdate)) { 30 | this.famousUpdate(this.props, this.state); 31 | } 32 | } 33 | }, 34 | 35 | _createFamousNode(component, parentNode = null) { 36 | if (FamousUtil.isFamous(component)) { 37 | if (isFunction(component.famousCreateNode)) { 38 | let [node, next] = component.famousCreateNode(parentNode); 39 | component.setFamousNode(node); 40 | (next || []).forEach(([child, parentNode]) => { 41 | this._createFamousNode(child, parentNode); 42 | }); 43 | } 44 | } else { 45 | let instance = FamousUtil.getInstance(component); 46 | FamousUtil.getFamousChildren(instance).forEach((child) => { 47 | this._createFamousNode(child, parentNode); 48 | }); 49 | } 50 | }, 51 | 52 | componentDidMount() { 53 | if (this.famousContext) { 54 | if (isFunction(this.famousCreate)) { 55 | this.setFamous(this.famousCreate()); 56 | } 57 | if (isFunction(this.famousUpdate)) { 58 | this.famousUpdate(this.props, this.state); 59 | } 60 | this._createFamousNode(this); 61 | setTimeout(FamousScheduler.run); 62 | } 63 | }, 64 | 65 | shouldComponentUpdate(nextProps, nextState) { 66 | return !shallowEqual(this.props, nextProps) || 67 | !shallowEqual(this.state, nextState) || 68 | !isEqual(this.props.options, nextProps.options); 69 | }, 70 | 71 | componentWillUpdate(nextProps, nextState) { 72 | if (isFunction(this.famousUpdate)) { 73 | this.famousUpdate(nextProps, nextState); 74 | } 75 | }, 76 | 77 | componentWillUnmount() { 78 | if (isFunction(this.famousDelete)) { 79 | this.famousDelete(); 80 | } 81 | this.releaseFamous(); 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /src/lib/FamousNodeMixin.js: -------------------------------------------------------------------------------- 1 | import merge from 'lodash/object/merge'; 2 | import React from 'react'; 3 | 4 | const FAMOUS_KEY = '__famous__'; 5 | const FAMOUS_NODE_KEY = '__famous_node__'; 6 | 7 | export default { 8 | createFamousWrapper(child, props) { 9 | return React.createElement('div', merge({ 10 | 'data-famous': 'Wrapper' 11 | }, props), child); 12 | }, 13 | 14 | getFamous() { 15 | return this[FAMOUS_KEY]; 16 | }, 17 | 18 | getFamousNode() { 19 | return this[FAMOUS_NODE_KEY]; 20 | }, 21 | 22 | getFamousChildren() { 23 | let result = []; 24 | let children = React.Children.forEach(this.props.children, (child, idx) => { 25 | result.push(this.createFamousWrapper(child, {key: idx, ref: idx})); 26 | }); 27 | return result; 28 | }, 29 | 30 | getFamousChildrenRef() { 31 | return this.getFamousChildren().map((child, idx) => { 32 | return this.refs[idx]; 33 | }); 34 | }, 35 | 36 | releaseFamous() { 37 | delete this[FAMOUS_KEY]; 38 | delete this[FAMOUS_NODE_KEY]; 39 | }, 40 | 41 | setFamous(famousInstance) { 42 | this[FAMOUS_KEY] = famousInstance; 43 | }, 44 | 45 | setFamousNode(famousNode) { 46 | this[FAMOUS_NODE_KEY] = famousNode; 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /src/lib/FamousPatch.js: -------------------------------------------------------------------------------- 1 | import ElementAllocator from 'famous/core/ElementAllocator'; 2 | 3 | let _allocate = ElementAllocator.prototype.allocate; 4 | 5 | ElementAllocator.prototype.allocate = function () { 6 | let result = _allocate.apply(this, arguments); 7 | this.container.appendChild(result); 8 | return result; 9 | }; 10 | -------------------------------------------------------------------------------- /src/lib/FamousScheduler.js: -------------------------------------------------------------------------------- 1 | const _callbacks = []; 2 | 3 | export function schedule(cb, delay) { 4 | _callbacks.push([cb, delay]); 5 | } 6 | 7 | export function run() { 8 | while (_callbacks.length) { 9 | let [cb, delay] = _callbacks.shift(); 10 | 11 | if (delay) { 12 | setTimeout(cb, delay); 13 | } else { 14 | cb(); 15 | } 16 | } 17 | } 18 | 19 | export default { 20 | schedule, 21 | run 22 | }; 23 | -------------------------------------------------------------------------------- /src/lib/FamousUtil.js: -------------------------------------------------------------------------------- 1 | import isFunction from 'lodash/lang/isFunction'; 2 | import values from 'lodash/object/values'; 3 | import React from 'react'; 4 | import ReactInstanceMap from 'react/lib/ReactInstanceMap'; 5 | 6 | function _buildTraversePath(fromAncestor, toDescendant) { 7 | if (fromAncestor === toDescendant) { 8 | return [fromAncestor]; 9 | } 10 | let component; 11 | fromAncestor = getInstance(fromAncestor); 12 | if (component._renderedComponent) { 13 | let traversePath; 14 | if (isFunction(component._renderedComponent.getPublicInstance)) { 15 | traversePath = _buildTraversePath(component._renderedComponent.getPublicInstance(), toDescendant); 16 | } else { 17 | traversePath = _buildTraversePath(component._renderedComponent, toDescendant); 18 | } 19 | if (traversePath) { 20 | return [fromAncestor].concat(traversePath); 21 | } 22 | } else if (component._renderedChildren) { 23 | let children = values(component._renderedChildren); 24 | for (let i = 0; i < children.length; ++i) { 25 | let child = children[i]; 26 | let traversePath = _buildTraversePath(child.getPublicInstance(), toDescendant); 27 | if (traversePath) { 28 | return [fromAncestor].concat(traversePath); 29 | } 30 | } 31 | } 32 | return null; 33 | } 34 | 35 | function _findKeyFromNearestDescendant(traversePath, root) { 36 | for (let i = 0; i < traversePath.length; ++i) { 37 | if (traversePath[i] === root) { 38 | let descendants = traversePath.slice(i + 1); 39 | for (let j = 0; j < descendants.length; ++j) { 40 | let descendant = descendants[j]; 41 | descendant = getInstance(descendant); 42 | if (descendant._currentElement.key) { 43 | return descendant._currentElement.key; 44 | } 45 | } 46 | break; 47 | } 48 | } 49 | return null; 50 | } 51 | 52 | function _findNearestFamousAncestor(component, searchedSubpath = []) { 53 | let owner = getOwner(component); 54 | if (!owner || owner === component) { 55 | return null; 56 | } 57 | let traversePath = _buildTraversePath(owner, component).concat(searchedSubpath); 58 | let famousTraversePath = traversePath.slice(0, -1).filter(isFamous); 59 | if (famousTraversePath.length) { 60 | return famousTraversePath.slice(-1)[0]; 61 | } else { 62 | let searchedSubpath = traversePath.slice(1); 63 | return _findNearestFamousAncestor(owner, searchedSubpath); 64 | } 65 | } 66 | 67 | export function getFamousChildren(component) { 68 | if (component._renderedComponent && 69 | isFunction(component._renderedComponent.getPublicInstance)) { 70 | return [component._renderedComponent.getPublicInstance()]; 71 | } 72 | let instance = component; 73 | while (instance._renderedComponent && !instance._renderedChildren) { 74 | instance = instance._renderedComponent; 75 | } 76 | if (instance._renderedChildren) { 77 | return values(instance._renderedChildren).map((child) => { 78 | return child.getPublicInstance(); 79 | }); 80 | } 81 | return []; 82 | } 83 | 84 | export function getFamousParent(component) { 85 | return _findNearestFamousAncestor(component); 86 | } 87 | 88 | export function getInstance(component) { 89 | if (ReactInstanceMap.has(component)) { 90 | return ReactInstanceMap.get(component); 91 | } 92 | return component; 93 | } 94 | 95 | export function getOwner(component) { 96 | let pointer = getInstance(component); 97 | let owner = null; 98 | do { 99 | pointer = pointer._currentElement._owner; 100 | if (!pointer) { break; } 101 | owner = pointer._renderedComponent.getPublicInstance(); 102 | } while (owner === component); 103 | return owner; 104 | } 105 | 106 | export function isFamous(component) { 107 | let FamousComponent = require('./FamousComponent'); 108 | return component instanceof FamousComponent; 109 | } 110 | 111 | export function renderContent(obj) { 112 | if (Array.isArray(obj)) { 113 | return obj.map((obj) => { 114 | return renderContent(obj); 115 | }).join(''); 116 | } else if (React.isValidElement(obj)) { 117 | return React.renderToString(obj); 118 | } else { 119 | return obj; 120 | } 121 | } 122 | 123 | export default { 124 | getFamousChildren, 125 | getFamousParent, 126 | getInstance, 127 | getOwner, 128 | isFamous, 129 | renderContent 130 | }; 131 | -------------------------------------------------------------------------------- /src/lib/ReactNode.jsx: -------------------------------------------------------------------------------- 1 | import FamousSurface from 'famous/core/Surface'; 2 | import isArray from 'lodash/lang/isArray'; 3 | import isString from 'lodash/lang/isString'; 4 | import defaults from 'lodash/object/defaults'; 5 | import React from 'react'; 6 | 7 | import FamousComponent from './FamousComponent'; 8 | 9 | export class FamousReactNode extends FamousSurface { 10 | constructor(options, context) { 11 | super(options); 12 | 13 | this._reactContext = context; 14 | 15 | this.deploy = this.recall = () => {}; 16 | 17 | this.on('deploy', this.onDeploy); 18 | this.on('recall', this.onRecall); 19 | } 20 | 21 | onDeploy() { 22 | let content = this.getContent(); 23 | let context = this._reactContext; 24 | let target = this._currentTarget; 25 | 26 | if (Array.isArray(content)) { 27 | content = ( 28 |
    {content}
    29 | ); 30 | } else if (isString(content)) { 31 | content = ( 32 | {content} 33 | ); 34 | } 35 | 36 | if (React.isValidElement(content)) { 37 | if (context) { 38 | React.withContext(context, () => { 39 | React.render(content, target); 40 | }); 41 | } else { 42 | React.render(content, target); 43 | } 44 | } else { 45 | throw new Error('Content is not a valid react component'); 46 | } 47 | } 48 | 49 | onRecall() { 50 | let target = this._currentTarget; 51 | 52 | React.unmountComponentAtNode(target); 53 | } 54 | } 55 | 56 | export class ReactNode extends FamousComponent { 57 | famousCreate() { 58 | return new FamousReactNode(defaults(this.props.options, { 59 | properties: { 60 | overflow: 'hidden' 61 | } 62 | })); 63 | } 64 | 65 | famousCreateNode(parentNode) { 66 | let reactNode = this.getFamous(); 67 | let node = parentNode.add(reactNode); 68 | return [node, null]; 69 | } 70 | 71 | famousUpdate(nextProps) { 72 | let reactNode = this.getFamous(); 73 | let content = this.props.children; 74 | 75 | reactNode.setOptions(defaults({}, nextProps.options, {content})); 76 | } 77 | 78 | render() { 79 | return ( 80 |
    81 | ); 82 | } 83 | } 84 | 85 | defaults(ReactNode, FamousReactNode); 86 | 87 | export default ReactNode; 88 | -------------------------------------------------------------------------------- /src/modifiers/Draggable.jsx: -------------------------------------------------------------------------------- 1 | import FamousDraggable from 'famous/modifiers/Draggable'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class Draggable extends FamousComponent { 8 | famousCreate() { 9 | return new FamousDraggable(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let draggable = this.getFamous(); 14 | let node = parentNode.add(draggable); 15 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 16 | return [node, next]; 17 | } 18 | 19 | famousUpdate(nextProps) { 20 | let draggable = this.getFamous(); 21 | 22 | draggable.setOptions(nextProps.options); 23 | } 24 | 25 | render() { 26 | return ( 27 |
    28 | {this.getFamousChildren()} 29 |
    30 | ); 31 | } 32 | } 33 | 34 | defaults(Draggable, FamousDraggable); 35 | 36 | export default Draggable; 37 | -------------------------------------------------------------------------------- /src/modifiers/ModifierChain.jsx: -------------------------------------------------------------------------------- 1 | import FamousModifierChain from 'famous/modifiers/ModifierChain'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class ModifierChain extends FamousComponent { 8 | famousCreate() { 9 | let modifierChain = new FamousModifierChain(this.props.options); 10 | 11 | this.props.modifiers.forEach((modifier) => modifierChain.addModifier(modifier)); 12 | 13 | return modifierChain; 14 | } 15 | 16 | famousCreateNode(parentNode) { 17 | let modifierChain = this.getFamous(); 18 | let node = parentNode.add(modifierChain); 19 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 20 | return [node, next]; 21 | } 22 | 23 | famousUpdate(nextProps) { 24 | let modifierChain = this.getFamous(); 25 | 26 | this._chain.length = 0; 27 | nextProps.modifiers.forEach((modifier) => modifierChain.addModifier(modifier)); 28 | } 29 | 30 | render() { 31 | return ( 32 |
    33 | {this.getFamousChildren()} 34 |
    35 | ); 36 | } 37 | } 38 | 39 | defaults(ModifierChain, FamousModifierChain); 40 | 41 | ModifierChain.propTypes = { 42 | modifiers: React.PropTypes.array 43 | }; 44 | 45 | export default ModifierChain; 46 | -------------------------------------------------------------------------------- /src/modifiers/StateModifier.jsx: -------------------------------------------------------------------------------- 1 | import FamousStateModifier from 'famous/modifiers/StateModifier'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class StateModifier extends FamousComponent { 8 | famousCreate() { 9 | return new FamousStateModifier(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let stateModifier = this.getFamous(); 14 | let node = parentNode.add(stateModifier); 15 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 16 | return [node, next]; 17 | } 18 | 19 | famousUpdate(nextProps) { 20 | let stateModifier = this.getFamous(); 21 | 22 | if (nextProps.options.transform) { 23 | stateModifier.setTransform(nextProps.options.transform); 24 | } 25 | if (nextProps.options.opacity !== undefined) { 26 | stateModifier.setOpacity(nextProps.options.opacity); 27 | } 28 | if (nextProps.options.origin) { 29 | stateModifier.setOrigin(nextProps.options.origin); 30 | } 31 | if (nextProps.options.align) { 32 | stateModifier.setAlign(nextProps.options.align); 33 | } 34 | if (nextProps.options.size) { 35 | stateModifier.setSize(nextProps.options.size); 36 | } 37 | if (nextProps.options.proportions) { 38 | stateModifier.setProportions(nextProps.options.proportions); 39 | } 40 | } 41 | 42 | render() { 43 | return ( 44 |
    45 | {this.getFamousChildren()} 46 |
    47 | ); 48 | } 49 | } 50 | 51 | defaults(StateModifier, FamousStateModifier); 52 | 53 | export default StateModifier; 54 | -------------------------------------------------------------------------------- /src/surfaces/CanvasSurface.jsx: -------------------------------------------------------------------------------- 1 | import FamousCanvasSurface from 'famous/surfaces/CanvasSurface'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class CanvasSurface extends FamousComponent { 8 | famousCreate() { 9 | return new FamousCanvasSurface(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let surface = this.getFamous(); 14 | let node = parentNode.add(surface); 15 | return [node, null]; 16 | } 17 | 18 | famousUpdate(nextProps) { 19 | let canvasSurface = this.getFamous(); 20 | 21 | canvasSurface.setOptions(nextProps.options); 22 | } 23 | 24 | render() { 25 | return ( 26 |
    27 | ); 28 | } 29 | } 30 | 31 | defaults(CanvasSurface, FamousCanvasSurface); 32 | 33 | export default CanvasSurface; 34 | -------------------------------------------------------------------------------- /src/surfaces/ContainerSurface.jsx: -------------------------------------------------------------------------------- 1 | import FamousContainerSurface from 'famous/surfaces/ContainerSurface'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import Context from '../core/Context'; 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class ContainerSurface extends FamousComponent { 9 | famousCreate() { 10 | return new FamousContainerSurface(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let containerSurface = this.getFamous(); 15 | let node = parentNode.add(containerSurface); 16 | let next = this.getFamousChildrenRef().map((child, idx) => [child, containerSurface]); 17 | return [node, next]; 18 | } 19 | 20 | famousUpdate(nextProps) { 21 | let containerSurface = this.getFamous(); 22 | 23 | containerSurface.setOptions(nextProps.options); 24 | } 25 | 26 | render() { 27 | return ( 28 |
    29 | {this.getFamousChildren()} 30 |
    31 | ); 32 | } 33 | } 34 | 35 | defaults(ContainerSurface, FamousContainerSurface); 36 | 37 | export default ContainerSurface; 38 | -------------------------------------------------------------------------------- /src/surfaces/FormContainerSurface.jsx: -------------------------------------------------------------------------------- 1 | import FamousFormContainerSurface from 'famous/surfaces/FormContainerSurface'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import Context from '../core/Context'; 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class FormContainerSurface extends FamousComponent { 9 | famousCreate() { 10 | return new FamousFormContainerSurface(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let formContainerSurface = this.getFamous(); 15 | let node = parentNode.add(formContainerSurface); 16 | let next = this.getFamousChildrenRef().map((child, idx) => [child, formContainerSurface]); 17 | return [node, next]; 18 | } 19 | 20 | famousUpdate(nextProps) { 21 | let formContainerSurface = this.getFamous(); 22 | 23 | formContainerSurface.setOptions(nextProps.options); 24 | } 25 | 26 | render() { 27 | return ( 28 |
    29 | {this.getFamousChildren()} 30 |
    31 | ); 32 | } 33 | } 34 | 35 | defaults(FormContainerSurface, FamousFormContainerSurface); 36 | 37 | export default FormContainerSurface; 38 | -------------------------------------------------------------------------------- /src/surfaces/ImageSurface.jsx: -------------------------------------------------------------------------------- 1 | import FamousImageSurface from 'famous/surfaces/ImageSurface'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | import FamousConstants from '../lib/FamousConstants'; 7 | 8 | class ImageSurface extends FamousComponent { 9 | famousCreate() { 10 | let imageSurface = new FamousImageSurface(this.props.options); 11 | 12 | FamousConstants.SURFACE_EVENTS.forEach((event) => { 13 | if (this.props[event.prop]) { 14 | imageSurface.on(event.type, () => { 15 | this.props[event.prop](this.props.eventKey); 16 | }); 17 | } 18 | }); 19 | 20 | return imageSurface; 21 | } 22 | 23 | famousCreateNode(parentNode) { 24 | let imageSurface = this.getFamous(); 25 | let node = parentNode.add(imageSurface); 26 | return [node, null]; 27 | } 28 | 29 | famousUpdate(nextProps) { 30 | let imageSurface = this.getFamous(); 31 | 32 | imageSurface.setOptions(nextProps.options); 33 | } 34 | 35 | render() { 36 | return ( 37 |
    38 | ); 39 | } 40 | } 41 | 42 | defaults(ImageSurface, FamousImageSurface); 43 | 44 | ImageSurface.propTypes = defaults({}, FamousConstants.SURFACE_PROPTYPES); 45 | 46 | export default ImageSurface; 47 | -------------------------------------------------------------------------------- /src/surfaces/InputSurface.jsx: -------------------------------------------------------------------------------- 1 | import FamousInputSurface from 'famous/surfaces/InputSurface'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class InputSurface extends FamousComponent { 8 | famousCreate() { 9 | return new FamousInputSurface(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let inputSurface = this.getFamous(); 14 | let node = parentNode.add(inputSurface); 15 | return [node, null]; 16 | } 17 | 18 | famousUpdate(nextProps) { 19 | let inputSurface = this.getFamous(); 20 | 21 | inputSurface.setOptions(nextProps.options); 22 | } 23 | 24 | render() { 25 | return ( 26 |
    27 | ); 28 | } 29 | } 30 | 31 | defaults(InputSurface, FamousInputSurface); 32 | 33 | export default InputSurface; 34 | -------------------------------------------------------------------------------- /src/surfaces/SubmitInputSurface.jsx: -------------------------------------------------------------------------------- 1 | import FamousSubmitInputSurface from 'famous/surfaces/SubmitInputSurface'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class SubmitInputSurface extends FamousComponent { 8 | famousCreate() { 9 | return new FamousSubmitInputSurface(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let submitInputSurface = this.getFamous(); 14 | let node = parentNode.add(submitInputSurface); 15 | return [node, null]; 16 | } 17 | 18 | famousUpdate(nextProps) { 19 | let submitInputSurface = this.getFamous(); 20 | 21 | submitInputSurface.setOptions(nextProps.options); 22 | } 23 | 24 | render() { 25 | return ( 26 |
    27 | ); 28 | } 29 | } 30 | 31 | defaults(SubmitInputSurface, FamousSubmitInputSurface); 32 | 33 | export default SubmitInputSurface; 34 | -------------------------------------------------------------------------------- /src/surfaces/TextareaSurface.jsx: -------------------------------------------------------------------------------- 1 | import FamousTextareaSurface from 'famous/surfaces/TextareaSurface'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class TextareaSurface extends FamousComponent { 8 | famousCreate() { 9 | return new FamousTextareaSurface(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let textareaSurface = this.getFamous(); 14 | let node = parentNode.add(textareaSurface); 15 | return [node, null]; 16 | } 17 | 18 | famousUpdate(nextProps) { 19 | let textareaSurface = this.getFamous(); 20 | 21 | textareaSurface.setOptions(nextProps.options); 22 | } 23 | 24 | render() { 25 | return ( 26 |
    27 | ); 28 | } 29 | } 30 | 31 | defaults(TextareaSurface, FamousTextareaSurface); 32 | 33 | export default TextareaSurface; 34 | -------------------------------------------------------------------------------- /src/surfaces/VideoSurface.jsx: -------------------------------------------------------------------------------- 1 | import FamousVideoSurface from 'famous/surfaces/VideoSurface'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class VideoSurface extends FamousComponent { 8 | famousCreate() { 9 | return new FamousVideoSurface(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let videoSurface = this.getFamous(); 14 | let node = parentNode.add(videoSurface); 15 | return [node, null]; 16 | } 17 | 18 | famousUpdate(nextProps) { 19 | let videoSurface = this.getFamous(); 20 | 21 | videoSurface.setOptions(nextProps.options); 22 | } 23 | 24 | render() { 25 | return ( 26 |
    27 | ); 28 | } 29 | } 30 | 31 | defaults(VideoSurface, FamousVideoSurface); 32 | 33 | export default VideoSurface; 34 | -------------------------------------------------------------------------------- /src/views/ContextualView.jsx: -------------------------------------------------------------------------------- 1 | import FamousContextualView from 'famous/views/ContextualView'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class ContextualView extends FamousComponent { 8 | famousCreate() { 9 | return new FamousContextualView(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let contextualView = this.getFamous(); 14 | let node = parentNode.add(contextualView); 15 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 16 | return [node, next]; 17 | } 18 | 19 | famousUpdate(nextProps) { 20 | let contextualView = this.getFamous(); 21 | 22 | contextualView.setOptions(nextProps.options); 23 | } 24 | 25 | render() { 26 | return ( 27 |
    28 | {this.getFamousChildren()} 29 |
    30 | ); 31 | } 32 | } 33 | 34 | defaults(ContextualView, FamousContextualView); 35 | 36 | export default ContextualView; 37 | -------------------------------------------------------------------------------- /src/views/Deck.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousDeck from 'famous/views/Deck'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class Deck extends FamousComponent { 9 | famousCreate() { 10 | return new FamousDeck(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let deck = this.getFamous(); 15 | let node = parentNode.add(deck); 16 | let next = []; 17 | let sequence = this.getFamousChildrenRef().map((child, idx) => { 18 | let renderNode = new FamousRenderNode(); 19 | next.push([child, renderNode]); 20 | return renderNode; 21 | }); 22 | deck.sequenceFrom(sequence); 23 | return [node, next]; 24 | } 25 | 26 | famousUpdate(nextProps) { 27 | let deck = this.getFamous(); 28 | 29 | deck.setOptions(nextProps.options); 30 | } 31 | 32 | render() { 33 | return ( 34 |
    35 | {this.getFamousChildren()} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | defaults(Deck, FamousDeck); 42 | 43 | export default Deck; 44 | -------------------------------------------------------------------------------- /src/views/DrawerLayout.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousDrawerLayout from 'famous/views/DrawerLayout'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class DrawerLayout extends FamousComponent { 9 | famousCreate() { 10 | return new FamousDrawerLayout(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let drawerLayout = this.getFamous(); 15 | let node = parentNode.add(drawerLayout); 16 | let next = [ 17 | [this.refs.content, drawerLayout.content], 18 | [this.refs.drawer, drawerLayout.drawer] 19 | ]; 20 | return [node, next]; 21 | } 22 | 23 | famousUpdate(nextProps) { 24 | let drawerLayout = this.getFamous(); 25 | 26 | drawerLayout.setOptions(nextProps.options); 27 | } 28 | 29 | render() { 30 | let children = []; 31 | 32 | React.Children.forEach(this.props.children, (child) => { 33 | switch (child.type) { 34 | case DrawerLayout.Content: 35 | children.push(this.createFamousWrapper(child, {key: 'content', ref: 'content'})); 36 | break; 37 | case DrawerLayout.Drawer: 38 | children.push(this.createFamousWrapper(child, {key: 'drawer', ref: 'drawer'})); 39 | break; 40 | default: 41 | break; 42 | } 43 | }); 44 | 45 | return ( 46 |
    47 | {children} 48 |
    49 | ); 50 | } 51 | }; 52 | 53 | DrawerLayout.Content = class extends FamousComponent { 54 | famousCreate() { 55 | return new FamousRenderNode(); 56 | } 57 | 58 | famousCreateNode(parentNode) { 59 | let renderNode = this.getFamous(); 60 | let node = parentNode.add(renderNode); 61 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 62 | return [node, next]; 63 | } 64 | 65 | render() { 66 | return ( 67 |
    68 | {this.getFamousChildren()} 69 |
    70 | ); 71 | } 72 | }; 73 | 74 | DrawerLayout.Drawer = class extends FamousComponent { 75 | famousCreate() { 76 | return new FamousRenderNode(); 77 | } 78 | 79 | famousCreateNode(parentNode) { 80 | let renderNode = this.getFamous(); 81 | let node = parentNode.add(renderNode); 82 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 83 | return [node, next]; 84 | } 85 | 86 | render() { 87 | return ( 88 |
    89 | {this.getFamousChildren()} 90 |
    91 | ); 92 | } 93 | }; 94 | 95 | defaults(DrawerLayout, FamousDrawerLayout); 96 | 97 | export default DrawerLayout; 98 | -------------------------------------------------------------------------------- /src/views/EdgeSwapper.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousEdgeSwapper from 'famous/views/EdgeSwapper'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class EdgeSwapper extends FamousComponent { 9 | famousCreate() { 10 | return new FamousEdgeSwapper(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let edgeSwapper = this.getFamous(); 15 | let node = parentNode.add(edgeSwapper); 16 | let next = this.getFamousChildrenRef().map((child, idx) => [child, new FamousRenderNode()]); 17 | return [node, next]; 18 | } 19 | 20 | famousUpdate(nextProps) { 21 | let edgeSwapper = this.getFamous(); 22 | 23 | edgeSwapper.setOptions(nextProps.options); 24 | } 25 | 26 | render() { 27 | return ( 28 |
    29 | {this.getFamousChildren()} 30 |
    31 | ); 32 | } 33 | } 34 | 35 | defaults(EdgeSwapper, FamousEdgeSwapper); 36 | 37 | export default EdgeSwapper; 38 | -------------------------------------------------------------------------------- /src/views/FlexibleLayout.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousFlexibleLayout from 'famous/views/FlexibleLayout'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class FlexibleLayout extends FamousComponent { 9 | famousCreate() { 10 | return new FamousFlexibleLayout(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let flexibleLayout = this.getFamous(); 15 | let node = parentNode.add(flexibleLayout); 16 | let next = []; 17 | let sequence = this.getFamousChildrenRef().map((child, idx) => { 18 | let renderNode = new FamousRenderNode(); 19 | next.push([child, renderNode]); 20 | return renderNode; 21 | }); 22 | flexibleLayout.sequenceFrom(sequence); 23 | return [node, next]; 24 | } 25 | 26 | famousUpdate(nextProps) { 27 | let flexibleLayout = this.getFamous(); 28 | 29 | flexibleLayout.setOptions(nextProps.options); 30 | } 31 | 32 | render() { 33 | return ( 34 |
    35 | {this.getFamousChildren()} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | defaults(FlexibleLayout, FamousFlexibleLayout); 42 | 43 | export default FlexibleLayout; 44 | -------------------------------------------------------------------------------- /src/views/Flipper.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousFlipper from 'famous/views/Flipper'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class Flipper extends FamousComponent { 9 | famousCreate() { 10 | return new FamousFlipper(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let flipper = this.getFamous(); 15 | let backRenderNode = new FamousRenderNode(); 16 | let frontRenderNode = new FamousRenderNode(); 17 | let node = parentNode.add(flipper); 18 | let next = [ 19 | [this.refs.back, backRenderNode], 20 | [this.refs.front, frontRenderNode] 21 | ]; 22 | flipper.setBack(backRenderNode); 23 | flipper.setFront(frontRenderNode); 24 | return [node, next]; 25 | } 26 | 27 | famousUpdate(nextProps) { 28 | let flipper = this.getFamous(); 29 | 30 | flipper.setOptions(nextProps.options); 31 | } 32 | 33 | render() { 34 | let children = []; 35 | 36 | React.Children.forEach(this.props.children, (child) => { 37 | switch (child.type) { 38 | case Flipper.Back: 39 | children.push(this.createFamousWrapper(child, {key: 'back', ref: 'back'})); 40 | break; 41 | case Flipper.Front: 42 | children.push(this.createFamousWrapper(child, {key: 'front', ref: 'front'})); 43 | break; 44 | default: 45 | break; 46 | } 47 | }); 48 | 49 | return ( 50 |
    51 | {children} 52 |
    53 | ); 54 | } 55 | } 56 | 57 | Flipper.Back = class extends FamousComponent { 58 | famousCreate() { 59 | return new FamousRenderNode(); 60 | } 61 | 62 | famousCreateNode(parentNode) { 63 | let renderNode = this.getFamous(); 64 | let node = parentNode.add(renderNode); 65 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 66 | return [node, next]; 67 | } 68 | 69 | render() { 70 | return ( 71 |
    72 | {this.getFamousChildren()} 73 |
    74 | ); 75 | } 76 | }; 77 | 78 | Flipper.Front = class extends FamousComponent { 79 | famousCreate() { 80 | return new FamousRenderNode(); 81 | } 82 | 83 | famousCreateNode(parentNode) { 84 | let renderNode = this.getFamous(); 85 | let node = parentNode.add(renderNode); 86 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 87 | return [node, next]; 88 | } 89 | 90 | render() { 91 | return ( 92 |
    93 | {this.getFamousChildren()} 94 |
    95 | ); 96 | } 97 | } 98 | 99 | defaults(Flipper, FamousFlipper); 100 | 101 | export default Flipper; 102 | -------------------------------------------------------------------------------- /src/views/GridLayout.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousGridLayout from 'famous/views/GridLayout'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class GridLayout extends FamousComponent { 9 | famousCreate() { 10 | return new FamousGridLayout(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let gridLayout = this.getFamous(); 15 | let node = parentNode.add(gridLayout); 16 | let next = []; 17 | let sequence = this.getFamousChildrenRef().map((child, idx) => { 18 | let renderNode = new FamousRenderNode(); 19 | next.push([child, renderNode]); 20 | return renderNode; 21 | }); 22 | gridLayout.sequenceFrom(sequence); 23 | return [node, next]; 24 | } 25 | 26 | famousUpdate(nextProps) { 27 | let gridLayout = this.getFamous(); 28 | 29 | gridLayout.setOptions(nextProps.options); 30 | } 31 | 32 | render() { 33 | return ( 34 |
    35 | {this.getFamousChildren()} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | defaults(GridLayout, FamousGridLayout); 42 | 43 | export default GridLayout; 44 | -------------------------------------------------------------------------------- /src/views/HeaderFooterLayout.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousHeaderFooterLayout from 'famous/views/HeaderFooterLayout'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class HeaderFooterLayout extends FamousComponent { 9 | famousCreate() { 10 | return new FamousHeaderFooterLayout(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let headerFooterlayout = this.getFamous(); 15 | let node = parentNode.add(headerFooterlayout); 16 | let next = [ 17 | [this.refs.content, headerFooterlayout.content], 18 | [this.refs.footer, headerFooterlayout.footer], 19 | [this.refs.header, headerFooterlayout.header] 20 | ]; 21 | return [node, next]; 22 | } 23 | 24 | famousUpdate(nextProps) { 25 | let headerFooterlayout = this.getFamous(); 26 | 27 | headerFooterlayout.setOptions(nextProps.options); 28 | } 29 | 30 | render() { 31 | let children = []; 32 | 33 | React.Children.forEach(this.props.children, (child) => { 34 | switch (child.type) { 35 | case HeaderFooterLayout.Content: 36 | children.push(this.createFamousWrapper(child, {key: 'content', ref: 'content'})); 37 | break; 38 | case HeaderFooterLayout.Footer: 39 | children.push(this.createFamousWrapper(child, {key: 'footer', ref: 'footer'})); 40 | break; 41 | case HeaderFooterLayout.Header: 42 | children.push(this.createFamousWrapper(child, {key: 'header', ref: 'header'})); 43 | break; 44 | default: 45 | break; 46 | } 47 | }); 48 | 49 | return ( 50 |
    51 | {children} 52 |
    53 | ); 54 | } 55 | }; 56 | 57 | HeaderFooterLayout.Content = class extends FamousComponent { 58 | famousCreate() { 59 | return new FamousRenderNode(); 60 | } 61 | 62 | famousCreateNode(parentNode) { 63 | let renderNode = this.getFamous(); 64 | let node = parentNode.add(renderNode); 65 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 66 | return [node, next]; 67 | } 68 | 69 | render() { 70 | return ( 71 |
    72 | {this.getFamousChildren()} 73 |
    74 | ); 75 | } 76 | }; 77 | 78 | HeaderFooterLayout.Footer = class extends FamousComponent { 79 | famousCreate() { 80 | return new FamousRenderNode(); 81 | } 82 | 83 | famousCreateNode(parentNode) { 84 | let renderNode = this.getFamous(); 85 | let node = parentNode.add(renderNode); 86 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 87 | return [node, next]; 88 | } 89 | 90 | render() { 91 | return ( 92 |
    93 | {this.getFamousChildren()} 94 |
    95 | ); 96 | } 97 | }; 98 | 99 | HeaderFooterLayout.Header = class extends FamousComponent { 100 | famousCreate() { 101 | return new FamousRenderNode(); 102 | } 103 | 104 | famousCreateNode(parentNode) { 105 | let renderNode = this.getFamous(); 106 | let node = parentNode.add(renderNode); 107 | let next = this.getFamousChildrenRef().map((child, idx) => [child, node]); 108 | return [node, next]; 109 | } 110 | 111 | render() { 112 | return ( 113 |
    114 | {this.getFamousChildren()} 115 |
    116 | ); 117 | } 118 | } 119 | 120 | defaults(HeaderFooterLayout, FamousHeaderFooterLayout); 121 | 122 | export default HeaderFooterLayout; 123 | -------------------------------------------------------------------------------- /src/views/Lightbox.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousLightbox from 'famous/views/Lightbox'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class Lightbox extends FamousComponent { 9 | famousCreate() { 10 | return new FamousLightbox(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let lightbox = this.getFamous(); 15 | let node = parentNode.add(lightbox); 16 | let next = this.getFamousChildrenRef().map((child, idx) => [child, new FamousRenderNode()]); 17 | return [node, next]; 18 | } 19 | 20 | famousUpdate(nextProps) { 21 | let lightbox = this.getFamous(); 22 | 23 | lightbox.setOptions(nextProps.options); 24 | } 25 | 26 | render() { 27 | return ( 28 |
    29 | {this.getFamousChildren()} 30 |
    31 | ); 32 | } 33 | } 34 | 35 | defaults(Lightbox, FamousLightbox); 36 | 37 | export default Lightbox; 38 | -------------------------------------------------------------------------------- /src/views/RenderController.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousRenderController from 'famous/views/RenderController'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class RenderController extends FamousComponent { 9 | famousCreate() { 10 | return new FamousRenderController(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let renderController = this.getFamous(); 15 | let node = parentNode.add(renderController); 16 | let next = this.getFamousChildrenRef().map((child, idx) => [child, new FamousRenderNode()]); 17 | return [node, next]; 18 | } 19 | 20 | famousUpdate(nextProps) { 21 | let renderController = this.getFamous(); 22 | 23 | renderController.setOptions(nextProps.options); 24 | } 25 | 26 | render() { 27 | return ( 28 |
    29 | {this.getFamousChildren()} 30 |
    31 | ); 32 | } 33 | } 34 | 35 | defaults(RenderController, FamousRenderController); 36 | 37 | export default RenderController; 38 | -------------------------------------------------------------------------------- /src/views/ScrollContainer.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousScrollContainer from 'famous/views/ScrollContainer'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class ScrollContainer extends FamousComponent { 9 | famousCreate() { 10 | return new FamousScrollContainer(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let scrollContainer = this.getFamous(); 15 | let node = parentNode.add(scrollContainer); 16 | let next = []; 17 | let sequence = this.getFamousChildrenRef().map((child, idx) => { 18 | let renderNode = new FamousRenderNode(); 19 | next.push([child, renderNode]); 20 | return renderNode; 21 | }); 22 | scrollContainer.sequenceFrom(sequence); 23 | return [node, next]; 24 | } 25 | 26 | famousUpdate(nextProps) { 27 | let scrollContainer = this.getFamous(); 28 | 29 | scrollContainer.setOptions(nextProps.options); 30 | } 31 | 32 | render() { 33 | return ( 34 |
    35 | {this.getFamousChildren()} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | defaults(ScrollContainer, FamousScrollContainer); 42 | 43 | export default ScrollContainer; 44 | -------------------------------------------------------------------------------- /src/views/Scroller.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousScroller from 'famous/views/Scroller'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class Scroller extends FamousComponent { 9 | famousCreate() { 10 | return new FamousScroller(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let scroller = this.getFamous(); 15 | let node = parentNode.add(scroller); 16 | let next = []; 17 | let sequence = this.getFamousChildrenRef().map((child, idx) => { 18 | let renderNode = new FamousRenderNode(); 19 | next.push([child, renderNode]); 20 | return renderNode; 21 | }); 22 | scroller.sequenceFrom(sequence); 23 | return [node, next]; 24 | } 25 | 26 | famousUpdate(nextProps) { 27 | let scroller = this.getFamous(); 28 | 29 | scroller.setOptions(nextProps.options); 30 | } 31 | 32 | render() { 33 | return ( 34 |
    35 | {this.getFamousChildren()} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | defaults(Scroller, FamousScroller); 42 | 43 | export default Scroller; 44 | -------------------------------------------------------------------------------- /src/views/Scrollview.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousScrollview from 'famous/views/Scrollview'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class Scrollview extends FamousComponent { 9 | famousCreate() { 10 | return new FamousScrollview(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let scrollview = this.getFamous(); 15 | let node = parentNode.add(scrollview); 16 | let next = []; 17 | let sequence = this.getFamousChildrenRef().map((child, idx) => { 18 | let renderNode = new FamousRenderNode(); 19 | next.push([child, renderNode]); 20 | return renderNode; 21 | }); 22 | scrollview.sequenceFrom(sequence); 23 | return [node, next]; 24 | } 25 | 26 | famousUpdate(nextProps) { 27 | let scrollview = this.getFamous(); 28 | 29 | scrollview.setOptions(nextProps.options); 30 | } 31 | 32 | render() { 33 | return ( 34 |
    35 | {this.getFamousChildren()} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | defaults(Scrollview, FamousScrollview); 42 | 43 | export default Scrollview; 44 | -------------------------------------------------------------------------------- /src/views/SequentialLayout.jsx: -------------------------------------------------------------------------------- 1 | import FamousRenderNode from 'famous/core/RenderNode'; 2 | import FamousSequentialLayout from 'famous/views/SequentialLayout'; 3 | import defaults from 'lodash/object/defaults'; 4 | import React from 'react'; 5 | 6 | import FamousComponent from '../lib/FamousComponent'; 7 | 8 | class SequentialLayout extends FamousComponent { 9 | famousCreate() { 10 | return new FamousSequentialLayout(this.props.options); 11 | } 12 | 13 | famousCreateNode(parentNode) { 14 | let sequentialLayout = this.getFamous(); 15 | let node = parentNode.add(sequentialLayout); 16 | let next = []; 17 | let sequence = this.getFamousChildrenRef().map((child, idx) => { 18 | let renderNode = new FamousRenderNode(); 19 | next.push([child, renderNode]); 20 | return renderNode; 21 | }); 22 | sequentialLayout.sequenceFrom(sequence); 23 | return [node, next]; 24 | } 25 | 26 | famousUpdate(nextProps) { 27 | let sequentialLayout = this.getFamous(); 28 | 29 | sequentialLayout.setOptions(nextProps.options); 30 | } 31 | 32 | render() { 33 | return ( 34 |
    35 | {this.getFamousChildren()} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | defaults(SequentialLayout, FamousSequentialLayout); 42 | 43 | export default SequentialLayout; 44 | -------------------------------------------------------------------------------- /src/views/SizeAwareView.jsx: -------------------------------------------------------------------------------- 1 | import FamousSizeAwareView from 'famous/views/SizeAwareView'; 2 | import defaults from 'lodash/object/defaults'; 3 | import React from 'react'; 4 | 5 | import FamousComponent from '../lib/FamousComponent'; 6 | 7 | class SizeAwareView extends FamousComponent { 8 | famousCreate() { 9 | return new FamousSizeAwareView(this.props.options); 10 | } 11 | 12 | famousCreateNode(parentNode) { 13 | let sizeAwareView = this.getFamous(); 14 | parentNode.add(sizeAwareView); 15 | let next = this.getFamousChildrenRef().map((child, idx) => [child, sizeAwareView]); 16 | return [sizeAwareView, next]; 17 | } 18 | 19 | famousUpdate(nextProps) { 20 | let sizeAwareView = this.getFamous(); 21 | 22 | sizeAwareView.setOptions(nextProps.options); 23 | } 24 | 25 | render() { 26 | return ( 27 |
    28 | {this.getFamousChildren()} 29 |
    30 | ); 31 | } 32 | } 33 | 34 | defaults(SizeAwareView, FamousSizeAwareView); 35 | 36 | export default SizeAwareView; 37 | -------------------------------------------------------------------------------- /tools/publish/amd/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pilwon/react-famous/1a37520899460f8d6ebbe9fb5f6048b92a6dc970/tools/publish/amd/README.md -------------------------------------------------------------------------------- /tools/publish/amd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /tools/publish/cjs/README.md: -------------------------------------------------------------------------------- 1 | # react-famous 2 | 3 | Add [Famo.us](http://famo.us) interactions and animations to any [React](http://facebook.github.io/react/) application and build **Famo.us** applications with **React**. 4 | 5 | Using `react-famous`, you can: 6 | 7 | * Create **Famo.us** apps using familiar **React** component specs and lifecycle. 8 | * Bring rich **Famo.us** animations to new or existing **React** apps. 9 | * Easily integrate **Famo.us** and **React** apps. 10 | 11 | Please visit [the project page](https://github.com/pilwon/react-famous) for more information. 12 | -------------------------------------------------------------------------------- /tools/publish/cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-famous", 3 | "description": "React bridge to Famo.us", 4 | "version": "0.1.7", 5 | "homepage": "https://github.com/pilwon/react-famous", 6 | "keywords": [ 7 | "react", 8 | "react-component", 9 | "famo.us", 10 | "famous" 11 | ], 12 | "author": "Pilwon Huh ", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "pilwon/react-famous" 17 | }, 18 | "bugs": { 19 | "url": "https://github.com/pilwon/react-famous/issues" 20 | }, 21 | "peerDependencies": { 22 | "famous": ">=0.3.5", 23 | "react": ">=0.13.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tools/publish/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-famous: React bridge to Famo.us 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | --------------------------------------------------------------------------------