├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── LICENSE.txt ├── README.md ├── bin └── famous-framework.js ├── dev ├── build-pipeline │ ├── build-bundle.js │ ├── build-dependencies.js │ ├── build-module.js │ ├── config │ │ └── config.js │ ├── expand-imports.js │ ├── expand-syntax.js │ ├── extract-artifacts.js │ ├── find-dependencies.js │ ├── helpers │ │ ├── esprima.js │ │ └── helpers.js │ ├── index.js │ ├── link-facets.js │ ├── load-dependencies.js │ ├── preprocess-assets.js │ ├── shims │ │ └── jsdom.js │ └── templates │ │ └── index.html ├── local-assistant │ └── local-assistant.js └── local-workspace │ ├── assets │ ├── Lato1.woff2 │ ├── Lato2.woff2 │ ├── apple-touch-icon.png │ ├── fonts.css │ ├── main.css │ ├── query-string.js │ ├── reset.min.css │ ├── search-icon.svg │ └── search.js │ ├── favicon.ico │ └── index.html ├── lib ├── behaviors │ ├── behavior-router.js │ └── behaviors.js ├── component │ └── component.js ├── control-flow │ ├── control-flow-data-manager.js │ ├── control-flow-utils.js │ └── control-flow.js ├── core-components │ ├── famous-demos │ │ ├── animation-timeline-queue │ │ │ ├── animation-timeline-queue.html │ │ │ └── animation-timeline-queue.js │ │ ├── animation-timeline │ │ │ ├── animation-timeline.html │ │ │ └── animation-timeline.js │ │ ├── attach-webgl │ │ │ ├── attach-webgl.js │ │ │ └── webgl-example.js │ │ ├── best │ │ │ ├── arrow │ │ │ │ └── arrow.js │ │ │ ├── demo │ │ │ │ └── demo.js │ │ │ └── floating-square │ │ │ │ └── floating-square.js │ │ ├── clickable-square-with-logo │ │ │ ├── assets │ │ │ │ └── famous_logo.svg │ │ │ └── clickable-square-with-logo.js │ │ ├── clickable-square │ │ │ └── clickable-square.js │ │ ├── config-panel │ │ │ └── config-panel.js │ │ ├── dynamic-list │ │ │ ├── dynamic-list.html │ │ │ └── dynamic-list.js │ │ ├── layouts │ │ │ ├── flexible │ │ │ │ ├── header-footer │ │ │ │ │ └── header-footer.js │ │ │ │ ├── nested │ │ │ │ │ └── nested.js │ │ │ │ ├── simple │ │ │ │ │ └── simple.js │ │ │ │ └── transition │ │ │ │ │ └── transition.js │ │ │ └── sequential │ │ │ │ └── simple │ │ │ │ └── simple.js │ │ ├── lifecycle │ │ │ ├── lifecycle.html │ │ │ └── lifecycle.js │ │ ├── repeat-color-wheel │ │ │ └── repeat-color-wheel.js │ │ ├── scroll-view-example │ │ │ └── scroll-view-example.js │ │ ├── simplified-todos │ │ │ ├── simplified-todos.js │ │ │ └── todos.css │ │ ├── styling-inner-content │ │ │ └── styling-inner-content.js │ │ ├── twitter │ │ │ ├── app │ │ │ │ └── app.js │ │ │ ├── logo │ │ │ │ └── logo.js │ │ │ ├── navbar-button │ │ │ │ └── navbar-button.js │ │ │ ├── navbar │ │ │ │ └── navbar.js │ │ │ ├── page-tweets │ │ │ │ └── page-tweets.js │ │ │ ├── page │ │ │ │ └── page.js │ │ │ ├── tabbar-button │ │ │ │ └── tabbar-button.js │ │ │ ├── tabbar │ │ │ │ └── tabbar.js │ │ │ └── tweet │ │ │ │ ├── tweet.css │ │ │ │ └── tweet.js │ │ └── widget-dashboard │ │ │ ├── calendar │ │ │ ├── calendar.css │ │ │ ├── calendar.html │ │ │ └── calendar.js │ │ │ ├── clock │ │ │ ├── clock.html │ │ │ └── clock.js │ │ │ ├── dashboard │ │ │ ├── background.jpg │ │ │ ├── background2.jpg │ │ │ ├── calendar-icon.jpg │ │ │ ├── clock-icon.jpg │ │ │ ├── dashboard.css │ │ │ ├── dashboard.html │ │ │ ├── dashboard.js │ │ │ ├── photos-icon.jpg │ │ │ ├── photos-icon.png │ │ │ ├── stocks-icon.jpg │ │ │ └── weather-icon.jpg │ │ │ ├── photos │ │ │ ├── photos.js │ │ │ └── stock │ │ │ │ ├── kitten-1.jpg │ │ │ │ ├── kitten-2.jpg │ │ │ │ ├── kitten-3.jpg │ │ │ │ ├── kitten-4.jpg │ │ │ │ └── kitten-5.jpg │ │ │ ├── stocks │ │ │ ├── stocks.css │ │ │ ├── stocks.html │ │ │ └── stocks.js │ │ │ └── weather │ │ │ ├── animate.css │ │ │ ├── background.jpg │ │ │ ├── clear_day.svg │ │ │ ├── clear_night.svg │ │ │ ├── cloudy.svg │ │ │ ├── partly_cloudy_day.svg │ │ │ ├── partly_cloudy_night.svg │ │ │ ├── rainy.svg │ │ │ ├── snowy.svg │ │ │ ├── thunderstorm.svg │ │ │ ├── weather.html │ │ │ └── weather.js │ ├── famous-tests │ │ ├── array-tweening │ │ │ └── array-tweening.js │ │ ├── assets-large │ │ │ ├── assets-large.js │ │ │ └── galaxy.jpg │ │ ├── bad-dependencies │ │ │ └── bad-dependencies.js │ │ ├── camera │ │ │ ├── camera.html │ │ │ ├── camera.js │ │ │ └── custom │ │ │ │ └── custom.js │ │ ├── component-composition │ │ │ ├── component-composition.html │ │ │ └── component-composition.js │ │ ├── component-targeting │ │ │ ├── child │ │ │ │ └── child.js │ │ │ └── parent │ │ │ │ └── parent.js │ │ ├── control-flow │ │ │ ├── basic-if │ │ │ │ ├── basic-if.html │ │ │ │ └── basic-if.js │ │ │ ├── repeat │ │ │ │ ├── repeat.html │ │ │ │ └── repeat.js │ │ │ └── static-repeat │ │ │ │ └── static-repeat.js │ │ ├── custom-famous-node │ │ │ ├── custom-famous-node.js │ │ │ └── register-node-constructor.js │ │ ├── custom-toolchain │ │ │ ├── browserify-me.js │ │ │ ├── custom-toolchain.js │ │ │ └── package.json │ │ ├── dispatcher │ │ │ ├── broadcasting │ │ │ │ ├── broadcasting.js │ │ │ │ └── child │ │ │ │ │ └── child.js │ │ │ ├── emit │ │ │ │ ├── child │ │ │ │ │ └── child.js │ │ │ │ └── emit.js │ │ │ └── trigger │ │ │ │ └── trigger.js │ │ ├── does-behavior-void │ │ │ ├── child │ │ │ │ └── child.js │ │ │ └── parent │ │ │ │ └── parent.js │ │ ├── drag-and-drop │ │ │ └── drag-and-drop.js │ │ ├── engine-integration │ │ │ ├── engine-integration.js │ │ │ ├── foo.css │ │ │ └── my-famous.js │ │ ├── fouc │ │ │ └── fouc.js │ │ ├── html-element-events │ │ │ └── html-element-events.js │ │ ├── include-css │ │ │ ├── a.css │ │ │ ├── b.css │ │ │ ├── c.css │ │ │ ├── d.css │ │ │ ├── e.css │ │ │ └── include-css.js │ │ ├── input-field-data │ │ │ └── input-field-data.js │ │ ├── misspelled-facets │ │ │ └── misspelled-facets.js │ │ ├── mount-point │ │ │ ├── mount-point.html │ │ │ └── mount-point.js │ │ ├── observe-nested-state │ │ │ └── observe-nested-state.js │ │ ├── opacity │ │ │ ├── child │ │ │ │ ├── bottle-label.jpg │ │ │ │ └── child.js │ │ │ └── opacity.js │ │ ├── pass-through │ │ │ ├── child-component │ │ │ │ ├── child-component.html │ │ │ │ ├── child-component.jade │ │ │ │ └── child-component.js │ │ │ ├── pass-through.html │ │ │ └── pass-through.js │ │ ├── physics │ │ │ └── basic │ │ │ │ ├── add-and-remove │ │ │ │ └── add-and-remove.js │ │ │ │ ├── gravity │ │ │ │ └── gravity.js │ │ │ │ ├── particle │ │ │ │ └── particle.js │ │ │ │ └── spring │ │ │ │ └── spring.js │ │ ├── router-test │ │ │ ├── router-test.html │ │ │ └── router-test.js │ │ ├── scope │ │ │ ├── child │ │ │ │ └── child.js │ │ │ └── scope.js │ │ ├── setter-vs-identity │ │ │ ├── child │ │ │ │ └── child.js │ │ │ └── parent │ │ │ │ └── parent.js │ │ ├── size-change-event │ │ │ ├── size-change-event.html │ │ │ └── size-change-event.js │ │ ├── state-interruption │ │ │ └── state-interruption.js │ │ ├── state-manager-test │ │ │ └── state-manager-test.js │ │ ├── static-assets │ │ │ ├── assets │ │ │ │ ├── excite.png │ │ │ │ └── excite2.png │ │ │ ├── more-assets │ │ │ │ ├── assets │ │ │ │ │ └── excite3.png │ │ │ │ └── more-assets.js │ │ │ └── static-assets.js │ │ ├── timeline-example │ │ │ └── timeline-example.js │ │ ├── timeline │ │ │ └── top-level-function │ │ │ │ └── top-level-function.js │ │ ├── webgl │ │ │ ├── basic │ │ │ │ └── geometry │ │ │ │ │ └── geometry.js │ │ │ ├── custom-shader │ │ │ │ ├── fragment │ │ │ │ │ └── fragment.js │ │ │ │ └── vertex │ │ │ │ │ └── vertex.js │ │ │ └── glsl-state │ │ │ │ └── uniform │ │ │ │ └── uniform.js │ │ └── weird-files │ │ │ ├── .foo │ │ │ ├── .something~~ │ │ │ └── .asfdasdfasfdaf │ │ │ ├── .xyz.mucho │ │ │ ├── bar │ │ │ ├── main.jsx │ │ │ └── weird-files.js │ └── famous │ │ ├── adapter │ │ ├── flickr │ │ │ └── flickr.js │ │ ├── google-finance │ │ │ └── google-finance.js │ │ └── open-weather-map │ │ │ └── open-weather-map.js │ │ ├── core │ │ └── node │ │ │ └── node.js │ │ ├── events │ │ └── events.js │ │ ├── layouts │ │ ├── flexible │ │ │ ├── _constructor.js │ │ │ └── flexible.js │ │ ├── header-footer │ │ │ ├── header-footer.html │ │ │ └── header-footer.js │ │ ├── scroll-view │ │ │ └── scroll-view.js │ │ └── sequential │ │ │ ├── _constructor.js │ │ │ └── sequential.js │ │ ├── service │ │ ├── http │ │ │ └── http.js │ │ ├── location │ │ │ └── location.js │ │ └── timer │ │ │ └── timer.js │ │ └── ui │ │ ├── config-panel │ │ ├── assets │ │ │ └── plus.svg │ │ └── config-panel.js │ │ └── textbox │ │ └── textbox.js ├── data-store │ └── data-store.js ├── deployer │ └── deployer.js ├── events │ ├── dispatcher.js │ ├── events.js │ └── injector.js ├── famous-connector │ └── famous-connector.js ├── helpers │ ├── helpers.js │ └── piecewise.js ├── index.js ├── logger │ └── logger.js ├── messenger │ └── messenger.js ├── polyfills │ └── custom-event.js ├── state-manager │ ├── operator.js │ └── state-manager.js ├── states │ └── states.js ├── timelines │ └── timelines.js ├── tree │ └── tree.js ├── utilities │ ├── array.js │ ├── converter.js │ ├── event-handler.js │ ├── function-parser.js │ ├── http.js │ ├── object.js │ ├── uid.js │ └── utilities.js └── virtual-dom │ └── virtual-dom.js ├── package.json └── test ├── build-pipeline └── index.spec.js ├── runtime-tests ├── control-flow │ ├── control-flow-data-manager.spec.js │ ├── control-flow-repeat.spec.js │ ├── control-flow-utils.spec.js │ └── control-flow.spec.js ├── events │ └── dispatcher.spec.js ├── helpers │ └── virtual-dom-stub.js ├── main │ └── index.spec.js └── virtual-dom │ └── virtual-dom.spec.js ├── state-manager-tests ├── fixtures.js └── index.spec.js └── utilities-tests ├── converter.spec.js └── function-parser.spec.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig: http://editorconfig.org 2 | # Global EditorConfig 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 4 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log 4 | *.bundle.js 5 | **/core-components/* 6 | **/test/* 7 | **/fixtures/* 8 | **/*.bundle.js 9 | **/build/* 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "arrowFunctions": true, 4 | "binaryLiterals": true, 5 | "blockBindings": true, 6 | "classes": true, 7 | "defaultParams": true, 8 | "destructuring": true, 9 | "forOf": true, 10 | "generators": true, 11 | "modules": true, 12 | "objectLiteralComputedProperties": true, 13 | "objectLiteralDuplicateProperties": true, 14 | "objectLiteralShorthandMethods": true, 15 | "objectLiteralShorthandProperties": true, 16 | "octalLiterals": true, 17 | "regexUFlag": true, 18 | "regexYFlag": true, 19 | "superInFunctions": true, 20 | "templateStrings": true, 21 | "unicodeCodePointEscapes": true, 22 | "globalReturn": true, 23 | "jsx": false 24 | }, 25 | "env": { 26 | "browser": true, 27 | "es6": true, 28 | "node": true 29 | }, 30 | "globals": { 31 | "FF": true, 32 | "FamousFramework": true, 33 | "QUERY": true 34 | }, 35 | "parser": "babel-eslint", 36 | "rules": { 37 | // Possible Errors 38 | "comma-dangle": 1, 39 | "valid-jsdoc": 0, //Moved to a separate script check-jsdoc 40 | // Better Practices 41 | "block-scoped-var": 0, 42 | "curly": [0, "multi"], 43 | "dot-location": [0, "object"], //Too much noise for now, might consider to enable it as a warning later 44 | "eqeqeq": [2, "allow-null"], 45 | "no-loop-func": 0, 46 | "no-multi-spaces": 0, 47 | "no-self-compare": 1, 48 | // Strict Mode 49 | "strict": 1, 50 | // Variables 51 | "no-shadow": 0, //Too much noise from tests, might consider to enable it as a warning later 52 | "no-undefined": 0, 53 | "no-unused-vars": [2, {"vars": "all", "args": "none"}], 54 | "no-use-before-define": [0, "nofunc"], 55 | "no-new": 0, 56 | // Stylistic Issues 57 | "brace-style": [1, "stroustrup"], 58 | "camelcase": 0, //Too much noise from tests, might consider to enable it as a warning later 59 | "comma-spacing": [0, {"before": false, "after": true}], //Noise 60 | "consistent-this": [0, "_this"], 61 | "eol-last": 1, 62 | "key-spacing": 0, 63 | "new-cap": 0, 64 | "no-trailing-spaces": 0, 65 | "no-mixed-spaces-and-tabs": 0, //Too much noise for now, might consider to enable it as a warning later 66 | "no-underscore-dangle": 0, 67 | "quotes": [0, "single"], //Too much noise for now, might consider to enable it as a warning later 68 | "semi-spacing": 0, //Too much noise for now, might consider to enable it as a warning later 69 | "space-infix-ops": 0, 70 | "space-unary-ops": 0 //Too much noise for now, might consider to enable it as a warning later 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | *.log 4 | *.bundle.js 5 | dev/local-workspace/build/* 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Famous Industries, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/famous-framework.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | 5 | var Program = require('commander'); 6 | 7 | var LocalAssistant = require('./../dev/local-assistant/local-assistant'); 8 | 9 | Program.command('copy-core-components') 10 | .option('-d, --destinationFolder [destinationFolder]') 11 | .action(function(info) { 12 | var la = new LocalAssistant(); 13 | la.copyCoreComponents(info); 14 | }); 15 | 16 | Program.command('watch-runtime') 17 | .option('-i, --inputFile [inputFile]') 18 | .option('-o, --outputFile [outputFile]') 19 | .action(function(info) { 20 | var la = new LocalAssistant(); 21 | la.watchRuntime(info); 22 | }); 23 | 24 | Program.command('local-only-bootstrap') 25 | .option('-s, --sourceFolder [sourceFolder]') 26 | .option('-d, --destinationFolder [destinationFolder]') 27 | .option('-e, --entrypointModuleName [entrypointModuleName]') 28 | .option('-f, --servedFolder [servedFolder]') 29 | .option('-r, --rebuildEverythingOnChange [rebuildEverythingOnChange]') 30 | .option('-w, --watchAfterBuild [watchAfterBuild]') 31 | .option('-p, --port [port]') 32 | .action(function(info) { 33 | var la = new LocalAssistant(); 34 | la.localOnlyBootstrap(info); 35 | }); 36 | 37 | Program.parse(process.argv); 38 | -------------------------------------------------------------------------------- /dev/build-pipeline/build-dependencies.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Async = require('async'); 4 | var each = require('lodash.foreach'); 5 | 6 | function buildDependency(name, version, files, originalData, cb) { 7 | return Async.waterfall([ 8 | function(cb) { 9 | // Since we need to build the component in order to fully understand 10 | // what its own dependencies are, we end up with a recursive build 11 | // process. Each build has a 'data' object, but we also don't want 12 | // to waste effort by loading dependencies that we've already gotten, 13 | // so we pass along the original dependencies loaded so this can be 14 | // checked against at each pass. 15 | cb(null, name, files, { 16 | dependenciesLoaded: originalData.dependenciesLoaded 17 | }); 18 | }, 19 | 20 | require('./preprocess-assets'), 21 | require('./extract-artifacts'), 22 | require('./link-facets'), 23 | require('./expand-imports'), 24 | require('./find-dependencies'), 25 | require('./load-dependencies'), 26 | require('./build-dependencies'), 27 | require('./expand-syntax') 28 | ], function(recursiveBuildErr, nameOut, filesOut, data) { 29 | if (recursiveBuildErr) { 30 | return cb(recursiveBuildErr); 31 | } 32 | 33 | return cb(null, [nameOut, version, filesOut, data]); 34 | }); 35 | } 36 | 37 | function buildDependencyTuple(tuple, cb) { 38 | return buildDependency(tuple[0], tuple[1], tuple[2], tuple[3], cb); 39 | } 40 | 41 | function buildDependencies(name, files, data, finish) { 42 | each(data.dependencyTuples, function(tuple) { 43 | // Pass the original 'data' object through in case we 44 | // need to add anything to the recursive build process 45 | tuple.push(data); 46 | }); 47 | 48 | Async.map(data.dependencyTuples, buildDependencyTuple, function(buildDepErr, builtDependencyTuples) { 49 | if (buildDepErr) { 50 | return finish(buildDepErr); 51 | } 52 | 53 | data.builtDependencyTuples = builtDependencyTuples; 54 | 55 | return finish(null, name, files, data); 56 | }); 57 | } 58 | 59 | module.exports = buildDependencies; 60 | -------------------------------------------------------------------------------- /dev/build-pipeline/build-module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Async = require('async'); 4 | 5 | var Config = require('./config/config'); 6 | 7 | function buildModule(name, files, options, finish) { 8 | Config.assign(options); 9 | 10 | return Async.waterfall([ 11 | function(cb) { 12 | cb(null, name, files, {}); 13 | }, 14 | 15 | require('./preprocess-assets'), 16 | require('./extract-artifacts'), 17 | require('./link-facets'), 18 | require('./expand-imports'), 19 | require('./find-dependencies'), 20 | require('./load-dependencies'), 21 | require('./build-dependencies'), 22 | require('./expand-syntax'), 23 | require('./build-bundle') 24 | ], function(pipelineErr, nameOut, filesOut, dataOut) { 25 | if (pipelineErr) { 26 | return finish(pipelineErr); 27 | } 28 | 29 | console.log('famous framework: Built ' + nameOut); 30 | return finish(null, nameOut, filesOut, dataOut); 31 | }); 32 | } 33 | 34 | module.exports = buildModule; 35 | -------------------------------------------------------------------------------- /dev/build-pipeline/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | buildModule: require('./build-module') 5 | }; 6 | -------------------------------------------------------------------------------- /dev/build-pipeline/link-facets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var find = require('lodash.find'); 4 | 5 | var EsprimaHelpers = require('./helpers/esprima'); 6 | var Config = require('./config/config'); 7 | 8 | /** 9 | * E.g., this will convert: 10 | * FamousFramework.scene(..., { 11 | * tree: 'tree.html' 12 | * }) 13 | * To: 14 | * FamousFramework.scene(..., { 15 | * tree: '' 16 | * }) 17 | * By inlining the content of the referred-to file 18 | */ 19 | function linkFacets(name, files, data, finish) { 20 | for (var moduleName in data.moduleDefinitionASTs) { 21 | EsprimaHelpers.eachStringProperty(data.moduleDefinitionASTs[moduleName], function(facetName, _1, facetValue, _2, facetProp) { 22 | // Skip if the facet value is just plain empty 23 | if (facetValue && facetValue.length > 2) { 24 | var facetFile = find(files, { path: facetValue }); 25 | 26 | if (facetFile) { 27 | var facetContent = facetFile.content; 28 | 29 | // Unlike other properties in the definition, the tree object is 30 | // an HTML string, and so it should be written as a string literal, 31 | // not parsed as JavaScript 32 | if (facetName === Config.get('treeFacetKeyName')) { 33 | facetProp.value = EsprimaHelpers.buildStringLiteralAST(facetContent); 34 | } 35 | else { 36 | facetProp.value = EsprimaHelpers.parse(facetContent).body[0]; 37 | } 38 | } 39 | } 40 | }); 41 | } 42 | 43 | return finish(null, name, files, data); 44 | } 45 | 46 | module.exports = linkFacets; 47 | -------------------------------------------------------------------------------- /dev/build-pipeline/shims/jsdom.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | jsdom: function(domString) { 3 | var domParser = new DOMParser(); 4 | var doc = domParser.parseFromString(domString, 'text/html'); 5 | return { 6 | defaultView: { 7 | 'document': doc 8 | } 9 | }; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /dev/build-pipeline/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{componentName}} | Famous Framework 7 | 8 | 27 | 28 | 29 | 30 | 31 | 39 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /dev/local-workspace/assets/Lato1.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/dev/local-workspace/assets/Lato1.woff2 -------------------------------------------------------------------------------- /dev/local-workspace/assets/Lato2.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/dev/local-workspace/assets/Lato2.woff2 -------------------------------------------------------------------------------- /dev/local-workspace/assets/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/dev/local-workspace/assets/apple-touch-icon.png -------------------------------------------------------------------------------- /dev/local-workspace/assets/fonts.css: -------------------------------------------------------------------------------- 1 | /* latin-ext */ 2 | @font-face { 3 | font-family: 'Lato'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Lato Regular'), local('Lato-Regular'), url(Lato1.woff2) format('woff2'); 7 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 8 | } 9 | 10 | /* latin */ 11 | @font-face { 12 | font-family: 'Lato'; 13 | font-style: normal; 14 | font-weight: 400; 15 | src: local('Lato Regular'), local('Lato-Regular'), url(Lato2.woff2) format('woff2'); 16 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; 17 | } 18 | -------------------------------------------------------------------------------- /dev/local-workspace/assets/query-string.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function() { 4 | var SEARCH = window.location.search; 5 | var QUERY = (function(a) { 6 | if (a === '') { 7 | return {}; 8 | } 9 | if (a[0] === '') { 10 | a.shift(); 11 | } 12 | var b = {}; 13 | for (var i = 0; i < a.length; ++i) { 14 | var p = a[i].split('=', 2); 15 | if (p.length === 1) { 16 | b[p[0]] = ''; 17 | } 18 | else { 19 | var s = p[1].replace(/\+/g, ' '); 20 | var sd = decodeURIComponent(s); 21 | if (sd === 'false') { 22 | sd = false; 23 | } 24 | else if (sd === 'true') { 25 | sd = true; 26 | } 27 | b[p[0]] = sd; 28 | } 29 | } 30 | return b; 31 | })(SEARCH.substr(1).split('&')); 32 | window.QUERY = QUERY; 33 | }()); 34 | -------------------------------------------------------------------------------- /dev/local-workspace/assets/reset.min.css: -------------------------------------------------------------------------------- 1 | /** Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) * http://cssreset.com */html{box-sizing:border-box;}*,*:before,*:after{box-sizing:inherit;}a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{border:0;font:inherit;margin:0;padding:0;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}html,body{width:100%;height:100%;}body{line-height:1-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}table{border-collapse:collapse;border-spacing:0} 2 | -------------------------------------------------------------------------------- /dev/local-workspace/assets/search-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | Layer 1 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /dev/local-workspace/assets/search.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function() { 4 | var iframe = document.getElementById('iframe'); 5 | var stage = document.getElementById('famous-framework-stage'); 6 | 7 | var SAFE_NAMESPACE_DELIMITER = '~'; 8 | var COMPONENT_DELIMITER = ':'; 9 | var DEFAULT_MODULE = 'famous-demos:clickable-square'; 10 | 11 | function updateCurrentModule(name, pushState) { 12 | var delimitedSafe = name.split(COMPONENT_DELIMITER).join(SAFE_NAMESPACE_DELIMITER); 13 | iframe.setAttribute('src', 'build/' + delimitedSafe + '/index.html'); 14 | } 15 | 16 | var query = QUERY.ff; 17 | if (query) { 18 | query = query.split('/')[0]; 19 | if (query.split(':').length < 2) { 20 | query = 'famous-demos:' + query; 21 | } 22 | updateCurrentModule(query, false); 23 | } 24 | else { 25 | updateCurrentModule(DEFAULT_MODULE, false); 26 | } 27 | }()); 28 | -------------------------------------------------------------------------------- /dev/local-workspace/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/dev/local-workspace/favicon.ico -------------------------------------------------------------------------------- /dev/local-workspace/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Famous Framework (workspace) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/behaviors/behavior-router.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Behaviors = require('./behaviors'); 4 | var VirtualDOM = require('./../virtual-dom/virtual-dom'); 5 | 6 | var CAMERA_KEY = '$camera'; 7 | var COMPONENT_DELIM = ':'; 8 | var IF_KEY = '$if'; 9 | var INVERTED_BEHAVIOR_KEYS = ['$index', '$repeatPayload']; 10 | var REPEAT_KEY = '$repeat'; 11 | var SELF_KEY = '$self'; 12 | var YIELD_KEY = '$yield'; 13 | 14 | var CONTROL_FLOW_KEYS = [IF_KEY, REPEAT_KEY, YIELD_KEY]; 15 | 16 | function isCameraSelector(selector) { 17 | return selector === CAMERA_KEY; 18 | } 19 | 20 | function isSelfSelector(selector) { 21 | return selector === SELF_KEY; 22 | } 23 | 24 | function isControlFlowBehavior(name) { 25 | return CONTROL_FLOW_KEYS.indexOf(name) >= 0; 26 | } 27 | 28 | function hasInvertedBehaviorParams(params) { 29 | var result = false; 30 | for (var i = 0; i < params.length; i++) { 31 | if (INVERTED_BEHAVIOR_KEYS.indexOf(params[i]) >= 0) { 32 | result = true; 33 | break; 34 | } 35 | } 36 | 37 | return result; 38 | } 39 | 40 | function getTargets(component, selector) { 41 | var expandedBlueprint = component.tree.getExpandedBlueprint(); 42 | if (expandedBlueprint) { 43 | return VirtualDOM.query(expandedBlueprint, selector); 44 | } 45 | else { 46 | return []; 47 | } 48 | } 49 | 50 | function route(behavior, component) { 51 | var name = behavior.name; 52 | 53 | if (isControlFlowBehavior(name)) { 54 | if (!component.blockControlFlow) { 55 | if (behavior.name === REPEAT_KEY) { 56 | component.processDynamicRepeat(behavior); 57 | } 58 | else if (behavior.name === IF_KEY) { 59 | component.processDynamicIf(behavior); 60 | } 61 | } 62 | } 63 | else { 64 | if (hasInvertedBehaviorParams(behavior.params)) { 65 | if (isSelfSelector(behavior.selector) || behavior.name.indexOf(COMPONENT_DELIM) >= 0) { 66 | throw new Error('Inverted behaviors (i.e., ones with params of `$index`/`$payload`) can not use `$self` and must use components\' public interface'); 67 | } 68 | 69 | Behaviors.invertedBehavior(behavior, component, getTargets(component, behavior.selector)); 70 | } 71 | else if (isCameraSelector(behavior.selector)) { 72 | Behaviors.cameraBehavior(behavior, component); 73 | } 74 | else { 75 | if (isSelfSelector(behavior.selector)) { 76 | if (name.indexOf(COMPONENT_DELIM) === -1) { 77 | Behaviors.selfMessagingBehavior(behavior, component); 78 | } 79 | else { 80 | Behaviors.selfDirectBehavior(behavior, component); 81 | } 82 | 83 | } 84 | else { 85 | if (name.indexOf(COMPONENT_DELIM) === -1) { 86 | Behaviors.targetMessagingBehavior(behavior, component, getTargets(component, behavior.selector)); 87 | } 88 | else { 89 | throw new Error('Direct targeted behavior is not supported (' + behavior.selector + '|' + name + '.)'); 90 | } 91 | } 92 | } 93 | } 94 | } 95 | 96 | module.exports = { 97 | route: route 98 | }; 99 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/animation-timeline-queue/animation-timeline-queue.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/animation-timeline-queue/animation-timeline-queue.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:animation-timeline-queue', { 2 | /** 3 | * Behaviors: 4 | * Target each circle in our tree 5 | * using selectors and set size, style 6 | * and other Famous properties. 7 | */ 8 | behaviors: { 9 | '.little-circle': { 10 | 'size': [200, 200], 11 | 'style': { 'border': '10px solid #49AFEB' } 12 | }, 13 | '.medium-circle': { 14 | 'size': [400, 400], 15 | 'style': { 'border': '10px solid #7099EE' } 16 | }, 17 | '.large-circle': { 18 | 'size': [600, 600], 19 | 'style': { 'border': '10px solid #9783F2' } 20 | }, 21 | '.circle': { 22 | 'origin': [0.5, 0.5], 23 | 'align': [0.5, 0.5], 24 | 'mount-point': [0.5, 0.5], 25 | 'style': { 26 | 'border-radius': '50%', 27 | 'cursor': 'pointer' 28 | } 29 | } 30 | }, 31 | /** 32 | * Events: 33 | * Target each circle in our tree 34 | * using selectors and attach a click 35 | * event listener with a callback. 36 | * 37 | * Inject timelines (denoted with a $) 38 | * into our callback function, get the 39 | * pulse-animation and start it with a 40 | * duration of 1500 seconds. 41 | */ 42 | events: { 43 | '.circle': { 44 | 'click': function($timelines) { 45 | $timelines.queue([ 46 | [ 'animation-1', { duration: 800 }, ()=> console.log('--> animation-1 complete!') ], 47 | [ 'animation-2', { duration: 800 }, ()=> console.log('--> animation-2 complete!') ], 48 | [ 'animation-3', { duration: 800 }, ()=> console.log('--> animation-3 complete!') ] 49 | ], function() { 50 | console.log('----> all animations complete!'); 51 | }).startQueue(); 52 | } 53 | } 54 | }, 55 | states: {}, 56 | tree: 'animation-timeline-queue.html' 57 | }) 58 | /** 59 | * Timelines: 60 | * Outline changes to each circle's behavior 61 | * using a keyframe-like API. Percentage 62 | * based frames mean that animations stay 63 | * in sync regardless of duration. 64 | */ 65 | .timelines({ 66 | 'animation-1': { 67 | '.little-circle': { 68 | 'scale': { 69 | '0%': { value: [1.0, 1.0], curve: 'linear' }, 70 | '25%': { value: [1.5, 1.5], curve: 'linear' }, 71 | '50%': { value: [1.0, 1.0] } 72 | } 73 | } 74 | }, 75 | 'animation-2': { 76 | '.medium-circle': { 77 | 'scale': { 78 | '0%': { value: [1.0, 1.0], curve: 'linear' }, 79 | '50%': { value: [1.5, 1.5], curve: 'linear' }, 80 | '75%': { value: [1.0, 1.0] } 81 | } 82 | } 83 | }, 84 | 'animation-3': { 85 | '.large-circle': { 86 | 'scale': { 87 | '0%': { value: [1.0, 1.0], curve: 'linear' }, 88 | '75%': { value: [1.5, 1.5], curve: 'linear' }, 89 | '100%': { value: [1.0, 1.0] } 90 | } 91 | } 92 | } 93 | }); 94 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/animation-timeline/animation-timeline.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/animation-timeline/animation-timeline.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:animation-timeline', { 2 | /** 3 | * Behaviors: 4 | * Target each circle in our tree 5 | * using selectors and set size, style 6 | * and other Famous properties. 7 | */ 8 | behaviors: { 9 | '.little-circle': { 10 | 'size': [200, 200], 11 | 'style': { 'border': '10px solid #49AFEB' } 12 | }, 13 | '.medium-circle': { 14 | 'size': [400, 400], 15 | 'style': { 'border': '10px solid #7099EE' } 16 | }, 17 | '.large-circle': { 18 | 'size': [600, 600], 19 | 'style': { 'border': '10px solid #9783F2' } 20 | }, 21 | '.circle': { 22 | 'origin': [0.5, 0.5], 23 | 'align': [0.5, 0.5], 24 | 'mount-point': [0.5, 0.5], 25 | 'style': { 26 | 'border-radius': '50%', 27 | 'cursor': 'pointer' 28 | } 29 | } 30 | }, 31 | /** 32 | * Events: 33 | * Target each circle in our tree 34 | * using selectors and attach a click 35 | * event listener with a callback. 36 | * 37 | * Inject timelines (denoted with a $) 38 | * into our callback function, get the 39 | * pulse-animation and start it with a 40 | * duration of 1500 seconds. 41 | */ 42 | events: { 43 | '.circle': { 44 | 'click': function($timelines) { 45 | $timelines.get('pulse-animation').start({ duration: 1500 }); 46 | } 47 | } 48 | }, 49 | states: {}, 50 | tree: 'animation-timeline.html' 51 | }) 52 | /** 53 | * Timelines: 54 | * Outline changes to each circle's behavior 55 | * using a keyframe-like API. Percentage 56 | * based frames mean that animations stay 57 | * in sync regardless of duration. 58 | */ 59 | .timelines({ 60 | 'pulse-animation': { 61 | '.little-circle': { 62 | 'scale': { 63 | '0%': { value: [1.0, 1.0], curve: 'outBack' }, 64 | '25%': { value: [1.5, 1.5], curve: 'outBack' }, 65 | '50%': { value: [1.0, 1.0] } 66 | } 67 | }, 68 | '.medium-circle': { 69 | 'scale': { 70 | '0%': { value: [1.0, 1.0], curve: 'outBack' }, 71 | '50%': { value: [1.5, 1.5], curve: 'outBack' }, 72 | '75%': { value: [1.0, 1.0] } 73 | } 74 | }, 75 | '.large-circle': { 76 | 'scale': { 77 | '0%': { value: [1.0, 1.0], curve: 'outBack' }, 78 | '75%': { value: [1.5, 1.5], curve: 'outBack' }, 79 | '100%': { value: [1.0, 1.0] } 80 | } 81 | } 82 | } 83 | }); 84 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/attach-webgl/attach-webgl.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:attach-webgl', { 2 | behaviors: { 3 | '#webgl-node' : { 4 | size: [200, 200], 5 | position: '[[identity]]', 6 | style: { 7 | 'cursor': 'pointer' 8 | } 9 | }, 10 | '#label' : { 11 | position: [50, 50], 12 | size: [400, 100], 13 | style: { 14 | color: 'white' 15 | } 16 | } 17 | }, 18 | events: { 19 | '#webgl-node' : { 20 | 'click' : function($state) { 21 | var newPosition = [Math.random() * 500, Math.random() * 500]; 22 | $state.set('position', newPosition, {duration: 400, 'curve' : 'outExpo'}); 23 | } 24 | } 25 | }, 26 | tree: ` 27 | 28 |
Click on the geodesic sphere to update its position:
29 |
30 | 31 | 32 | `, 33 | states: { 34 | 'position' : [100, 100] 35 | } 36 | }) 37 | /** 38 | * Config: 39 | * Include other files (.js, .css, etc) in your project. 40 | */ 41 | .config({ includes: ['webgl-example.js'] }); 42 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/attach-webgl/webgl-example.js: -------------------------------------------------------------------------------- 1 | var Mesh = FamousFramework.FamousEngine.webglRenderables.Mesh; 2 | var Material = FamousFramework.FamousEngine.webglMaterials.Material; 3 | 4 | /** 5 | * Attach: 6 | * To attach raw engine code to a component, 7 | * simply pass in the component, version and 8 | * the context that it'll live in. 9 | * 10 | * Inside of our executable function, we'll 11 | * have access to the node of that context 12 | * and can use it with 13 | */ 14 | FamousFramework.attach('#webgl-node', function(node) { 15 | var mesh = new Mesh(node) 16 | .setGeometry('GeodesicSphere') 17 | .setBaseColor(Material.normal()); 18 | }); 19 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/best/arrow/arrow.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:best:arrow', { 2 | behaviors: { 3 | '#arrow': { 4 | 'size': [true, 70], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5], 7 | 'origin': [0.5, 0.5], 8 | 'style': { 9 | 'color': 'whitesmoke', 10 | 'font-size': '50px' 11 | }, 12 | 'content': '⬆', 13 | 'position': function(position) { 14 | return position; 15 | }, 16 | 'rotation-z': function(angle) { 17 | return angle; 18 | } 19 | } 20 | }, 21 | events: { 22 | '$public': { 23 | 'position': function($state, $payload) { 24 | $state.set('position', $payload); 25 | }, 26 | 'angle': function($state, $payload) { 27 | $state.set('angle', $payload); 28 | } 29 | } 30 | }, 31 | states: { 32 | 'position': [0, 0], 33 | 'angle': 0 34 | }, 35 | tree: ` 36 | 37 | ` 38 | }); 39 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/best/demo/demo.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:best:demo', { 2 | behaviors: { 3 | '$self': { 4 | 'position-y': 100, 5 | 'rotation-x': Math.PI/4 6 | }, 7 | '$camera': { 8 | 'depth': 4000 9 | }, 10 | '#square': { 11 | '$repeat': [ 12 | { content: 'BEHAVIOR', position: [ 200, 0] }, 13 | { content: 'EVENT' , position: [-200, 0] }, 14 | { content: 'STATE' , position: [ 0, -200] }, 15 | { content: 'TREE' , position: [ 0, 200] } 16 | ] 17 | }, 18 | '#arrow': { 19 | '$repeat': [ 20 | { position: [ 115, 115], angle: 5 * Math.PI / 4 }, 21 | { position: [ 115, -115], angle: -5 * Math.PI / 4 }, 22 | { position: [-115, 115], angle: -Math.PI / 4 }, 23 | { position: [-115, -115], angle: Math.PI / 4 } 24 | ] 25 | } 26 | }, 27 | events: {}, 28 | states: {}, 29 | tree: ` 30 | 31 | 32 | ` 33 | }) 34 | .config({ 35 | imports: { 36 | 'famous-demos:best': ['floating-square', 'arrow'] 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/best/floating-square/floating-square.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:best:floating-square', { 2 | behaviors: { 3 | '#container': { 4 | 'position': function(position, hoverHeight) { 5 | // return [position[0], hoverHeight + 100 * (Math.sin(hoverHeight)) + position[1]]; 6 | return position; 7 | } 8 | }, 9 | '#square': { 10 | 'align': [0.5, 0.5], 11 | 'origin': [0.5, 0.5], 12 | 'mount-point': [0.5, 0.5], 13 | 'rotation-z': Math.PI/4, 14 | 'size': function(squareSize) { 15 | return squareSize; 16 | }, 17 | 'style': { 18 | 'background': 'linear-gradient(45deg, #3F5AA7, #3DB0E4)' 19 | } 20 | }, 21 | '#label': { 22 | 'position-z': 10, 23 | 'size': [200, 200], 24 | 'align': [0.5, 0.5], 25 | 'origin': [0.5, 0.5], 26 | 'mount-point': [0.5, 0.5], 27 | 'style': { 28 | 'text-align': 'center', 29 | 'line-height': '175px', 30 | 'font-family': 'Lato', 31 | 'font-size': '24px', 32 | 'color': 'whitesmoke', 33 | }, 34 | 'unselectable': true, 35 | 'content': function(labelContent) { 36 | return labelContent.split('').join(' '); 37 | } 38 | } 39 | }, 40 | events: { 41 | '$public': { 42 | 'content': function($state, $payload) { 43 | $state.set('labelContent', $payload); 44 | }, 45 | 'position': function($state, $payload) { 46 | $state.set('position', $payload); 47 | }, 48 | 'hover': function($state, $payload) { 49 | $state.set('hoverHeight', $payload, { duration: $payload * 1000 }); 50 | } 51 | } 52 | }, 53 | states: { 54 | 'hoverHeight': 0, 55 | 'position': [0, 0], 56 | 'squareSize': [200, 200], 57 | 'labelContent': 'TEXT' 58 | }, 59 | tree: ` 60 | 61 | 62 | 63 | 64 | ` 65 | }); 66 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/clickable-square-with-logo/assets/famous_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/clickable-square/clickable-square.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:clickable-square', { 2 | behaviors: { 3 | '#background': { 4 | 'style': { 5 | 'background-color': '#444' 6 | } 7 | }, 8 | '#square': { 9 | 'align': [0.5, 0.5], 10 | 'origin': [0.5, 0.5], 11 | 'mount-point': [0.5, 0.5], 12 | 'size': function(boxSize) { 13 | return [boxSize, boxSize]; 14 | }, 15 | 'content': function(numberOfClicks) { 16 | return `
${numberOfClicks}
`; 17 | }, 18 | 'rotation-z': function(angle) { 19 | // console.log(angle); 20 | return angle; 21 | }, 22 | 'style': { 23 | 'color': '#7099EE', 24 | 'background': '#222222', 25 | 'border': '6px solid #333333', 26 | 'text-align': 'center', 27 | 'font-size': '60px', 28 | 'font-family': '"Lato", Helvetica, Arial, sans-serif', 29 | 'cursor': 'pointer' 30 | }, 31 | 'unselectable': true 32 | } 33 | }, 34 | events: { 35 | '#square': { 36 | 'click': function($state) { 37 | $state.set('numberOfClicks', $state.get('incrementPerClick') + $state.get('numberOfClicks')); 38 | $state.set('angle', $state.get('angle') + $state.get('rotationPerClick'), { 39 | duration: $state.get('rotationDuration'), 40 | curve: $state.get('rotationCurve') 41 | }); 42 | } 43 | } 44 | }, 45 | states: { 46 | numberOfClicks: 0, 47 | angle: 0, 48 | rotationPerClick: Math.PI / 2, 49 | rotationDuration: 1500, 50 | rotationCurve: 'outBounce', 51 | incrementPerClick: 1, 52 | boxSize: 400 53 | }, 54 | tree: ` 55 | 56 | 57 | 58 | ` 59 | }) 60 | .config({ 61 | expose: [ 62 | { key: 'rotationCurve', name: 'Rotation Curve' }, 63 | { key: 'rotationPerClick', name: 'Rotation Per Click', range: [0, Math.PI * 2], step: 0.1 }, 64 | { key: 'rotationDuration', name: 'Rotation Duration', range: [0, 5000] }, 65 | { key: 'incrementPerClick', name: 'Increment Per Click', range: [0, 10], type: 'int' }, 66 | { key: 'boxSize', name: 'Box Size', range: [0, 1000] }, 67 | ] 68 | }); 69 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/config-panel/config-panel.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:config-panel', { 2 | tree: ` 3 | 4 | 5 | ` 6 | }); 7 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/dynamic-list/dynamic-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 |
Add
10 |
11 | 12 | 13 |
Remove
14 |
15 | 16 |
17 | 18 | 19 | 20 | 21 |
-------------------------------------------------------------------------------- /lib/core-components/famous-demos/layouts/flexible/header-footer/header-footer.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:layouts:flexible:header-footer', { 2 | behaviors: { 3 | 'famous:layouts:flexible': { 4 | 'direction': 1, 5 | 'ratios': [true, 1, true] 6 | }, 7 | '.header': { 8 | 'content': 'HEADER', 9 | 'size-absolute-y': 100, 10 | 'style': { 11 | 'background-color': '#000', 12 | 'color': '#fff' 13 | } 14 | }, 15 | '.body': { 16 | 'content': 'BODY', 17 | 'style': { 18 | 'background-color': '#ddd', 19 | 'color': '#000' 20 | } 21 | }, 22 | '.footer': { 23 | 'content': 'FOOTER', 24 | 'size-absolute-y': 50, 25 | 'style': { 26 | 'background-color': '#555', 27 | 'color': '#fff' 28 | } 29 | } 30 | }, 31 | events: {}, 32 | states: {}, 33 | tree: ` 34 | 35 | 36 | 37 | 38 | 39 | ` 40 | }); 41 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/layouts/flexible/nested/nested.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:layouts:flexible:nested', { 2 | behaviors: { 3 | '.wrapper': { 4 | 'direction': 0, 5 | 'ratios': [3, true, 1, true, 2] 6 | }, 7 | '.first': { 8 | 'direction': 1, 9 | 'ratios': [1, true, 5] 10 | }, 11 | '.second': { 12 | 'direction': 0, 13 | 'ratios': [1] 14 | }, 15 | '.third': { 16 | 'direction': 1, 17 | 'ratios': [5, true, 1] 18 | }, 19 | '.item': { 20 | 'style': { 21 | 'background-color': '#000', 22 | 'color': '#fff' 23 | } 24 | }, 25 | '.splitter': { 26 | 'style': { 27 | 'background-color': '#fff' 28 | } 29 | }, 30 | '.horizontal.splitter': { 31 | 'size-absolute-y': 1, 32 | }, 33 | '.vertical.splitter': { 34 | 'size-absolute-x': 1, 35 | } 36 | }, 37 | events: {}, 38 | states: {}, 39 | tree: ` 40 | 41 | 42 |
1
43 | 44 |
2
45 |
46 | 47 | 48 |
3
49 |
50 | 51 | 52 |
4
53 | 54 |
5
55 |
56 |
57 | ` 58 | }); 59 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/layouts/flexible/simple/simple.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:layouts:flexible:simple', { 2 | behaviors: { 3 | 'famous:layouts:flexible': { 4 | 'direction': 0, 5 | 'ratios': [1, true, 2, true, 5, true, 10, true, 5, true, 2, true, 1] 6 | }, 7 | '.item': { 8 | 'style': { 9 | 'background-color': '#000', 10 | 'color': '#fff' 11 | } 12 | }, 13 | '.splitter': { 14 | 'size-absolute-x': 1, 15 | 'style': { 16 | 'background-color': '#fff' 17 | } 18 | } 19 | }, 20 | events: {}, 21 | states: {}, 22 | tree: ` 23 | 24 |
1
25 | 26 |
2
27 | 28 |
5
29 | 30 |
10
31 | 32 |
5
33 | 34 |
2
35 | 36 |
1
37 |
38 | ` 39 | }); 40 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/layouts/sequential/simple/simple.js: -------------------------------------------------------------------------------- 1 | const COLORS = ['#990000', '#009900', '#000099', '#999900', '#990099']; 2 | const SIZES = [100, 70, 250, 100, 200]; 3 | 4 | FamousFramework.component('famous-demos:layouts:sequential:simple', { 5 | behaviors: { 6 | 'famous:layouts:sequential': { 7 | 'direction': 0 8 | }, 9 | '.item': { 10 | 'style': { 11 | 'color': '#fff' 12 | } 13 | }, 14 | '.item.one': { 15 | 'content': `${SIZES[0]}px`, 16 | 'size-absolute-x': SIZES[0], 17 | 'style': { 18 | 'background-color': COLORS[0] 19 | } 20 | }, 21 | '.item.two': { 22 | 'content': `${SIZES[1]}px`, 23 | 'size-absolute-x': SIZES[1], 24 | 'style': { 25 | 'background-color': COLORS[1] 26 | } 27 | }, 28 | '.item.three': { 29 | 'content': `${SIZES[2]}px`, 30 | 'size-absolute-x': SIZES[2], 31 | 'style': { 32 | 'background-color': COLORS[2] 33 | } 34 | }, 35 | '.item.four': { 36 | 'content': `${SIZES[3]}px`, 37 | 'size-absolute-x': SIZES[3], 38 | 'style': { 39 | 'background-color': COLORS[3] 40 | } 41 | }, 42 | '.item.five': { 43 | 'content': `${SIZES[4]}px`, 44 | 'size-absolute-x': SIZES[4], 45 | 'style': { 46 | 'background-color': COLORS[4] 47 | } 48 | } 49 | }, 50 | events: {}, 51 | states: {}, 52 | tree: ` 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | ` 61 | }); 62 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/lifecycle/lifecycle.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/lifecycle/lifecycle.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:lifecycle', { 2 | /** 3 | * Behaviors: 4 | * Target the ball and ground in our tree 5 | * using selectors and set style, size 6 | * and other Famous properties. 7 | * 8 | * position-x is a function of our positionX state 9 | * and will rerun on each positionX state change. 10 | * 11 | * rotation-z is a function of our rotationZ state 12 | * and will rerun on each rotationZ state change. 13 | */ 14 | behaviors: { 15 | '#ball': { 16 | 'size': [400, 400], 17 | 'align': [0, 0.5], 18 | 'origin': [0.5, 0.5], 19 | 'mount-point': [0.5, 0.5], 20 | 'position-x': function(positionX) { return positionX; }, 21 | 'rotation-z': function(rotationZ) { return rotationZ; }, 22 | 'style': { 23 | 'border-radius': '100%', 24 | 'border': '10px dotted #9783F2', 25 | } 26 | }, 27 | '#ground': { 28 | 'size': [window.innerWidth, 1], 29 | 'position-y': 200, 30 | 'align': [0.5, 0.5], 31 | 'mount-point': [0.5, 0.5], 32 | 'style': { 'border': '4px solid #222222' } 33 | } 34 | }, 35 | /** 36 | * Events: 37 | * On our component's post-load 38 | * event, a callback will fire. 39 | * 40 | * Lifecycle: 41 | * Throughout the life of a component, 42 | * special lifecycle events will be emitted. 43 | * 44 | * Inject state (denoted with a $) 45 | * into our callback function. 46 | * 47 | * Set the positionX to 200 less than the width of the window over a duration. 48 | * and curve. Also, set the rotationX to Math.PI*4 over a duration and curve. 49 | */ 50 | events: { 51 | '$lifecycle': { 52 | 'post-load': function($state) { 53 | $state.set('positionX', window.innerWidth - 200, {duration: 10000, curve: 'outBounce'}); 54 | $state.set('rotationZ', Math.PI*4, {duration: 10000, curve: 'outBounce'}); 55 | } 56 | } 57 | }, 58 | /** 59 | * States: 60 | * Set the positonX and rotationZ 61 | * states of our application. 62 | */ 63 | states: { 64 | 'positionX': 0, 65 | 'rotationZ': 0 66 | }, 67 | tree: 'lifecycle.html' 68 | }); 69 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/repeat-color-wheel/repeat-color-wheel.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:repeat-color-wheel', { 2 | /** 3 | * Behaviors: 4 | * Target the line in our tree 5 | * using selectors and set size, style 6 | * and other Famous properties. 7 | * 8 | * Repeat: 9 | * Repeat is used when we want to repeat 10 | * some element in our tree. 11 | * 12 | * We are using $repeat to make 360 lines. 13 | * 14 | * Index: 15 | * When using $repeat, we can inject $index 16 | * to other behavior functions to gain access 17 | * to that elements index. 18 | * 19 | * We are using $index to rotate each line to 20 | * make a circle. We are also using it to style 21 | * each line a different color. 22 | */ 23 | behaviors: { 24 | '.line': { 25 | 'size': [window.innerWidth/4, 2], 26 | 'align': [0.5, 0.5], 27 | 'mount-point': [0.5, 0.5], 28 | 'origin': [0.5, 0.5], 29 | '$repeat': function() { 30 | var messages = []; 31 | for (var i = 0; i < 360; i++) { 32 | messages.push({ i: i }); 33 | } 34 | return messages; 35 | }, 36 | 'rotation-z': function($index) { 37 | return $index * Math.PI/360; 38 | }, 39 | 'style': function($index) { 40 | return { 41 | 'background': "hsl(" + $index + ", 100%, 50%)" 42 | } 43 | } 44 | } 45 | }, 46 | events: {}, 47 | states: {}, 48 | tree: ` 49 | 50 | ` 51 | }); 52 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/scroll-view-example/scroll-view-example.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:scroll-view-example', { 2 | behaviors: { 3 | '$self': { 4 | }, 5 | 'scroll-view' : { 6 | 'item-height' : 100, 7 | 'scroll-view-size' : [400, 700], 8 | 'scroll-view-position' : [75, 100] 9 | }, 10 | '#label' : { 11 | 'position': [75, 25], 12 | 'size' : [400, 100], 13 | 'style' : { 14 | 'color' : '#40b2e8', 15 | 'font-family' : 'Lato', 16 | 'font-size' : '18px' 17 | } 18 | }, 19 | '.scroll-view-item' : { 20 | style: { 21 | 'background-color' : 'white', 22 | 'border' : '1px solid black', 23 | 'color' : '#40b2e8', 24 | 'font-family' : 'Lato', 25 | 'font-size' : '30px', 26 | 'padding' : '10px' 27 | }, 28 | 'size-absolute-y': 100, 29 | '$repeat' : function(count) { 30 | var result = []; 31 | for(var i =0; i < count; i++) { 32 | result.push({ 33 | content: `Item ${ i + 1 }` 34 | }); 35 | } 36 | return result; 37 | } 38 | } 39 | }, 40 | events: { 41 | '$public' : { 42 | count: '[[setter]]' 43 | }, 44 | 'node' : { 45 | 'click' : function($index) { 46 | console.log('Click on Item ', $index); 47 | } 48 | } 49 | }, 50 | states: { 51 | count: 10 52 | }, 53 | tree: ` 54 | 55 |
Send a message to the component using \`FamousFramework.message\` to update the number of items.
56 |
57 | 58 | 59 | 60 | ` 61 | }) 62 | .config({ 63 | imports: { 64 | 'famous:layouts' : ['scroll-view'] 65 | } 66 | }); 67 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/simplified-todos/simplified-todos.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-demos:simplified-todos', { 2 | behaviors: { 3 | '#list': { 4 | 'inner-html': function(todos) { 5 | return todos.map(function(todo) { 6 | return `
  • ${todo}
  • `; 7 | }).join(''); 8 | } 9 | } 10 | }, 11 | events: { 12 | '#input': { 13 | 'famous:events:change': function($state, $event) { 14 | $state.set('todos', $state.get('todos').concat($event.value)); 15 | } 16 | } 17 | }, 18 | states: { 19 | todos: [] 20 | }, 21 | tree: ` 22 |
    23 |

    todos

    24 | 25 |
      26 |
      27 | ` 28 | }) 29 | .config({ 30 | includes: ['todos.css'] 31 | }); 32 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/simplified-todos/todos.css: -------------------------------------------------------------------------------- 1 | #todos { 2 | margin-top: 100px; 3 | } 4 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/styling-inner-content/styling-inner-content.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-demos:styling-inner-content', { 2 | behaviors: { 3 | 'node' : { 4 | position: [100, 100], 5 | size: [200, 200], 6 | style: { 7 | 'background-color' : 'whitesmoke', 8 | 'border-radius' : '10px', 9 | 'line-height' : '200px', 10 | 'text-align' : 'center' 11 | } 12 | }, 13 | 'a' : { 14 | 'style' : function(color, fontFamily) { 15 | return { 16 | 'color': color, 17 | 'font-family': fontFamily, 18 | 'font-size' : '30px', 19 | 'text-align' : 'center', 20 | } 21 | } 22 | } 23 | }, 24 | events: { 25 | }, 26 | states: { 27 | color: '#49afeb', 28 | fontFamily: 'Lato, Helvetica, Arial, sans-serif' 29 | }, 30 | tree: ` 31 | 32 | famous.org 33 | 34 | `, 35 | }); 36 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/app/app.js: -------------------------------------------------------------------------------- 1 | const INITIAL_PAGE_ID = 'tweets'; 2 | 3 | FamousFramework.component('famous-demos:twitter:app', { 4 | behaviors: { 5 | '.layout': { 6 | 'direction': 1, 7 | 'ratios': [true, 1, true] 8 | }, 9 | '.navbar': { 10 | 'size-absolute-y': 50 11 | }, 12 | '.page': { 13 | 'page-id': '[[identity|pageId]]' 14 | }, 15 | '.tabbar': { 16 | 'size-absolute-y': 50 17 | } 18 | }, 19 | events: {}, 20 | states: { 21 | pageId: INITIAL_PAGE_ID 22 | }, 23 | tree: ` 24 | 25 | 26 | 27 | 28 | 29 | ` 30 | }).config({ 31 | imports: { 32 | 'famous-demos:twitter': ['navbar', 'page', 'tabbar'] 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/logo/logo.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:twitter:logo', { 2 | behaviors: { 3 | '.container': { 4 | 'content': 'Twitter Layout', 5 | 'style': { 6 | 'color': '#79B8EC', 7 | 'font-size': '25px', 8 | 'font-weight': 'bold', 9 | 'line-height': '25px', 10 | 'text-align': 'center' 11 | } 12 | } 13 | }, 14 | events: {}, 15 | states: {}, 16 | tree: ` 17 | 18 | ` 19 | }); 20 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/navbar-button/navbar-button.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:twitter:navbar-button', { 2 | behaviors: { 3 | '.container': {} 4 | }, 5 | events: {}, 6 | states: {}, 7 | tree: ` 8 | 9 | ` 10 | }); 11 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/navbar/navbar.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:twitter:navbar', { 2 | behaviors: { 3 | '$self': { 4 | 'style': { 5 | 'background': 'linear-gradient(to bottom, #76c5fb 0%, #60abe2 1%, #2978b1 99%, #18659d 100%)', 6 | 'background-color': '#4294ce', 7 | 'text-shadow': 'rgba(0, 0, 0, 0.75) 0px -1px 0px' 8 | } 9 | }, 10 | '.layout': { 11 | 'direction': 0, 12 | 'ratios': [true, 1, true] 13 | }, 14 | '.left': { 15 | 'size-absolute-x': 100 16 | }, 17 | '.logo': { 18 | 'align': [0.5, 0.5], 19 | 'mount-point': [0.5, 0.5], 20 | 'size-absolute-y': 25 21 | }, 22 | '.right': { 23 | 'size-absolute-x': 100 24 | } 25 | }, 26 | events: {}, 27 | states: {}, 28 | tree: ` 29 | 30 | 31 | 32 | 33 | 36 | 37 | 38 | 39 | 40 | ` 41 | }).config({ 42 | imports: { 43 | 'famous-demos:twitter': ['logo', 'navbar-button'] 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/page-tweets/page-tweets.js: -------------------------------------------------------------------------------- 1 | function getData() { 2 | let data = []; 3 | for (let i = 0; i < 20; ++i) { 4 | data.push({ 5 | author: '@famous', 6 | content: 'Hello, Famous Framework!', 7 | imageURL: 'https://pbs.twimg.com/profile_images/378800000758419327/fdb265917b06e621611577a9cec23c58_400x400.png' 8 | }); 9 | } 10 | return data; 11 | } 12 | 13 | const DATA = getData(); 14 | 15 | FamousFramework.component('famous-demos:twitter:page-tweets', { 16 | behaviors: { 17 | '$self': { 18 | 'style': { 19 | 'background-color': '#fff', 20 | 'overflow': 'scroll' 21 | } 22 | }, 23 | '.layout': { 24 | 'direction': 1 25 | }, 26 | '.tweet': { 27 | 'image-url': ($index) => { 28 | return DATA[$index].imageURL; 29 | }, 30 | 'image-width': '[[identity|tweetImageWidth]]', 31 | 'tweet-author': ($index) => { 32 | return DATA[$index].author; 33 | }, 34 | 'tweet-content': ($index) => { 35 | return DATA[$index].content; 36 | }, 37 | 'size-absolute-y': '[[identity|tweetHeight]]', 38 | 'style': { 39 | 'border-bottom': '1px solid #888' 40 | } 41 | } 42 | }, 43 | events: { 44 | '$public': { 45 | 'page': '[[setter]]' 46 | } 47 | }, 48 | states: { 49 | page: null, 50 | tweetHeight: 80, 51 | tweetImageWidth: 80 52 | }, 53 | tree: ` 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | ` 77 | }).config({ 78 | imports: { 79 | 'famous-demos:twitter': ['datastream', 'tweet'] 80 | } 81 | }); 82 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/page/page.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:twitter:page', { 2 | behaviors: { 3 | '$self': { 4 | 'style': { 5 | 'background-color': '#fff', 6 | 'overflow': 'scroll' 7 | } 8 | }, 9 | 'page-tweets': { 10 | '$if': (pageId) => { 11 | return pageId === 'tweets'; 12 | } 13 | } 14 | }, 15 | events: { 16 | '$public': { 17 | 'page-id': '[[setter|pageId]]' 18 | } 19 | }, 20 | states: { 21 | pageId: null 22 | }, 23 | tree: ` 24 | 25 | ` 26 | }).config({ 27 | imports: { 28 | 'famous-demos:twitter': ['page-tweets'] 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/tabbar-button/tabbar-button.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:twitter:tabbar-button', { 2 | behaviors: { 3 | '.container': { 4 | 'style': (backgroundColor) => { 5 | return { 6 | 'background-color': backgroundColor 7 | }; 8 | } 9 | }, 10 | '.text': { 11 | 'content': '[[identity|text]]', 12 | 'align-y': 0.5, 13 | 'mount-point-y': 0.5, 14 | 'size-absolute-y': 18, 15 | 'style': { 16 | 'color': '#aaa', 17 | 'font-size': '18px', 18 | 'line-height': '18px', 19 | 'text-align': 'center' 20 | } 21 | } 22 | }, 23 | events: { 24 | '$public': { 25 | 'background-color': '[[setter|backgroundColor]]', 26 | 'text': '[[setter]]' 27 | } 28 | }, 29 | states: { 30 | backgroundColor: null, 31 | text: '' 32 | }, 33 | tree: ` 34 | 35 | 36 | 37 | 38 | ` 39 | }); 40 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/tabbar/tabbar.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:twitter:tabbar', { 2 | behaviors: { 3 | '$self': { 4 | 'style': { 5 | 'background-color': '#181818' 6 | } 7 | }, 8 | '.layout': { 9 | 'direction': 0, 10 | 'ratios': [1, 1, 1] 11 | }, 12 | '.one': { 13 | 'background-color': '#000', 14 | 'text': 'Tweets' 15 | }, 16 | '.two': { 17 | 'background-color': '#181818', 18 | 'text': 'Mentions' 19 | }, 20 | '.three': { 21 | 'background-color': '#000', 22 | 'text': 'Settings' 23 | } 24 | }, 25 | events: {}, 26 | states: {}, 27 | tree: ` 28 | 29 | 30 | 31 | 32 | 33 | ` 34 | }).config({ 35 | imports: { 36 | 'famous-demos:twitter': ['tabbar-button'] 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/tweet/tweet.css: -------------------------------------------------------------------------------- 1 | img { 2 | height: auto; 3 | left: 5%; 4 | max-height: 90%; 5 | max-width: 90%; 6 | position: relative; 7 | top: 5%; 8 | } 9 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/twitter/tweet/tweet.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous-demos:twitter:tweet', { 2 | behaviors: { 3 | '.layout': { 4 | 'ratios': [true, 1] 5 | }, 6 | '.image': { 7 | 'content': (imageURL) => { 8 | return `` 9 | }, 10 | 'size-absolute-x': '[[identity|imageWidth]]' 11 | }, 12 | '.content': { 13 | 'direction': 1, 14 | 'ratios': [1, 1] 15 | }, 16 | '.author': { 17 | 'content': '[[identity|author]]', 18 | 'style': (contentHeight) => { 19 | return { 20 | 'font-weight': 'bold', 21 | 'line-height': `${contentHeight / 2}px`, 22 | 'top': '5px' 23 | }; 24 | } 25 | }, 26 | '.tweet': { 27 | 'content': '[[identity]]', 28 | 'style': (contentHeight) => { 29 | return { 30 | 'line-height': `${contentHeight / 2}px`, 31 | 'top': '-5px' 32 | }; 33 | } 34 | } 35 | }, 36 | events: { 37 | '$self': { 38 | 'size-change': ($famousNode, $state) => { 39 | let size = $famousNode.getSize(); 40 | $state.set('contentHeight', size[1]); 41 | } 42 | }, 43 | '$public': { 44 | 'image-url': '[[setter|imageURL]]', 45 | 'image-width': '[[setter|imageWidth]]', 46 | 'tweet-author': '[[setter|author]]', 47 | 'tweet-content': '[[setter|content]]' 48 | } 49 | }, 50 | states: { 51 | author: '', 52 | content: '', 53 | contentHeight: null, 54 | imageURL: null, 55 | imageWidth: 0 56 | }, 57 | tree: ` 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | ` 68 | }).config({ 69 | includes: ['tweet.css'] 70 | }); 71 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/calendar/calendar.css: -------------------------------------------------------------------------------- 1 | table.days { 2 | margin:0 auto; 3 | } 4 | 5 | table.days td { 6 | width:50px; 7 | height:50px; 8 | background:#222; 9 | text-align:center; 10 | cursor:pointer; 11 | font-size:22px; 12 | font-weight: bold; 13 | -moz-user-select: -moz-none; 14 | -khtml-user-select: none; 15 | -webkit-user-select: none; 16 | -o-user-select: none; 17 | user-select:none; 18 | } 19 | 20 | table.days td.spacer, table.days td.spacer:hover { 21 | border:none; 22 | background:none 23 | } 24 | 25 | table.days td.active { 26 | color:#40b2e8; 27 | } 28 | 29 | table.days td:hover { 30 | color:#fff; 31 | background:#40b2e8; 32 | } 33 | 34 | .previous button { 35 | cursor:pointer; 36 | background:transparent; 37 | border:none; 38 | border-top: 15px solid transparent; 39 | border-right: 25px solid #40b2e8; 40 | border-bottom: 15px solid transparent; 41 | } 42 | 43 | .next button { 44 | cursor:pointer; 45 | background:transparent; 46 | border:none; 47 | border-top: 15px solid transparent; 48 | border-left: 25px solid #40b2e8; 49 | border-bottom: 15px solid transparent; 50 | } -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/calendar/calendar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/clock/clock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/dashboard/background.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/background2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/dashboard/background2.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/calendar-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/dashboard/calendar-icon.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/clock-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/dashboard/clock-icon.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/dashboard.css: -------------------------------------------------------------------------------- 1 | [draggable] { 2 | -moz-user-select: none; 3 | -khtml-user-select: none; 4 | -webkit-user-select: none; 5 | user-select: none; 6 | /* Required to make elements draggable in old WebKit */ 7 | -khtml-user-drag: element; 8 | -webkit-user-drag: element; 9 | } 10 | 11 | .widget-list-item div { 12 | transition: all 100ms ease-out; 13 | -webkit-transition: all 100ms ease-out 14 | -moz-transition: all 100ms ease-out 15 | -o-transition: all 100ms ease-out 16 | } 17 | 18 | .widget-list-item img { 19 | border-radius: 10px; 20 | } 21 | 22 | .widget-list-item div:hover { 23 | transform:scale(1.1); 24 | -moz-transform:scale(1.1); 25 | -webkit-transform:scale(1.1); 26 | -o-transform:scale(1.1); 27 | -ms-transform:scale(1.1); 28 | } -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 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 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/photos-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/dashboard/photos-icon.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/photos-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/dashboard/photos-icon.png -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/stocks-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/dashboard/stocks-icon.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/dashboard/weather-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/dashboard/weather-icon.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-1.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-2.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-3.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-4.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/photos/stock/kitten-5.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/stocks/stocks.css: -------------------------------------------------------------------------------- 1 | .text-box input { 2 | width:100%; 3 | height:100%; 4 | font-size:38px; 5 | border-radius: 10px; 6 | border: none, 7 | border-bottom: 1px solid black, 8 | } 9 | 10 | .ticker-item:hover { 11 | background:red; 12 | } 13 | 14 | .chart { 15 | width:455px; 16 | height:240px; 17 | /*background:url(https://www.google.com/finance/getchart?q=GOOG) 0px -12px no-repeat; */ 18 | border:4px solid #40b2e8; 19 | border-radius:20px; 20 | position:absolute; 21 | bottom:0; 22 | margin: 20px; 23 | } 24 | 25 | .ticker-detail h2 { 26 | margin:35px 0 0 30px; 27 | font-size:40px; 28 | font-weight: normal; 29 | } 30 | 31 | .ticker-detail h3 { 32 | margin:0 0 0 30px; 33 | font-size:20px; 34 | font-weight: normal; 35 | } 36 | 37 | .ticker-detail h4 { 38 | position:absolute; 39 | top:0; 40 | right:0; 41 | font-size:60px; 42 | line-height:0; 43 | margin-right:30px 44 | } 45 | 46 | h3.none-selected { 47 | font-size:40px; 48 | text-align:center; 49 | margin-top:150px; 50 | } 51 | 52 | h4#stock-l { 53 | padding-top: 50px; 54 | } -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/stocks/stocks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Add 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/weather/animate.css: -------------------------------------------------------------------------------- 1 | h1.loading { 2 | transition: opacity 1000ms ease-out; 3 | -webkit-transition: opacity 1000ms ease-out; 4 | -moz-transition: opacity 1000ms ease-out; 5 | } -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/weather/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-demos/widget-dashboard/weather/background.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/weather/clear_day.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | ]> 6 | 10 | 11 | 12 | 15 | 17 | 19 | 21 | 24 | 26 | 28 | 31 | 34 | 35 | -------------------------------------------------------------------------------- /lib/core-components/famous-demos/widget-dashboard/weather/weather.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

      Loading...

      10 | 11 | 12 |

      13 |

      14 |

      15 |

      16 | 17 | 18 |
      19 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/array-tweening/array-tweening.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:array-tweening', { 2 | behaviors: { 3 | '#square': { 4 | 'position': '[[identity|position]]', 5 | 'size': [200, 200], 6 | 'style': { 7 | 'background': 'red', 8 | 'color': 'white', 9 | 'font-family': 'Lato' 10 | } 11 | } 12 | }, 13 | events: { 14 | '#square': { 15 | 'click': function($state) { 16 | if ($state.get('position')[0] > 200) { 17 | $state.set('position', [0, 0], { 18 | duration: 500, 19 | curve: 'outBack' 20 | }); 21 | } 22 | else { 23 | $state.set('position', [400, 400], { 24 | duration: 500, 25 | curve: 'outBack' 26 | }); 27 | } 28 | } 29 | } 30 | }, 31 | states: { 32 | position: [0, 0] 33 | }, 34 | tree: ` 35 | 36 |
      Click here to see example of tweening array values!
      37 |
      38 | ` 39 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/assets-large/assets-large.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:assets-large', { 2 | tree: ` 3 |

      You should see a large image of a galaxy here

      4 | 5 | ` 6 | }); 7 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/assets-large/galaxy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-tests/assets-large/galaxy.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-tests/bad-dependencies/bad-dependencies.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:bad-dependencies', { 2 | behaviors: { 3 | 'style:': { 4 | 'style:': { 5 | 6 | } 7 | } 8 | }, 9 | events: { 10 | '#hi': { 11 | 'size:': { 12 | 13 | } 14 | } 15 | }, 16 | tree: ` 17 |

      You should see an error message to the effect of

      18 |

      "Direct targeted behavior is not supported..."

      19 | ` 20 | }); 21 | 22 | console.log('You should see an error message to the effect of'); 23 | console.log('"Direct targeted behavior is not supported..."'); 24 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/camera/camera.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/camera/camera.js: -------------------------------------------------------------------------------- 1 | var angle = Math.PI / 5; 2 | 3 | FamousFramework.scene('famous-tests:camera', { 4 | behaviors: { 5 | '$camera': { 6 | 'depth': '[[identity]]' 7 | }, 8 | '$self': { 9 | 'unselectable': true 10 | }, 11 | '#output': { 12 | 'align': [0.5, 0, 0.5], 13 | 'mount-point': [0.5, 0, 0.5], 14 | 'content': function(depth) { 15 | return 'current camera depth: ' + depth; 16 | }, 17 | 'size-absolute': [300, 80], 18 | 'style': { 19 | background: 'rgba(255, 0, 153, 0.5)', 20 | border: '3px solid #ffffff', 21 | color: '#ffffff', 22 | 'line-height': '80px', 23 | 'text-align': 'center' 24 | } 25 | }, 26 | '#outer': { 27 | 'align': [0.5, 0.5, 0.5], 28 | 'mount-point': [0.5, 0.5, 0.5], 29 | 'origin': [0.5, 0.5, 0.5], 30 | 'rotation': [-angle/2, angle, 0], 31 | 'position': [0, 0, -500], 32 | 'size-absolute': [800, 600], 33 | 'style': { 34 | background: 'rgba(255, 0, 153, 0.3)', 35 | border: '5px solid #ffffff', 36 | color: '#ffffff', 37 | 'text-align': 'center' 38 | } 39 | }, 40 | '#middle': { 41 | 'align': [0.5, 0.5, 0.5], 42 | 'mount-point': [0.5, 0.5, 0.5], 43 | 'origin': [0.5, 0.5, 0.5], 44 | 'rotation': [0, -angle, 0], 45 | 'position': [0, 0, -200], 46 | 'size-absolute': [600, 450], 47 | 'style': { 48 | background: 'rgba(255, 0, 153, 0.5)', 49 | border: '5px solid #ffffff', 50 | color: '#ffffff', 51 | 'text-align': 'center' 52 | } 53 | }, 54 | '#inner': { 55 | 'align': [0.5, 0.5, 0.5], 56 | 'mount-point': [0.5, 0.5, 0.5], 57 | 'origin': [0.5, 0.5, 0.5], 58 | 'rotation': [0, -angle, 0], 59 | 'position': [0, 0, 300], 60 | 'size-absolute': [450, 250], 61 | 'style': { 62 | background: 'rgba(255, 0, 153, 1.0)', 63 | border: '5px solid #ffffff', 64 | color: '#ffffff', 65 | 'text-align': 'center' 66 | } 67 | } 68 | }, 69 | events: { 70 | '$self': { 71 | 'click': function($state) { 72 | var newDepth = Math.floor(Math.random() * 2000) + 200; 73 | $state.set('depth', newDepth); 74 | } 75 | } 76 | }, 77 | states: { 78 | depth: 400 79 | }, 80 | tree: 'camera.html' 81 | }) 82 | .config({ 83 | imports: { 84 | 'famous-tests:camera': ['custom'] 85 | } 86 | }); 87 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/camera/custom/custom.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:camera:custom', { 2 | behaviors: { 3 | '$self': { 4 | 'content': 'hello I\'m a custom component' 5 | } 6 | }, 7 | events: {}, 8 | states: {}, 9 | tree: '' 10 | }); 11 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/component-composition/component-composition.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/component-composition/component-composition.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:component-composition', { 2 | behaviors: { 3 | '#box1': { 4 | 'size': [200, 200], 5 | 'position': [0, 0], 6 | 'style': { 7 | background: 'rgba(255, 0, 0, 0.9)' 8 | } 9 | }, 10 | '#box2': { 11 | 'size': [200, 200], 12 | 'position': [50, 50], 13 | // 'style': { 14 | // background: 'rgba(0, 255, 0, 0.9)' 15 | // } 16 | }, 17 | '#child1': { 18 | 'size': [200, 200], 19 | 'position': [250, 250], 20 | 'style': { 21 | background: 'rgba(0, 0, 255, 0.9)' 22 | } 23 | } 24 | }, 25 | events: {}, 26 | states: {}, 27 | tree: 'component-composition.html' 28 | }); 29 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/component-targeting/child/child.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:component-targeting:child', { 2 | behaviors: { 3 | '#child': { 4 | 'align': [0.5, 0.5], 5 | 'mount-point': [0.5, 0.5], 6 | 'size': '[[identity|mySize]]', 7 | 'style': { 8 | 'background': 'whitesmoke' 9 | } 10 | } 11 | }, 12 | events: { 13 | '$public': { 14 | 'my-size': '[[setter|mySize]]', 15 | } 16 | }, 17 | states: { 18 | 'mySize': [100, 100] 19 | }, 20 | tree: ` 21 | 22 | ` 23 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/component-targeting/parent/parent.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:component-targeting:parent', { 2 | behaviors: { 3 | 'child': { 4 | 'my-size': [400, 400] 5 | } 6 | }, 7 | events: {}, 8 | states: {}, 9 | tree: ` 10 | 11 | ` 12 | }) 13 | .config({ 14 | imports: { 15 | 'famous-tests:component-targeting': ['child'] 16 | } 17 | 18 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/control-flow/basic-if/basic-if.html: -------------------------------------------------------------------------------- 1 | 2 |
      Toggle Add/Remove
      3 |
      4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/control-flow/basic-if/basic-if.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:control-flow:basic-if', { 2 | behaviors: { 3 | '#button' : { 4 | position: [200, 50], 5 | size: [200, 50], 6 | style: { 7 | 'border': '2px solid black', 8 | 'background' : 'white', 9 | 'border-radius': '7px', 10 | 'text-align': 'center', 11 | 'line-height' : '50px', 12 | 'cursor' : 'pointer' 13 | }, 14 | 'unselectable' : true, 15 | }, 16 | '#circle' : { 17 | style: { 18 | 'background-color' : 'blue', 19 | 'border-radius': '50%' 20 | }, 21 | position: [200, 125], 22 | }, 23 | '#square' : { 24 | style: { 25 | 'background-color' : 'red', 26 | 'border-radius': '0%' // Work around for bug in Engine (https://github.com/Famous/engine/issues/325) 27 | }, 28 | position: [200, 350], 29 | }, 30 | '.block' : { 31 | $if: function(toggle) { 32 | console.log('`$if`: ', toggle); 33 | return toggle; 34 | }, 35 | style: { 36 | 'border': '3px solid white' 37 | }, 38 | size: [200, 200] 39 | } 40 | }, 41 | events: { 42 | '#button' : { 43 | 'click' : function($state) { 44 | $state.set('toggle', !$state.get('toggle')); 45 | } 46 | } 47 | }, 48 | states: { 49 | toggle: true 50 | }, 51 | tree: 'basic-if.html' 52 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/control-flow/repeat/repeat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
      Square
      7 |
      8 | 9 | 10 |
      Repeated Node
      11 |
      12 | 13 |
      14 | 15 |
      -------------------------------------------------------------------------------- /lib/core-components/famous-tests/control-flow/repeat/repeat.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:control-flow:repeat', { 2 | behaviors: { 3 | '.row' : { 4 | size: [200, 200], 5 | '$repeat' : function(rowCount) { 6 | var messages = []; 7 | for (var i = 0; i < rowCount; i++) { 8 | messages.push({ 9 | 'row' : i 10 | }); 11 | } 12 | return messages; 13 | }, 14 | 'position' : function($index, $repeatPayload, horizontalOffset) { 15 | return [($index) * 50 + horizontalOffset, ($index) * 250]; 16 | } 17 | }, 18 | '.square': { 19 | style: { 20 | 'background-color' : '#f2f2f0', 21 | 'font-family': 'monospace', 22 | 'padding' : '20px', 23 | 'box-shadow': '10px 13px 43px 0px rgba(0,0,0,0.75)' 24 | } 25 | }, 26 | '.label': { 27 | style: { 28 | 'color': '#40b2e8', 29 | 'font-weight' : 'bold', 30 | 'font-family' : 'Lato', 31 | 'font-size' : '20px' 32 | }, 33 | position: [25, 50] 34 | }, 35 | '.column' : { 36 | '$repeat' : function(colCount) { 37 | var messages = []; 38 | for (var i = 0; i < colCount; i++) { 39 | messages.push({ 40 | 'col' : i 41 | }); 42 | } 43 | return messages; 44 | }, 45 | 'position' : function($index, $repeatPayload) { 46 | return [$index * 300, 0] 47 | }, 48 | }, 49 | }, 50 | events: { 51 | '$public': { 52 | 'row-count' : '[[setter|rowCount]]', 53 | 'col-count' : '[[setter|colCount]]', 54 | 'horizontal-offset' : '[[setter|horizontalOffset]]' 55 | } 56 | }, 57 | states: { 58 | rowCount: 5, 59 | colCount: 3, 60 | horizontalOffset: 50, 61 | }, 62 | tree: 'repeat.html', 63 | }); 64 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/control-flow/static-repeat/static-repeat.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:control-flow:static-repeat', { 2 | behaviors: { 3 | '#repeat': { 4 | size: [100, 100], 5 | $repeat: [ 6 | {position: [100, 100], content: 'Element 1'}, 7 | {position: [210, 100], content: 'Element 2'}, 8 | {position: [320, 100], content: 'Element 3'}, 9 | {position: [430, 100], content: 'Element 4'}, 10 | {position: [540, 100], content: 'Element 5'} 11 | ], 12 | style: { 13 | border: '1px solid black' 14 | } 15 | } 16 | }, 17 | tree: '', 18 | }) 19 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/custom-famous-node/custom-famous-node.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:custom-famous-node', { 2 | behaviors: { 3 | '$self' : { 4 | 'top-padding' : '[[identity|topPadding]]', 5 | 'bottom-padding' : '[[identity|bottomPadding]]', 6 | 'left-padding' : '[[identity|leftPadding]]', 7 | 'right-padding' : '[[identity|rightPadding]]', 8 | }, 9 | 'node': { 10 | style: { 11 | 'background-color' : 'peru' 12 | } 13 | } 14 | }, 15 | events: { 16 | $public: { 17 | 'top-padding' : '[[setter|topPadding]]', 18 | 'right-padding' : '[[setter|rightPadding]]', 19 | 'bottom-padding' : '[[setter|bottomPadding]]', 20 | 'left-padding' : '[[setter|leftPadding]]' 21 | }, 22 | '$private' : { 23 | 'top-padding' : function($famousNode, $payload) { 24 | $famousNode.setTopPadding($payload); 25 | }, 26 | 'right-padding' : function($famousNode, $payload) { 27 | $famousNode.setRightPadding($payload); 28 | }, 29 | 'bottom-padding' : function($famousNode, $payload) { 30 | $famousNode.setBottomPadding($payload); 31 | }, 32 | 'left-padding' : function($famousNode, $payload) { 33 | $famousNode.setLeftPadding($payload); 34 | } 35 | } 36 | }, 37 | states: { 38 | 'leftPadding': 40, 39 | 'topPadding': 0, 40 | 'rightPadding': 40, 41 | 'bottomPadding': 0 42 | }, 43 | tree: ` 44 | Child of custom padded node 45 | ` 46 | }) 47 | .config({ 48 | includes: ['register-node-constructor.js'], 49 | famousNodeConstructorName: 'PaddedNode' 50 | }); 51 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/custom-toolchain/browserify-me.js: -------------------------------------------------------------------------------- 1 | var qs = require('qs'); 2 | 3 | console.log(qs.parse('a=c')); 4 | 5 | FamousFramework.scene('famous-tests:custom-toolchain', { 6 | tree: ` 7 |

      You should see the console log something

      8 |

      Foo

      9 | ` 10 | }); 11 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/custom-toolchain/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-toolchain", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "custom-toolchain.js", 6 | "author": "", 7 | "license": "ISC", 8 | "scripts": { 9 | "build": "browserify browserify-me.js -o custom-toolchain.js" 10 | }, 11 | "devDependencies": { 12 | "browserify": "^10.1.3" 13 | }, 14 | "dependencies": { 15 | "qs": "^2.4.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/dispatcher/broadcasting/broadcasting.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:dispatcher:broadcasting', { 2 | behaviors: { 3 | '#parent': { 4 | 'size': [window.innerWidth, window.innerHeight] 5 | } 6 | }, 7 | events: { 8 | '#parent': { 9 | 'click': function($dispatcher) { 10 | $dispatcher.broadcast('child-size', [600, 600]); 11 | } 12 | } 13 | }, 14 | states: {}, 15 | tree: ` 16 | 17 | 18 | 19 | ` 20 | }) 21 | .config({ 22 | imports: { 23 | 'famous-tests:dispatcher:broadcasting': ['child'] 24 | } 25 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/dispatcher/broadcasting/child/child.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:dispatcher:broadcasting:child', { 2 | behaviors: { 3 | '#child': { 4 | 'align': [0.5, 0.5], 5 | 'mount-point': [0.5, 0.5], 6 | 'origin': [0.5, 0.5], 7 | 'size': function(childSize) { 8 | return childSize; 9 | }, 10 | 'style': { 11 | 'background': '#222', 12 | 'border': '1px solid whitesmoke', 13 | 'color': 'whitesmoke' 14 | } 15 | } 16 | }, 17 | events: { 18 | '#child': { 19 | 'child-size': function($state, $payload) { 20 | $state.set('childSize', $payload, { duration: 400, curve: 'outBack' }); 21 | } 22 | } 23 | }, 24 | states: { 25 | childSize: [200, 200] 26 | }, 27 | tree: `Click here!` 28 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/dispatcher/emit/child/child.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:dispatcher:emit:child', { 2 | behaviors: { 3 | '$self' : { 4 | 'size' : [100, 100], 5 | 'style': { 6 | 'background-color' : 'white', 7 | 'cursor' : 'pointer' 8 | } 9 | } 10 | }, 11 | events: { 12 | '$self' : { 13 | 'click' : function($dispatcher, $event, $payload, $repeatPayload, $index) { 14 | console.log('Click Event from child:'); 15 | console.log('event: ', $event); 16 | console.log('payload: ', $payload); 17 | console.log('$index: ', $index); 18 | console.log('$repeatPayload: ', $repeatPayload); 19 | console.log('----------------------------'); 20 | $dispatcher.emit('custom-event', {payload: 'payload'}); 21 | } 22 | } 23 | }, 24 | states: { 25 | }, 26 | tree: ` 27 | ` 28 | }); 29 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/dispatcher/emit/emit.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:dispatcher:emit', { 2 | behaviors: { 3 | '#label' : { 4 | position: [100, 20], 5 | size: [600, 25], 6 | content: 'Click on square, $index/$repeatPayload should be logged from dispatched event.', 7 | style: { 8 | color: 'white', 9 | 'font-family' : 'Lato' 10 | } 11 | }, 12 | 'child' : { 13 | '$repeat': function(count) { 14 | var result = []; 15 | for (var i = 0; i < count; i++) { 16 | result.push({ 17 | content: 'Item ' + i, 18 | position: [100 + i * 150, 100] 19 | }); 20 | } 21 | return result; 22 | } 23 | } 24 | }, 25 | events: { 26 | 'child' : { 27 | 'custom-event' : function($payload, $index, $repeatPayload, $event) { 28 | console.log('Custom Event captured by parent:'); 29 | console.log('event: ', $event); 30 | console.log('payload: ', $payload); 31 | console.log('$index: ', $index); 32 | console.log('$repeatPayload: ', $repeatPayload); 33 | console.log('----------------------------\n\n\n'); 34 | } 35 | } 36 | }, 37 | states: { 38 | count: 5 39 | }, 40 | tree: ` 41 | 42 | 43 | ` 44 | }) 45 | .config({ 46 | imports: { 47 | 'famous-tests:dispatcher:emit': ['child'] 48 | } 49 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/dispatcher/trigger/trigger.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:dispatcher:trigger', { 2 | behaviors: { 3 | '#element': { 4 | 'align': [0.5, 0.5], 5 | 'mount-point': [0.5, 0.5], 6 | 'origin': [0.5, 0.5], 7 | 'size': function(elementSize) { 8 | return elementSize; 9 | }, 10 | 'style': { 'background': 'purple' } 11 | } 12 | }, 13 | events: { 14 | '$public': { 15 | 'change': function($state, $payload) { 16 | console.log('change triggered!'); 17 | } 18 | }, 19 | '#element': { 20 | 'click': function($state, $dispatcher) { 21 | console.log('clicked') 22 | $state.set('elementSize', [400, 400]); 23 | $dispatcher.trigger('change', $state.get('elementSize')); 24 | } 25 | } 26 | }, 27 | states: { 28 | elementSize: [200, 200] 29 | }, 30 | tree: ` 31 |
      Click here!
      32 | ` 33 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/does-behavior-void/child/child.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:does-behavior-void:child', { 2 | behaviors: { 3 | '#child': { 4 | 'size': [200, 200], 5 | 'style': { 6 | 'background': 'whitesmoke' 7 | } 8 | } 9 | }, 10 | events: {}, 11 | states: {}, 12 | tree: ` 13 | 14 | ` 15 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/does-behavior-void/parent/parent.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:does-behavior-void:parent', { 2 | behaviors: { 3 | '#child': { 4 | '$repeat': function() { 5 | var children = []; 6 | for (var i = 0; i < 10; i++) { 7 | children.push(i); 8 | } 9 | return children; 10 | } 11 | } 12 | }, 13 | events: {}, 14 | states: {}, 15 | tree: ` 16 | 17 | ` 18 | }) 19 | .config({ 20 | imports: { 21 | 'famous-tests:does-behavior-void': ['child'] 22 | } 23 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/drag-and-drop/drag-and-drop.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:drag-and-drop', { 2 | behaviors: { 3 | '$self': { 4 | 'size': [undefined, undefined], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5] 7 | }, 8 | '#draggable': { 9 | 'size': [200, 200], 10 | 'position': function(pos) { 11 | return pos 12 | }, 13 | 'style': { 14 | 'background-color': 'whitesmoke', 15 | 'font-family' : 'Lato' 16 | } 17 | } 18 | }, 19 | events: { 20 | '#draggable': { 21 | 'drag': function($state, $event) { 22 | var curr = $state.get('pos'); 23 | var delta = $event.centerDelta; 24 | $state.set('pos', [curr[0] + delta.x, curr[1] + delta.y]); 25 | }, 26 | 'tap' : function($event) { 27 | console.log('tap event: ', $event); 28 | } 29 | } 30 | }, 31 | states: { 32 | 'pos': [0, 0] 33 | }, 34 | tree: ` 35 | 36 |
      Drag me!
      37 |
      38 | ` 39 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/engine-integration/engine-integration.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:engine-integration', { 2 | tree: ` 3 |

      You should see a red box. That box is controlled by raw platform code.

      4 | 5 | `, 6 | behaviors: { 7 | '#ctx': { 8 | 'position': [100, 100] 9 | } 10 | } 11 | }) 12 | .config({ 13 | includes: [ 14 | 'my-famous.js', 15 | 'foo.css' 16 | ] 17 | }); 18 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/engine-integration/foo.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #49afeb; 3 | } 4 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/engine-integration/my-famous.js: -------------------------------------------------------------------------------- 1 | var DOMElement = FamousFramework.FamousEngine.domRenderables.DOMElement; 2 | 3 | var Size = FamousFramework.FamousEngine.components.Size; 4 | 5 | FamousFramework.attach('#ctx', function(renderNode) { 6 | var domEl = new DOMElement(renderNode); 7 | domEl.setContent('Hello Famous!'); 8 | domEl.setProperty('background-color', 'red'); 9 | 10 | var size = new Size(renderNode); 11 | size.setMode(1, 1, 1); 12 | size.setAbsolute(200, 200); 13 | }); 14 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/fouc/fouc.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:fouc', { 2 | behaviors: { 3 | '#view': { 4 | 'size': [200, 200], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5], 7 | 'style': { 8 | 'background-color': '#d3d3d3', 9 | 'border': '5px solid #666' 10 | } 11 | } 12 | }, 13 | events: {}, 14 | states: {}, 15 | tree: ` 16 | 17 | ` 18 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/html-element-events/html-element-events.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:html-element-events', { 2 | behaviors: { 3 | '.container': { 4 | 'size': [200, 200], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5] 7 | } 8 | }, 9 | events: { 10 | '.button': { 11 | 'click': function($event) { 12 | console.log('$event: ', $event); 13 | // Actual behavior: above gets logged three times 14 | // Expected behavior: above gets logged once 15 | 16 | // Problem: 17 | // Cannot read current target off of the stripped 18 | // event returned from the Famous Engine. 19 | 20 | // Solution: 21 | // We're discussing ways to fix this. 22 | // In the meantime, wrap each html element 23 | // in a node to attach events in this way. 24 | } 25 | } 26 | }, 27 | states: {}, 28 | tree: ` 29 | 30 | 31 | 32 | 33 | 34 | ` 35 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/include-css/a.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: blue; 3 | } 4 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/include-css/b.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 64px; 3 | } -------------------------------------------------------------------------------- /lib/core-components/famous-tests/include-css/c.css: -------------------------------------------------------------------------------- 1 | #my-h1 { 2 | color: white; 3 | } 4 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/include-css/d.css: -------------------------------------------------------------------------------- 1 | p { 2 | color: orange; 3 | } 4 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/include-css/e.css: -------------------------------------------------------------------------------- 1 | .p { 2 | text-decoration: underline; 3 | } -------------------------------------------------------------------------------- /lib/core-components/famous-tests/include-css/include-css.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:include-css', { 2 | tree: ` 3 |

      Testing that CSS is included via includes correctly

      4 |

      You should see a blug background, white large header text, and three orange underlined ahoys.

      5 |

      Ahoy

      6 |

      Ahoy

      7 |

      Ahoy

      8 | ` 9 | }) 10 | .config({ 11 | includes: [ 12 | 'a.css', 13 | 'b.css', 14 | 'c.css', 15 | 'd.css', 16 | 'e.css' 17 | ] 18 | }); 19 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/input-field-data/input-field-data.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:input-field-data', { 2 | behaviors: { 3 | '$self': { 4 | 'size': [200, 200], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5] 7 | } 8 | }, 9 | events: { 10 | '#input-field': { 11 | 'famous:events:change': function($state, $event) { 12 | alert($event.value); 13 | }, 14 | 'input': function($state, $event) { 15 | console.log('$event.value: ', $event.value); 16 | } 17 | } 18 | }, 19 | states: {}, 20 | tree: ` 21 | 22 | ` 23 | }); 24 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/misspelled-facets/misspelled-facets.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:misspelled-facets', { 2 | behaviours: {}, 3 | state: {}, 4 | event: {}, 5 | template: '', 6 | tree: ` 7 |

      You should see console warnings about properties that don't belong in the component definition

      8 | ` 9 | }); 10 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/mount-point/mount-point.html: -------------------------------------------------------------------------------- 1 |

      You should see squares rotating about their origin points correctly

      2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
      top left
      12 |
      13 | 14 | 15 |
      top mid
      16 |
      17 | 18 | 19 |
      top left
      20 |
      21 | 22 | 23 | 24 |
      mid left
      25 |
      26 | 27 | 28 |
      mid left
      29 |
      30 | 31 | 32 |
      mid right
      33 |
      34 | 35 | 36 | 37 |
      bottom left
      38 |
      39 | 40 | 41 |
      bottom mid
      42 |
      43 | 44 | 45 |
      bottom right
      46 |
      47 | 48 |
      -------------------------------------------------------------------------------- /lib/core-components/famous-tests/mount-point/mount-point.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:mount-point', { 2 | behaviors: { 3 | '$self' : { 4 | start: true 5 | }, 6 | '#mount-point' : { 7 | size: [200, 50], 8 | position : [100, -50], 9 | content: function(mountPoint) { 10 | return 'Mount point: [' + mountPoint + ']'; 11 | } 12 | }, 13 | '#origin' : { 14 | size: [200, 50], 15 | position : [300, -50], 16 | content: function(origin) { 17 | return 'Origin: [' + origin + ']'; 18 | } 19 | }, 20 | '#container' : { 21 | 'size': [500, 500], 22 | 'position': [100, 100] 23 | }, 24 | '#border' : { 25 | 'style' : { 26 | 'border' : '1px solid black' 27 | } 28 | }, 29 | '.block' : { 30 | style: { 31 | 'background-color' : 'black', 32 | 'opacity' : 0.8, 33 | 'color' : 'white' 34 | }, 35 | size: [100, 100], 36 | 'mount-point' : function(mountPoint) { 37 | return mountPoint; 38 | }, 39 | 'origin' : function(origin) { 40 | return origin; 41 | }, 42 | 'rotation-z' : function(rotateZ) { 43 | return rotateZ; 44 | } 45 | }, 46 | 47 | '#top-left' : { 48 | 'align' : [0, 0] 49 | }, 50 | '#top-mid' : { 51 | 'align' : [0.5, 0] 52 | }, 53 | '#top-right' : { 54 | 'align' : [1, 0] 55 | }, 56 | 57 | 58 | '#mid-left' : { 59 | 'align' : [0, 0.5] 60 | }, 61 | '#mid-mid' : { 62 | 'align' : [0.5, 0.5] 63 | }, 64 | '#mid-right' : { 65 | 'align' : [1, 0.5] 66 | }, 67 | 68 | 69 | '#bottom-left' : { 70 | 'align' : [0, 1] 71 | }, 72 | '#bottom-mid' : { 73 | 'align' : [0.5, 1] 74 | }, 75 | '#bottom-right' : { 76 | 'align' : [1, 1] 77 | }, 78 | }, 79 | events: { 80 | '$private' : { 81 | 'start' : function($state) { 82 | $state.set('rotateZ', Math.PI * 4, {duration: 10000}); 83 | } 84 | } 85 | }, 86 | states: { 87 | mountPoint: [0.5, 0.5], 88 | origin: [0, 0], 89 | rotateZ: 0 90 | }, 91 | tree: 'mount-point.html', 92 | }); 93 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/observe-nested-state/observe-nested-state.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:observe-nested-state', { 2 | behaviors: { 3 | '#thing': { 4 | 'size': function(size) { 5 | return [size.x, size.y]; 6 | }, 7 | 'style': { 8 | 'background': 'whitesmoke' 9 | } 10 | } 11 | }, 12 | events: { 13 | '#thing': { 14 | 'click': function($state) { 15 | var x = $state.get(['size', 'x']); 16 | var y = $state.get(['size', 'y']); 17 | 18 | $state 19 | .set(['size', 'x'], x + 100, { duration: 1000, curve: 'outBack' }) 20 | .set(['size', 'y'], y + 100, { duration: 1000, curve: 'outBack' }) 21 | } 22 | } 23 | }, 24 | states: { 25 | 'size': { 26 | 'x': 100, 27 | 'y': 100 28 | } 29 | }, 30 | tree: ` 31 | 32 | ` 33 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/opacity/child/bottle-label.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-tests/opacity/child/bottle-label.jpg -------------------------------------------------------------------------------- /lib/core-components/famous-tests/opacity/child/child.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:opacity:child', { 2 | behaviors: { 3 | '$self': { 4 | opacity: (opacity) => { 5 | return opacity; 6 | }, 7 | size: [120, 100], 8 | 'style': { 9 | 'background-image': 'url({{BASE_URL}}bottle-label.jpg)', 10 | 'background-repeat': 'no-repeat', 11 | 'background-size': 'cover', 12 | 'display': 'block', 13 | 'overflow': 'hidden' 14 | } 15 | } 16 | }, 17 | events: {}, 18 | states: { 19 | opacity: 0 20 | }, 21 | tree: '' 22 | }); 23 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/opacity/opacity.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:opacity', { 2 | behaviors: { 3 | '$self' : { 4 | size: [800, 50] 5 | }, 6 | '#node1' : { 7 | position: [0, 50] 8 | }, 9 | '#node2' : { 10 | position: [0, 300], 11 | opacity: 0.2 12 | }, 13 | '#node3label' : { 14 | content: 'Opacity of 0% applied to the node beneath this label', 15 | style: { 16 | color: 'white' 17 | }, 18 | size: [200, 25], 19 | position: [0, 550] 20 | }, 21 | '#node3' : { 22 | position: [0, 600], 23 | opacity: 0 24 | }, 25 | '.block' : { 26 | style: '[[identity|myStyle]]', 27 | size: [200, 200] 28 | }, 29 | 30 | 31 | '#child1' : { 32 | position: [300, 300] 33 | }, 34 | '#child2' : { 35 | position: [600, 50], 36 | opacity: 0 37 | }, 38 | '#child3' : { 39 | position: [600, 50], 40 | opacity: 1 41 | } 42 | }, 43 | events: { 44 | }, 45 | states: { 46 | myStyle : { 47 | 'background-color' : 'white', 48 | 'text-align' : 'center', 49 | 'line-height' : '200px', 50 | 'color' : 'black', 51 | 'cursor' : 'pointer' 52 | } 53 | }, 54 | tree: ` 55 |

      You should see two squares, one opaque, and the other semi-transparent. You should also see one logo.

      56 | 57 | 58 | 59 | 60 |
      Opacity: 100%
      61 |
      62 |
      63 |
      64 | 65 | 66 | 67 | 68 |
      Opacity: 20%
      69 |
      70 |
      71 |
      72 | 73 | 74 | 75 | 76 | 77 |
      Opacity: 0%
      78 |
      79 |
      80 |
      81 | 82 | 83 | 84 | 85 | ` 86 | }); 87 | 88 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/pass-through/child-component/child-component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/pass-through/child-component/child-component.jade: -------------------------------------------------------------------------------- 1 | node#view 2 | node#el -------------------------------------------------------------------------------- /lib/core-components/famous-tests/pass-through/child-component/child-component.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:pass-through:child-component', { 2 | behaviors: { 3 | '#el' : { 4 | size: [400, 100], 5 | style : { 6 | 'background-color' : 'whitesmoke', 7 | 'padding': '15px' 8 | } 9 | } 10 | }, 11 | events: { 12 | '$pass-through' : { 13 | '#view' : {'position-view-node' : 'position'}, 14 | '#el' : ['content'] 15 | } 16 | }, 17 | states: { 18 | }, 19 | tree: 'child-component.html' 20 | }); 21 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/pass-through/pass-through.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

      Pass through example

      4 |
      Public Messages are being directly passed through to child components without having to set up an indirect events --> behaviors pipeline.
      5 |
      6 |
      Send messages to the subcomponents via:
      FamousFramework.message('[[root selector]]', '$root', '[[event-name]]', '[[value]]');
      7 |
      8 | 9 | 10 | 11 |
      Passthrough:
      '*'
      12 |
      13 | 14 | 15 |
      Passthrough:
      ['content', 'scale', 'style']
      16 |
      17 | 18 | 19 |
      Passthrough:
      {'block-size' : 'size'}
      20 |
      21 |
      22 | 23 | 24 |
      -------------------------------------------------------------------------------- /lib/core-components/famous-tests/pass-through/pass-through.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:pass-through', { 2 | behaviors: { 3 | '#container' : { 4 | position: [50, 50] 5 | }, 6 | '#label' : { 7 | size: [600, 200] 8 | }, 9 | '#block-view': { 10 | position: [0, 200] 11 | }, 12 | '.block' : { 13 | size: [200, 200], 14 | style: { 15 | 'background-color' : 'navy', 16 | 'color': 'white', 17 | 'font-family': 'monospace', 18 | 'font-weight': 'bold', 19 | 'font-size': '16px' 20 | } 21 | }, 22 | '#two' : { 23 | position: [250, 0] 24 | }, 25 | '#three' : { 26 | position: [500, 0] 27 | }, 28 | // exposes 'pass-through' event for `position` that 29 | // allows the parent to directly interface with its 30 | '#child' : { 31 | 'position-view-node': [0, 500], 32 | content: ` 33 | This child component's view is positioned directly by its 34 | parent because the child exposes a pass-through event for 35 | 'position'. 36 | ` 37 | } 38 | }, 39 | events: { 40 | '$pass-through' : { 41 | '#one' : '*', 42 | '#two' : ['content', 'scale', 'style'], 43 | '#three' : {'block-size' : 'size'} 44 | } 45 | }, 46 | tree: 'pass-through.html', 47 | }) 48 | .config({ 49 | imports: { 50 | 'famous-tests:pass-through' : ['child-component'] 51 | } 52 | }); 53 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/physics/basic/gravity/gravity.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:physics:basic:gravity', { 2 | behaviors: { 3 | '$camera': { 4 | 'depth': 1000 5 | }, 6 | '.sphere': { 7 | 'size': [100, 100], 8 | 'align': [0.5, 0.5], 9 | 'mount-point': [0.5, 0.5], 10 | 'position': function(spherePosition) { 11 | return spherePosition; 12 | }, 13 | 'style': { 14 | 'background': '#666', 15 | 'border-radius': '50%', 16 | 'box-shadow': '0 0 100px #fff' 17 | } 18 | }, 19 | '.particle': { 20 | 'size': [50, 50], 21 | 'align': [0.5, 0.5], 22 | 'mount-point': [0.5, 0.5], 23 | 'position': function(particlePosition) { 24 | return particlePosition; 25 | }, 26 | 'style': { 27 | 'background': '#999', 28 | 'border-radius': '50%' 29 | } 30 | } 31 | }, 32 | events: { 33 | '$lifecycle': { 34 | 'post-load': function($state) { 35 | $state.applyPhysicsForce('gravity3D', [ 'spherePosition', 'particlePosition' ]); 36 | 37 | $state.setPhysicsMass('spherePosition', 10000); 38 | $state.setPhysicsMass('particlePosition', 5); 39 | 40 | $state.setPhysicsVelocity('particlePosition', [ 41 | -250 / Math.PI, 42 | -250 / Math.PI / 2, 43 | -250 / 2 44 | ]); 45 | } 46 | } 47 | }, 48 | states: { 49 | 'spherePosition': [0, 0, 0], 50 | 'particlePosition': [100, 0, 0] 51 | }, 52 | tree: ` 53 | 54 | 55 | ` 56 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/physics/basic/particle/particle.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:physics:basic:particle', { 2 | behaviors: { 3 | '.particle': { 4 | 'size': [200, 200], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5], 7 | 'style': { 8 | 'background': 'whitesmoke', 9 | 'border-radius': '50%' 10 | } 11 | }, 12 | '.one': { 13 | 'position': function(position1) { 14 | return position1; 15 | } 16 | }, 17 | '.two': { 18 | 'position': function(position2) { 19 | return position2; 20 | } 21 | } 22 | }, 23 | events: { 24 | '$lifecycle': { 25 | 'post-load': function($state) { 26 | $state 27 | .applyPhysicsForce('gravity1D', [ 'position1' ]) 28 | .applyPhysicsConstraint('distance', [ 'position1', 'position2' ], { 29 | length: 400 30 | }); 31 | } 32 | }, 33 | '.one': { 34 | 'click': function($state) { 35 | $state 36 | .removePhysicsForce('gravity1D') 37 | .removePhysicsBody('position1'); 38 | } 39 | }, 40 | '.two': { 41 | 'click': function($state) { 42 | $state 43 | .removePhysicsConstraint('distance') 44 | .removePhysicsBody('position2'); 45 | } 46 | } 47 | }, 48 | states: { 49 | 'position1': [0, 0, 0], 50 | 'position2': [0, -200, 0] 51 | }, 52 | tree: ` 53 | 54 | 55 | ` 56 | }); 57 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/physics/basic/spring/spring.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:physics:basic:spring', { 2 | behaviors: { 3 | '.particle': { 4 | 'size': [100, 100], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5] 7 | }, 8 | '.one': { 9 | 'position': function(position1) { 10 | return position1 11 | }, 12 | 'style': { 13 | 'background': '#666', 14 | 'border-radius': '50%', 15 | 'box-shadow': '0 0 100px #fff' 16 | } 17 | }, 18 | '.two': { 19 | 'position': function(position2) { 20 | return position2; 21 | }, 22 | 'style': { 23 | 'background': 'whitesmoke', 24 | 'border-radius': '50%' 25 | } 26 | } 27 | }, 28 | events: { 29 | '$lifecycle': { 30 | 'post-load': function($state) { 31 | $state.applyPhysicsForce('spring', [ 'position1', 'position2' ], { 32 | period: 2, 33 | dampingRatio: 0.3 34 | }); 35 | 36 | $state.setPhysicsMass('position1', 500); 37 | $state.setPhysicsMass('position2', 5); 38 | } 39 | }, 40 | '.one': { 41 | 'click': function($state) { 42 | var xPos = Math.floor(Math.random() * window.innerWidth / 2); 43 | var yPos = Math.floor(Math.random() * window.innerHeight / 2); 44 | 45 | xPos = Math.random() > 0.5 ? -xPos : xPos; 46 | yPos = Math.random() > 0.5 ? -yPos : yPos; 47 | 48 | $state.setPhysicsPosition('position1', [ xPos, yPos, 0 ]); 49 | } 50 | }, 51 | '.two': { 52 | 'click': function($state) { 53 | var xPos = Math.floor(Math.random() * window.innerWidth / 2); 54 | var yPos = Math.floor(Math.random() * window.innerHeight / 2); 55 | 56 | xPos = Math.random() > 0.5 ? -xPos : xPos; 57 | yPos = Math.random() > 0.5 ? -yPos : yPos; 58 | 59 | $state.setPhysicsPosition('position1', [ xPos, yPos, 0 ]); 60 | } 61 | } 62 | }, 63 | states: { 64 | 'position1': [ 200, 0, 0], 65 | 'position2': [-200, 0, 0] 66 | }, 67 | tree: ` 68 | 69 | 70 | ` 71 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/router-test/router-test.html: -------------------------------------------------------------------------------- 1 |
      HOME
      2 |
      BLOG
      3 |
      ABOUT
      4 |
      404
      5 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/router-test/router-test.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:router-test', { 2 | behaviors: { 3 | '#home': { 4 | '$if': function($route) { return $route === '/home' } 5 | }, 6 | '#blog': { 7 | '$if': function($route) { return $route === '/blog' } 8 | }, 9 | '#about': { 10 | '$if': function($route) { return $route === '/about' } 11 | }, 12 | '#fourOhFour': { 13 | '$if': function($route) { return $route != '/home' && $route != '/blog' && $route != '/about' } 14 | }, 15 | '.page': { 16 | 'size': [200, 200], 17 | 'align': [0.5, 0.5], 18 | 'mount-point': [0.5, 0.5], 19 | 'style': { 20 | 'background': 'whitesmoke' 21 | } 22 | } 23 | }, 24 | events: { 25 | 'node': { 26 | 'click': function() { 27 | // go home when a page is clicked 28 | 29 | var location = window.location; 30 | var href = location.href; 31 | 32 | var baseURL = href.substr(0, href.lastIndexOf('/')); 33 | location.replace(baseURL + '/home'); 34 | } 35 | } 36 | }, 37 | states: {}, 38 | tree: 'router-test.html' 39 | }); 40 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/scope/child/child.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:scope:child', { 2 | behaviors: { 3 | "#node" : { 4 | style: { 5 | 'background-color' : 'gray' 6 | }, 7 | size: [100, 100] 8 | } 9 | }, 10 | tree: ` 11 | 12 | `, 13 | }); 14 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/scope/scope.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:scope', { 2 | behaviors: { 3 | '#node' : { 4 | 'content' : 'This square should be blue. \n\n The other square should be gray.', 5 | 'position' : [100, 100], 6 | style: { 7 | 'background-color' : 'blue', 8 | 'color' : 'white' 9 | }, 10 | size: [200, 200] 11 | }, 12 | '#child': { 13 | position: [350, 100] 14 | } 15 | }, 16 | tree: ` 17 | 18 | 19 | ` 20 | }) 21 | .config({ 22 | imports: { 23 | 'famous-tests:scope': ['child'] 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/setter-vs-identity/child/child.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:setter-vs-identity:child', { 2 | behaviors: { 3 | '#square': { 4 | 'size': '[[identity|squareSize]]', // try changing this to '[[setter|squareSize]]' 5 | 'style': { 'background': 'whitesmoke' } 6 | } 7 | }, 8 | events: { 9 | '$public': { 10 | 'childSize': '[[setter|squareSize]]' // try changing this to '[[identity|squareSize]]' 11 | } 12 | }, 13 | states: { 14 | 'squareSize': [200, 200] 15 | }, 16 | tree: ` 17 | 18 | ` 19 | }); 20 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/setter-vs-identity/parent/parent.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:setter-vs-identity:parent', { 2 | behaviors: { 3 | '#child': { 4 | 'childSize': [300, 300] 5 | } 6 | }, 7 | events: {}, 8 | states: {}, 9 | tree: ` 10 | 11 | ` 12 | }) 13 | .config({ 14 | imports: { 15 | 'famous-tests:setter-vs-identity': ['child'] 16 | } 17 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/size-change-event/size-change-event.html: -------------------------------------------------------------------------------- 1 | 2 |
      Try resizing the window.
      The content of square is being updated via `size-change` event.
      3 |
      4 | 5 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/size-change-event/size-change-event.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous-tests:size-change-event', { 2 | behaviors: { 3 | '#container' : { 4 | 'size-proportional': [0.5, 0.5], 5 | 'position' : [0, 50], 6 | 'style': { 7 | 'background-color' : 'gray', 8 | 'padding' : '20px', 9 | 'font-size' : '20px' 10 | }, 11 | 'content' : '[[identity|sizeStr]]' 12 | } 13 | }, 14 | events: { 15 | '#container' : { 16 | 'parent-size-change' : function($event) { 17 | console.log('Parent size change: ', $event); 18 | }, 19 | 'size-change' : function($state, $event) { 20 | var sizeStr = '[ ' + Math.floor($event.value[0]) + ' , ' + Math.floor($event.value[1]) + ' ]'; 21 | $state.set('sizeStr', sizeStr); 22 | } 23 | } 24 | }, 25 | states: {}, 26 | tree: 'size-change-event.html' 27 | }); 28 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/state-interruption/state-interruption.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:state-interruption', { 2 | behaviors: { 3 | '#square': { 4 | 'position': '[[identity]]', 5 | 'size': [100, 100], 6 | 'style': { 7 | 'background': 'whitesmoke' 8 | } 9 | } 10 | }, 11 | events: { 12 | '#square': { 13 | 'click': function($state) { 14 | console.log('clicked!'); 15 | 16 | // The square's position will remain at [0, 0] 17 | // because the second set will override the first 18 | 19 | $state 20 | .set('position', [100, 100], { duration: 1000 }) 21 | .set('position', [0, 0]) 22 | 23 | // If we added a setTimeout instead of the second 24 | // set above, the position of the square will be [0, 0] 25 | // after 500 ms. 26 | 27 | // setTimeout(function() { 28 | // $state.set('position', [0, 0]); 29 | // }, 500); 30 | } 31 | } 32 | }, 33 | states: { 34 | 'position': [0, 0] 35 | }, 36 | tree: ` 37 | 38 | ` 39 | }); 40 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/state-manager-test/state-manager-test.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:state-manager-test', { 2 | behaviors: { 3 | '#element': { 4 | 'position': function(position) { 5 | return position; 6 | }, 7 | 'size': function(size) { 8 | return size; 9 | }, 10 | 'style': function(background) { 11 | return { 12 | 'background': background 13 | } 14 | } 15 | } 16 | }, 17 | events: { 18 | '#element': { 19 | 'click': function($state) { 20 | $state 21 | .set('background', 'purple') 22 | .thenSet('size', [400, 400], { duration: 1000, curve: 'outBack' }) 23 | .thenSet('position', [200, 200], { duration: 1000, curve: 'outBounce' }); 24 | } 25 | } 26 | }, 27 | states: { 28 | background: 'red', 29 | size: [250, 250], 30 | position: [0, 0] 31 | }, 32 | tree: ` 33 | 34 |
      Click Here
      35 |
      36 | ` 37 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/static-assets/assets/excite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-tests/static-assets/assets/excite.png -------------------------------------------------------------------------------- /lib/core-components/famous-tests/static-assets/assets/excite2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-tests/static-assets/assets/excite2.png -------------------------------------------------------------------------------- /lib/core-components/famous-tests/static-assets/more-assets/assets/excite3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-tests/static-assets/more-assets/assets/excite3.png -------------------------------------------------------------------------------- /lib/core-components/famous-tests/static-assets/more-assets/more-assets.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:static-assets:more-assets', { 2 | behaviors: { 3 | 'ui-element' : { 4 | 'content': '' 5 | } 6 | }, 7 | events: { 8 | }, 9 | tree: ` 10 | 11 | `, 12 | }); 13 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/static-assets/static-assets.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:static-assets', { 2 | behaviors: { 3 | '#one-a': { 4 | 'content': '

      You should see several images on this page, showing that assets can be loaded/referenced in a variety of ways

      ' 5 | }, 6 | // Content is defined inside of the tree 7 | '#one-b': { 8 | 'position' : [400, 0] 9 | }, 10 | '#two': { 11 | 'content': function(imageTwoPath) { 12 | // Alternative syntax for inferring asset path name. 13 | // {{BASE_URL}} is a keyword that will be evaluated during compilation 14 | // to match the CDN location where this component is hosted. 15 | return ''; 16 | }, 17 | 'position': [0, 300] 18 | }, 19 | '#three': { 20 | 'content': function(imageThreePath) { 21 | return ''; // TODO 22 | }, 23 | 'position': [0, 600] 24 | }, 25 | '#four': { 26 | 'position': [400, 300] 27 | }, 28 | '#img-four' : { 29 | src: '[[identity|imageFourPath]]' 30 | } 31 | }, 32 | states: { 33 | imageTwoPath: 'assets/excite2.png', 34 | imageThreePath: 'assets/excite3.png', 35 | imageFourPath: '{{BASE_URL}}assets/excite2.png' 36 | }, 37 | tree: ` 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | `, 48 | }); 49 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/timeline-example/timeline-example.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:timeline-example', { 2 | behaviors: { 3 | '#circle': { 4 | 'size': [200, 200], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5], 7 | 'origin': [0.5, 0.5], 8 | 'style': { 9 | 'background': 'whitesmoke', 10 | 'border-radius': '50%', 11 | } 12 | }, 13 | '#play': { 'position': [-100, 250] }, 14 | '#pause': { 'position': [0, 250] }, 15 | '#rewind': { 'position': [100, 250] }, 16 | '.button': { 17 | 'size': [100, 25], 18 | 'align': [0.5, 0.5], 19 | 'mount-point': [0.5, 0.5], 20 | 'style': { 21 | 'background': 'whitesmoke', 22 | 'color': '#222', 23 | 'font-size': '20px', 24 | 'font-weight': 'bold', 25 | 'line-height': '1.2', 26 | 'text-align': 'center', 27 | 'cursor': 'pointer', 28 | 'font-family': 'Lato' 29 | } 30 | } 31 | }, 32 | events: { 33 | '#play': { 34 | 'click': function($timelines) { 35 | $timelines.get('scale-animation').start({ duration: 2000 }); 36 | } 37 | }, 38 | '#pause': { 39 | 'click': function($timelines) { 40 | var scaleTimeline = $timelines.get('scale-animation'); 41 | 42 | if (scaleTimeline.isPaused()) scaleTimeline.resume(); 43 | else scaleTimeline.halt(); 44 | } 45 | }, 46 | '#rewind': { 47 | 'click': function($timelines) { 48 | $timelines.get('scale-animation').rewind(); 49 | } 50 | } 51 | }, 52 | states: {}, 53 | tree: ` 54 | 55 | 56 |
      Play
      57 |
      Pause
      58 |
      Rewind
      59 | ` 60 | }) 61 | .timelines({ 62 | 'scale-animation': { 63 | '#circle': { 64 | 'scale': { 65 | '0%': { value: [1.0, 1.0], curve: 'outBack' }, 66 | '50%': { value: [2.0, 2.0], curve: 'outBack' }, 67 | '100%': { value: [1.0, 1.0], curve: 'outBack' } 68 | }, 69 | 'position': { 70 | '0%': { value: [0, 0], curve: 'outBack' }, 71 | '50%': { value: [0, -200], curve: 'outBack' }, 72 | '100%': { value: [0, 0], curve: 'outBack' } 73 | } 74 | } 75 | } 76 | }) 77 | ; -------------------------------------------------------------------------------- /lib/core-components/famous-tests/timeline/top-level-function/top-level-function.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:timeline:top-level-function', { 2 | behaviors: { 3 | '#square': { 4 | 'align': [0.5, 0.5], 5 | 'origin': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5], 7 | 'style': function() { 8 | return { 9 | 'background-color': 'red', 10 | } 11 | } 12 | } 13 | }, 14 | events: { 15 | '$lifecycle': { 16 | 'post-load': function($timelines) { 17 | $timelines.get('intro').start({ duration: 3000 }); 18 | } 19 | }, 20 | '#square': { 21 | 'click': function($timelines) { 22 | $timelines.get('spinAround').start({ duration: 1000 }); 23 | } 24 | } 25 | }, 26 | states: {}, 27 | tree: ` 28 | Click here! 29 | ` 30 | }) 31 | .timelines({ 32 | 'intro': { 33 | '#square': { 34 | 'size': { 35 | '0%': { value: [200, 200], curve: 'easeInOut' }, 36 | '50%': { value: [400, 400], curve: 'easeInOut' }, 37 | '100%': { value: [200, 200] } 38 | }, 39 | 'position': { 40 | '0%': { value: [0, 0], curve: 'outBounce' }, 41 | '40%': { value: [-200, -200], curve: 'outBounce' }, 42 | '80%': { value: [200, 200], curve: 'outBounce' }, 43 | '100%': { value: [0, 0] } 44 | }, 45 | 'rotation-z': { 46 | '0%': { value: 0, curve: 'easeInOut' }, 47 | '50%': { value: Math.PI/2, curve: 'easeInOut' }, 48 | '100%': { value: Math.PI*4 } 49 | } 50 | } 51 | }, 52 | 'spinAround': { 53 | '#square': { 54 | 'rotation-z': { 55 | '0%': { value: 0, curve: 'easeInOut' }, 56 | '50%': { value: Math.PI/2, curve: 'easeInOut' }, 57 | '100%': { value: Math.PI*4 } 58 | } 59 | } 60 | } 61 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/webgl/basic/geometry/geometry.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:webgl:basic:geometry', { 2 | behaviors: { 3 | '.sphere': { 4 | 'size': [200, 200], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5], 7 | 'base-color': 'whitesmoke', 8 | 'geometry': { 9 | 'shape': 'GeodesicSphere', 10 | 'options': { 11 | 'detail': 3 12 | } 13 | }, 14 | 'light': { 15 | 'type': 'point', 16 | 'color': 'blue' 17 | } 18 | }, 19 | '.light': { 20 | 'size': [200, 200], 21 | 'align': [0.5, 0.5], 22 | 'mount-point': [0.5, 0.5], 23 | 'position-z': 50, 24 | 'light': { 25 | 'type': 'point', 26 | 'color': 'red' 27 | } 28 | }, 29 | '.background': { 30 | 'size': [undefined, undefined], 31 | 'align': [0.5, 0.5], 32 | 'mount-point': [0.5, 0.5], 33 | 'geometry': { 34 | 'shape': 'Plane' 35 | } 36 | } 37 | }, 38 | events: {}, 39 | states: {}, 40 | tree: ` 41 | 42 | 43 | 44 | ` 45 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/webgl/custom-shader/fragment/fragment.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:webgl:custom-shader:fragment', { 2 | behaviors: { 3 | '.sphere': { 4 | 'size': [200, 200], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5], 7 | 'base-color': { 8 | 'name': 'sphereFragment', 9 | 'glsl': 'vec4((v_normal + 1.0) * 0.5, 1.0);', 10 | 'output': 4, 11 | }, 12 | 'geometry': { 13 | 'shape': 'GeodesicSphere', 14 | 'options': { 15 | 'detail': 3 16 | } 17 | } 18 | }, 19 | '.light': { 20 | 'size': [200, 200], 21 | 'align': [0.5, 0.5], 22 | 'mount-point': [0.5, 0.5], 23 | 'position-z': 500, 24 | 'light': { 25 | 'type': 'point', 26 | 'color': 'white' 27 | } 28 | }, 29 | '.background': { 30 | 'size': [undefined, undefined], 31 | 'align': [0.5, 0.5], 32 | 'mount-point': [0.5, 0.5], 33 | 'geometry': { 34 | 'shape': 'Plane' 35 | } 36 | } 37 | }, 38 | events: {}, 39 | states: {}, 40 | tree: ` 41 | 42 | 43 | 44 | ` 45 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/webgl/custom-shader/vertex/vertex.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:webgl:custom-shader:vertex', { 2 | behaviors: { 3 | '$camera': { 4 | 'depth': 1000 5 | }, 6 | '.sphere': { 7 | 'size': [200, 200], 8 | 'align': [0.5, 0.5], 9 | 'origin': [0.5, 0.5], 10 | 'mount-point': [0.5, 0.5], 11 | 'base-color': 'whitesmoke', 12 | 'geometry': { 13 | 'shape': 'GeodesicSphere', 14 | 'dynamic': true, 15 | 'options': { 16 | 'detail': 3 17 | } 18 | }, 19 | 'position-offset': { 20 | 'name': 'sphereVertex', 21 | 'glsl': 'vec3(v_normal * 3.0);', 22 | 'output': 3 23 | } 24 | }, 25 | '.light': { 26 | 'size': [200, 200], 27 | 'align': [0.5, 0.5], 28 | 'mount-point': [0.5, 0.5], 29 | 'position-z': 500, 30 | 'light': { 31 | 'type': 'point', 32 | 'color': 'white' 33 | } 34 | }, 35 | '.background': { 36 | 'size': [undefined, undefined], 37 | 'align': [0.5, 0.5], 38 | 'mount-point': [0.5, 0.5], 39 | 'geometry': { 40 | 'shape': 'Plane' 41 | } 42 | } 43 | }, 44 | events: {}, 45 | states: {}, 46 | tree: ` 47 | 48 | 49 | 50 | ` 51 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/webgl/glsl-state/uniform/uniform.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous-tests:webgl:glsl-state:uniform', { 2 | behaviors: { 3 | '.sphere': { 4 | 'size': [200, 200], 5 | 'align': [0.5, 0.5], 6 | 'mount-point': [0.5, 0.5], 7 | 'geometry': { 8 | 'shape': 'GeodesicSphere', 9 | 'options': { 10 | 'detail': 3 11 | } 12 | }, 13 | 'position-offset': { 14 | 'name': 'sphereVertex', 15 | 'glsl': 'vec3(v_normal * (u_Offset * 5.0));', 16 | 'output': 3, 17 | 'defaults': { 18 | 'uniforms': { 19 | 'u_Offset': 1 20 | } 21 | } 22 | }, 23 | 'base-color': { 24 | 'name': 'sphereFragment', 25 | 'glsl': 'vec4((v_normal + u_Offset / 2.0) * 0.5, 1.0);', 26 | 'output': 4, 27 | }, 28 | 'uniform': function(offset) { 29 | return { 30 | 'vertexName': 'sphereVertex', 31 | 'variableName': 'u_Offset', 32 | 'value': offset 33 | } 34 | } 35 | } 36 | }, 37 | events: { 38 | '$self': { 39 | 'click': function($state) { 40 | $state 41 | .set('offset', 2.0, { duration: 800, curve: 'outBack' }) 42 | .thenSet('offset', 0.0, { duration: 600, curve: 'outBack' }); 43 | } 44 | } 45 | }, 46 | states: { 47 | 'offset': 0.0 48 | }, 49 | tree: ` 50 | 51 | ` 52 | }); -------------------------------------------------------------------------------- /lib/core-components/famous-tests/weird-files/.foo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-tests/weird-files/.foo -------------------------------------------------------------------------------- /lib/core-components/famous-tests/weird-files/.something~~/.asfdasdfasfdaf: -------------------------------------------------------------------------------- 1 | asdfasdf -------------------------------------------------------------------------------- /lib/core-components/famous-tests/weird-files/.xyz.mucho: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Famous/framework/c83a13c90ab727dbb6c40a32171d73988fad608d/lib/core-components/famous-tests/weird-files/.xyz.mucho -------------------------------------------------------------------------------- /lib/core-components/famous-tests/weird-files/bar: -------------------------------------------------------------------------------- 1 | dsfsdf -------------------------------------------------------------------------------- /lib/core-components/famous-tests/weird-files/main.jsx: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/core-components/famous-tests/weird-files/weird-files.js: -------------------------------------------------------------------------------- 1 | function foo(){} 2 | FamousFramework.scene('famous-tests:weird-files', { 3 | tree: ` 4 |

      5 | Nothing visible should be on this page (except this message). 6 | This is just to show that a module that has a lot of 'weird' 7 | files (like dotfiles, etc.) compiles successfully. 8 |

      9 | ` 10 | }); 11 | /////HELLO 12 | /// 13 | /// 14 | /// 15 | ///sdf -------------------------------------------------------------------------------- /lib/core-components/famous/adapter/google-finance/google-finance.js: -------------------------------------------------------------------------------- 1 | var API_URL = "http://finance.google.com/finance/info?client=ig&q={tickers}"; 2 | 3 | /** 4 | * A service component used to connect to the Google finance api. 5 | * It leverages the justinsmith:service:http service component to make the web requests. 6 | */ 7 | FamousFramework.scene('famous:adapter:google-finance', { 8 | 9 | behaviors: { 10 | 11 | 'famous:service:http': { 12 | 13 | 'url': API_URL, 14 | 'parse-json': false, 15 | 16 | 'request': function(tickers) { 17 | 18 | //create the request whenever tickers are updated using 19 | //url parameters + token since the url is defined above 20 | return { 21 | 22 | //i'm not actually checking the token in the response, 23 | //but i put it in here anyways to show usage 24 | 'token': "googlefinance-" + Math.random(), 25 | 26 | 'parameters': { 27 | 'tickers':tickers.join(',') 28 | } 29 | }; 30 | } 31 | } 32 | }, 33 | 34 | events: { 35 | 36 | 'famous:service:http': { 37 | 38 | 'response': function($payload, $event, $dispatcher) { 39 | 40 | $event.stopPropagation(); 41 | 42 | var response = $payload.response; 43 | 44 | try { 45 | //need to do some funny business cuz Google adds some comments to the result??? 46 | //not sure why...but just parse it out 47 | var data = JSON.parse(response.data.substring(3)); 48 | 49 | if(data.cod && data.message) { 50 | $dispatcher.emit("error", data.message); 51 | return; 52 | } 53 | 54 | //send the response event with our parsed data 55 | $dispatcher.emit("response", data); 56 | } 57 | catch(ee) { 58 | $dispatcher.emit("error", ee); 59 | } 60 | }, 61 | 62 | 'error': function($payload, $dispatcher) { 63 | console.warn("Error: ", $payload); 64 | $dispatcher.emit("error", $payload); 65 | } 66 | }, 67 | 68 | '$public': { 69 | 70 | 'query': function($dispatcher, $state, $payload) { 71 | 72 | //dont' do anything if a null query was made 73 | if(!$payload) { 74 | return; 75 | } 76 | 77 | //otherwise set our tickers 78 | $state.set("tickers", $payload); 79 | } 80 | } 81 | }, 82 | 83 | tree: '' 84 | }); 85 | -------------------------------------------------------------------------------- /lib/core-components/famous/layouts/flexible/flexible.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous:layouts:flexible', { 2 | behaviors: { 3 | '$self' : { 4 | 'direction' : '[[identity]]', 5 | 'ratios' : '[[identity]]', 6 | 'transition' : '[[identity]]' 7 | }, 8 | '.flexible-layout': { 9 | // HACK: force creating a layout wrapper container 10 | 'style': {} 11 | }, 12 | '.flexible-layout-item': { 13 | '$yield': true 14 | } 15 | }, 16 | events: { 17 | '$public': { 18 | 'direction': '[[setter]]', 19 | 'ratios': '[[setter]]', 20 | 'transition': '[[setter]]', 21 | 'update-layout': ($famousNode) => { 22 | $famousNode.updateLayout(); 23 | } 24 | }, 25 | '$private' : { 26 | 'direction': ($famousNode, $payload) => { 27 | if ($payload === 0) { 28 | $famousNode.direction = FlexibleLayout.Direction.X; 29 | } else if ($payload === 1) { 30 | $famousNode.direction = FlexibleLayout.Direction.Y; 31 | } else if ($payload === 2) { 32 | $famousNode.direction = FlexibleLayout.Direction.Z; 33 | } 34 | }, 35 | 'ratios': ($famousNode, $payload) => { 36 | $famousNode.ratios = $payload; 37 | }, 38 | 'transition': ($famousNode, $payload) => { 39 | $famousNode.transition = $payload; 40 | } 41 | } 42 | }, 43 | states: { 44 | direction: 0, 45 | ratios: [], 46 | transition: null 47 | }, 48 | tree: ` 49 | 50 | 51 | 52 | ` 53 | }).config({ 54 | famousNodeConstructorName: 'FlexibleLayout', 55 | includes: ['_constructor.js'] 56 | }); 57 | -------------------------------------------------------------------------------- /lib/core-components/famous/layouts/header-footer/header-footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /lib/core-components/famous/layouts/header-footer/header-footer.js: -------------------------------------------------------------------------------- 1 | FamousFramework.module('famous:layouts:header-footer', { 2 | tree: 'header-footer.html', 3 | behaviors: { 4 | '#header' : { 5 | /* 6 | $yield is a special type of "control-flow behavior". It is at the core of 7 | what enables components in the Famous Framework to be composable. Setting $yield 8 | on a component tells the system that it is ok for a parent component to inject 9 | components inside of a child component. Values for $yield are either a boolean, 10 | which signifies that the parent component can add any component into the child, 11 | or a String, which signifies that the parent component can add components into 12 | the child if those components match the CSS selector given by String. 13 | 14 | In this example, the parent can include the header-footer component and inject 15 | its own content into the header/body/footer nodes like so: 16 | header-footer 17 | a#header 18 | b#body 19 | c#footer 20 | 21 | Component `a` will end up being slotted into the 'header' nodes, and as such will 22 | be sized according to the behavior specified bellow. 23 | */ 24 | '$yield' : '#header', 25 | 'size-absolute-y' : '[[identity|headerHeight]]' 26 | }, 27 | '#body' : { 28 | '$yield' : '#body', 29 | 'position' : function(headerHeight) { 30 | return [0, headerHeight] 31 | }, 32 | 'size-differential-y' : function(headerHeight, footerHeight) { 33 | return -headerHeight - footerHeight; 34 | } 35 | }, 36 | '#footer' : { 37 | '$yield' : '#footer', 38 | 'size-absolute-y' : function(footerHeight) { 39 | return footerHeight; 40 | }, 41 | 'position-y': function(footerHeight) { 42 | return -footerHeight; 43 | }, 44 | align: [0, 1], 45 | } 46 | }, 47 | events: { 48 | '$public' : { 49 | 'header-height' : '[[setter|headerHeight]]', 50 | 'footer-height' : '[[setter|footerHeight]]' 51 | } 52 | }, 53 | states: { 54 | 'headerHeight' : 100, 55 | 'footerHeight' : 100 56 | } 57 | }); 58 | -------------------------------------------------------------------------------- /lib/core-components/famous/layouts/scroll-view/scroll-view.js: -------------------------------------------------------------------------------- 1 | FamousFramework.scene('famous:layouts:scroll-view', { 2 | behaviors: { 3 | '$self': { 4 | position: '[[identity|scrollViewPosition]]', 5 | size: '[[identity|scrollViewSize]]', 6 | style: function(border) { 7 | var style = {}; 8 | style.overflow = 'scroll'; 9 | if (border) style.border = border; 10 | return style; 11 | } 12 | }, 13 | '.item' : { 14 | '$yield' : '.scroll-view-item', 15 | 'size' : function(itemHeight) { 16 | return [undefined, itemHeight]; 17 | }, 18 | 'position' : function($index, itemHeight) { 19 | return [0, $index * itemHeight]; 20 | } 21 | } 22 | }, 23 | events: { 24 | $public: { 25 | 'item-height' : '[[setter|itemHeight]]', 26 | 'scroll-view-position' : '[[setter|scrollViewPosition]]', 27 | 'scroll-view-size' : '[[setter|scrollViewSize]]', 28 | } 29 | }, 30 | states: { 31 | itemHeight: 100, 32 | scrollViewSize: [400, 800], 33 | scrollViewPosition: [0, 0], 34 | border: '3px solid #40b2e8' 35 | }, 36 | tree: ` 37 | 38 | ` 39 | }); 40 | -------------------------------------------------------------------------------- /lib/core-components/famous/layouts/sequential/sequential.js: -------------------------------------------------------------------------------- 1 | FamousFramework.component('famous:layouts:sequential', { 2 | behaviors: { 3 | '$self' : { 4 | 'direction' : '[[identity]]', 5 | 'transition' : '[[identity]]' 6 | }, 7 | '.sequential-layout': { 8 | // HACK: force creating a layout wrapper container 9 | 'style': {} 10 | }, 11 | '.sequential-layout-item': { 12 | '$yield': true 13 | } 14 | }, 15 | events: { 16 | '$public': { 17 | 'direction': '[[setter]]', 18 | 'transition': '[[setter]]', 19 | 'update-layout': ($famousNode) => { 20 | $famousNode.updateLayout(); 21 | } 22 | }, 23 | '$private' : { 24 | 'direction': ($famousNode, $payload) => { 25 | if ($payload === 0) { 26 | $famousNode.direction = SequentialLayout.Direction.X; 27 | } else if ($payload === 1) { 28 | $famousNode.direction = SequentialLayout.Direction.Y; 29 | } else if ($payload === 2) { 30 | $famousNode.direction = SequentialLayout.Direction.Z; 31 | } 32 | }, 33 | 'transition': ($famousNode, $payload) => { 34 | $famousNode.transition = $payload; 35 | } 36 | } 37 | }, 38 | states: { 39 | direction: 0, 40 | transition: null 41 | }, 42 | tree: ` 43 | 44 | 45 | 46 | ` 47 | }).config({ 48 | famousNodeConstructorName: 'SequentialLayout', 49 | includes: ['_constructor.js'] 50 | }); 51 | -------------------------------------------------------------------------------- /lib/core-components/famous/service/location/location.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The amount of time (in milliseconds) to wait 3 | * for the browser to return geo coordinates of 4 | * 5 | * the user's location. 6 | * @type {number} 7 | */ 8 | var TIMEOUT = 10000; 9 | 10 | /** 11 | * A service component used to get the users 12 | * geographic location from the browser. 13 | * Originally justinsmith:service:location, moved into core. 14 | */ 15 | FamousFramework.component('famous:service:location', { 16 | 17 | events: { 18 | 19 | '$lifecycle': { 20 | 21 | /** 22 | * Trigger the location-requested event on load. 23 | * 24 | * @param $dispatcher The event dispatcher 25 | */ 26 | 'post-load': function($dispatcher) { 27 | $dispatcher.trigger("location-requested"); 28 | } 29 | }, 30 | 31 | '$public': { 32 | 33 | /** 34 | * Requests the geographic location from the browser (if supported). 35 | * If the browser doesn't respond within 10 seconds, an error event 36 | * is dispatched. 37 | * 38 | * @param $state 39 | * @param $dispatcher 40 | */ 41 | 'location-requested': function($state, $dispatcher) { 42 | 43 | //quick exit if the browser doesn't support geolocation 44 | if(!navigator.geolocation) { 45 | var message = "Geolocation is not supported by this browser." 46 | console.warn(message); 47 | $dispatcher.emit("error", message); 48 | return 49 | } 50 | 51 | //timeout after 10 seconds 52 | //TODO: maybe make this configurable??? 53 | 54 | var isTimedOut = false; 55 | var timeout = setTimeout(function() { 56 | isTimedOut = true; 57 | $dispatcher.emit("error", "Geolocation request timed out or permission was not granted."); 58 | }, TIMEOUT); 59 | 60 | /** 61 | * The callback handler for the geolocation api. 62 | * 63 | * @param position The geographic position of the user's browser. 64 | */ 65 | function callback(position) { 66 | 67 | clearTimeout(timeout); 68 | 69 | //if the callback actually DOES return 70 | //but we've exceeded the timeout, ignore the result. 71 | if(isTimedOut) { 72 | return; 73 | } 74 | 75 | //save our data and dispatch an event 76 | $state.set("location", position.coords); 77 | $dispatcher.emit("location", position.coords); 78 | }; 79 | 80 | //call the geolocation api 81 | navigator.geolocation.getCurrentPosition(callback); 82 | } 83 | } 84 | }, 85 | 86 | //TODO: if all I'm doing is just emitting events, do i really NEED the state? 87 | //TODO: probably not, but leaving it in here anyways 88 | states: { 89 | location: null 90 | } 91 | }); 92 | -------------------------------------------------------------------------------- /lib/core-components/famous/service/timer/timer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Workaround due to the inability to save 3 | * the interval timer function as a state. 4 | * 5 | * It's a map because anything in this space is defacto singleton. 6 | */ 7 | var intervalMap = {}; 8 | 9 | /** 10 | * A service component used to periodically fire a 'time' event. 11 | * To use, include in your tree and set the 'period' behavior 12 | * to a numerical (milliseconds) value. 13 | * Originally justinsmith:service:timer, moved into core. 14 | */ 15 | FamousFramework.component('famous:service:timer', { 16 | 17 | events: { 18 | 19 | '$public': { 20 | 21 | /** 22 | * The interval period in milliseconds. 23 | * 24 | * @param $payload The period in milliseconds 25 | * @param $state The state manager. 26 | * @param $dispatcher The event dispatcher 27 | * @param $famousNode A reference to the Node this component belongs to. 28 | */ 29 | 'period': function($payload, $state, $dispatcher, $famousNode) { 30 | 31 | //save our period state 32 | var period = $payload; 33 | $state.set("period", period); 34 | 35 | //get a reference to the famous engine clock 36 | var clock = FamousFramework.FamousEngine.core.FamousEngine.getClock(); 37 | var nodeId = $famousNode.getId(); 38 | 39 | //reset the timer interval for this component (if it exists) 40 | if(intervalMap.hasOwnProperty(nodeId)) { 41 | clock.clearTimer(intervalMap[nodeId]); 42 | } 43 | 44 | //create an interval to periodically 45 | //trigger a 'time' event 46 | intervalMap[nodeId] = clock.setInterval(function() { 47 | 48 | //set the new time 49 | var time = new Date().getTime(); 50 | $state.set("time", time); 51 | $dispatcher.emit("tick", time); 52 | 53 | }, period); 54 | } 55 | } 56 | }, 57 | 58 | states: { 59 | 60 | /** 61 | * Default timer update period 100 milliseconds 62 | */ 63 | period: 100 64 | } 65 | }); 66 | -------------------------------------------------------------------------------- /lib/core-components/famous/ui/config-panel/assets/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /lib/events/injector.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var FamousConnector = require('./../famous-connector/famous-connector'); 4 | var DataStore = require('./../data-store/data-store'); 5 | 6 | var PAYLOAD_KEY = '$payload'; 7 | var STATE_MANAGER_KEY = '$state'; 8 | var TIMELINES_KEY = '$timelines'; 9 | var FRAMEWORK_COMPONENT_KEY = '$component'; 10 | var FAMOUS_NODE_KEY = '$famousNode'; 11 | var FRAMEWORK_DOM_NODE_KEY = '$domNode'; 12 | var DISPATCHER_KEY = '$dispatcher'; 13 | var DOM_ELEMENT_KEY = '$DOMElement'; 14 | var MESH_KEY = '$mesh'; 15 | var INDEX_KEY = '$index'; 16 | var REPEAT_PAYLOAD_KEY = '$repeatPayload'; 17 | var ROUTE_KEY = '$route'; 18 | var EVENT_KEY = '$event'; 19 | var GESTURE_HANDLER_KEY = '$GestureHandler'; 20 | 21 | function getArgs(paramNames, payload, uid) { 22 | var component = DataStore.getComponent(uid); 23 | var args = []; 24 | for (var i = 0; i < paramNames.length; i++) { 25 | switch (paramNames[i]) { 26 | case PAYLOAD_KEY: args.push(payload); break; 27 | case FRAMEWORK_COMPONENT_KEY: args.push(component); break; 28 | case FAMOUS_NODE_KEY: args.push(component.famousNode); break; 29 | case FRAMEWORK_DOM_NODE_KEY: args.push(component.tree.getRootNode()); break; 30 | case STATE_MANAGER_KEY: args.push(component.states.getStateManager()); break; 31 | case TIMELINES_KEY: args.push(component.timelines); break; 32 | case DISPATCHER_KEY: args.push(component.events.dispatcher); break; 33 | case INDEX_KEY: args.push(component.states.get(INDEX_KEY)); break; 34 | case REPEAT_PAYLOAD_KEY: args.push(component.states.get(REPEAT_PAYLOAD_KEY)); break; 35 | case ROUTE_KEY: args.push(component.states.get(ROUTE_KEY)); break; 36 | case DOM_ELEMENT_KEY: args.push(FamousConnector.decorateComponent(component, 'DOMElement')); break; 37 | case MESH_KEY: args.push(FamousConnector.decorateComponent(component, 'Mesh')); break; 38 | case EVENT_KEY: args.push(null); break; // `$event` gets overwritten with event object if one exists 39 | case GESTURE_HANDLER_KEY: args.push(FamousConnector.GestureHandler); break; 40 | default: 41 | throw new Error('No such object `' + paramNames[i] + '`'); 42 | } 43 | } 44 | return args; 45 | } 46 | 47 | module.exports = { 48 | getArgs: getArgs 49 | }; 50 | -------------------------------------------------------------------------------- /lib/helpers/helpers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var piecewise = require('./piecewise'); 4 | var clone = require('./../utilities/object').clone; 5 | 6 | function formatStyle(styleObj) { 7 | var styleStr = ''; 8 | for (var name in styleObj) { 9 | styleStr += name + ':' + styleObj[name] + '; '; 10 | } 11 | return styleStr; 12 | } 13 | 14 | module.exports = { 15 | piecewise: piecewise, 16 | clone: clone, 17 | formatStyle: formatStyle 18 | }; 19 | -------------------------------------------------------------------------------- /lib/helpers/piecewise.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var FamousConnector = require('./../famous-connector/famous-connector'); 4 | var Curves = FamousConnector.Curves; 5 | 6 | var linear = function(x) { 7 | return x; 8 | }; 9 | 10 | var ADD = 'ADD'; 11 | var SUBTRACT = 'SUBTRACT'; 12 | var MULTIPLY = 'MULTIPLY'; 13 | 14 | var operations = { 15 | ADD: function(a, b) { 16 | return a + b; 17 | }, 18 | SUBTRACT: function(a, b) { 19 | return a - b; 20 | }, 21 | MULTIPLY: function(a, b) { 22 | return a * b; 23 | } 24 | }; 25 | 26 | function polymorphicOperation(operationName, a, b) { 27 | if (typeof a === 'number') { 28 | return operations[operationName](a, b); 29 | } 30 | else { 31 | var isArray = Array.isArray(b); 32 | return a.map(function(value, i) { 33 | return operations[operationName](value, isArray ? b[i] : b); 34 | }); 35 | } 36 | } 37 | 38 | function scale(time, easingCurve, t1, t2, v1, v2) { 39 | var standardizedTime = (time - t1) / (t2 - t1); // value from 0 to 1 40 | var timeScale = easingCurve(standardizedTime); // adjusted with easing curve 41 | 42 | var valueSpan = polymorphicOperation(SUBTRACT, v2, v1); 43 | var valueProgess = polymorphicOperation(MULTIPLY, valueSpan, timeScale); 44 | var value = polymorphicOperation(ADD, valueProgess, v1); 45 | return value; 46 | } 47 | 48 | // Store timeline by UID 49 | var timelines = {}; 50 | 51 | function piecewise(points) { 52 | var timelineUID = JSON.stringify(points); 53 | 54 | if (timelines[timelineUID]) { 55 | return timelines[timelineUID]; 56 | } 57 | else { 58 | timelines[timelineUID] = function(t) { 59 | if (t <= points[0][0]) { 60 | return points[0][1]; 61 | } 62 | else { 63 | for (var i = 0; i < points.length - 1; i++) { 64 | if (points[i][0] <= t && t < points[i + 1][0]) { 65 | return scale( 66 | t, 67 | Curves[points[i][2]] || linear, 68 | points[i][0], 69 | points[i + 1][0], 70 | points[i][1], 71 | points[i + 1][1] 72 | ); 73 | } 74 | } 75 | } 76 | return points[points.length - 1][1]; 77 | }; 78 | return timelines[timelineUID]; 79 | } 80 | } 81 | 82 | module.exports = piecewise; 83 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('./polyfills/custom-event'); 4 | 5 | var DataStore = require('./data-store/data-store'); 6 | var Deployer = require('./deployer/deployer'); 7 | var helpers = require('./helpers/helpers'); 8 | var Messenger = require('./messenger/messenger'); 9 | 10 | var deployer = new Deployer(); 11 | 12 | function register(name, tag, options, definition) { 13 | return DataStore.registerModule(name, tag, options, definition); 14 | } 15 | 16 | module.exports = { 17 | attach: deployer.attach.bind(deployer), 18 | component: register, // alias for 'register' 19 | deploy: deployer.deploy.bind(deployer), 20 | execute: deployer.execute.bind(deployer), 21 | FamousEngine: require('./famous-connector/famous-connector').FamousEngine, 22 | getComponentByUID: DataStore.getComponent, 23 | helpers: helpers, 24 | includes: deployer.includes.bind(deployer), 25 | markComponentAsReady: deployer.markComponentAsReady.bind(deployer), 26 | message: Messenger.message, 27 | module: register, // alias for 'register' 28 | register: register, 29 | registerCustomFamousNodeConstructors: DataStore.registerCustomFamousNodeConstructors, 30 | scene: register // alias for 'register' 31 | }; 32 | -------------------------------------------------------------------------------- /lib/logger/logger.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var MAP = { 4 | 2: 'INFO', 5 | 1: 'WARN', 6 | 0: 'FAIL' 7 | }; 8 | 9 | var LOG_LEVEL = 0; 10 | 11 | var LOG = {}; 12 | LOG[MAP[0]] = []; 13 | LOG[MAP[1]] = []; 14 | LOG[MAP[2]] = []; 15 | LOG.ALL = []; 16 | 17 | function log(msg, level) { 18 | if (level <= LOG_LEVEL) { 19 | if (level === 0) { 20 | console.error(msg); 21 | } 22 | else if (level === 1) { 23 | console.warn(msg); 24 | } 25 | else { 26 | console.log(msg); 27 | } 28 | } 29 | 30 | var info = { 31 | message: msg, 32 | timestamp: Date.now() 33 | }; 34 | 35 | LOG.ALL.push(info); 36 | LOG[MAP[level]].push(info); 37 | } 38 | 39 | function setLevel(level) { 40 | if (level < 0 || level > 2) { 41 | throw new Error('Log level must be set to an integer between 0 and 2'); 42 | } 43 | LOG_LEVEL = level; 44 | } 45 | 46 | function getLevel() { 47 | return LOG_LEVEL; 48 | } 49 | 50 | function getLog() { 51 | return LOG; 52 | } 53 | 54 | 55 | module.exports = { 56 | log: log, 57 | getLog: getLog, 58 | setLevel: setLevel, 59 | getLevel: getLevel 60 | }; 61 | -------------------------------------------------------------------------------- /lib/messenger/messenger.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var VirtualDOM = require('./../virtual-dom/virtual-dom'); 4 | var DataStore = require('./../data-store/data-store'); 5 | 6 | var ROOT_SELECTOR = '$root'; 7 | 8 | function message(domSelector, componentSelector, key, value) { 9 | var rootComponent = DataStore.getExecutedComponent(domSelector); 10 | var targetComponent; 11 | if (componentSelector === ROOT_SELECTOR) { 12 | targetComponent = rootComponent; 13 | targetComponent.sendMessage(key, value); 14 | } 15 | else { 16 | var targets = VirtualDOM.query(rootComponent.getRootNode(), componentSelector); 17 | for (var i = 0; i < targets.length; i++) { 18 | targetComponent = DataStore.getComponent(VirtualDOM.getUID(targets[i])); 19 | targetComponent.sendMessage(key, value); 20 | } 21 | } 22 | } 23 | 24 | module.exports = { 25 | message: message 26 | }; 27 | -------------------------------------------------------------------------------- /lib/polyfills/custom-event.js: -------------------------------------------------------------------------------- 1 | var CustomEvent = function(event, params) { 2 | var evt; 3 | 4 | params = params || { 5 | bubbles: false, 6 | cancelable: false, 7 | detail: undefined 8 | }; 9 | 10 | evt = document.createEvent("CustomEvent"); 11 | evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 12 | 13 | return evt; 14 | }; 15 | 16 | CustomEvent.prototype = window.Event.prototype; 17 | 18 | window.CustomEvent = CustomEvent; 19 | -------------------------------------------------------------------------------- /lib/state-manager/operator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function handleArrayInput (operator, a, b) { 4 | if (Array.isArray(b)) { 5 | for (var i = 0; i < b.length; i++) { 6 | if (b === a.length) return undefined; 7 | a[i] = operations[operator](a[i], b[i]); 8 | } 9 | } 10 | else { 11 | for (var j = 0; j < a.length; j++) { 12 | a[j] = operations[operator](a[j], b); 13 | } 14 | } 15 | 16 | return a; 17 | } 18 | 19 | // Check for number/string/array 20 | function isTypeValid(input) { 21 | return !isNaN(input) || typeof(input) === 'string' || Array.isArray(input); 22 | } 23 | 24 | // Convenient state operators. 25 | var operations = { 26 | '+': function(a, b) { 27 | return a + b; 28 | }, 29 | '-': function(a, b) { 30 | return a - b; 31 | }, 32 | '*': function(a, b) { 33 | return a * b; 34 | }, 35 | '/': function(a, b) { 36 | return a / b; 37 | }, 38 | 'pow': function(a, b) { 39 | return Math.pow(a, b); 40 | }, 41 | 'sqrt': function(a) { 42 | return Math.sqrt(a); 43 | }, 44 | 'abs': function(a) { 45 | return Math.abs(a); 46 | }, 47 | 'sin': function(a) { 48 | return Math.sin(a); 49 | }, 50 | 'cos': function(a) { 51 | return Math.cos(a); 52 | }, 53 | 'tan': function(a) { 54 | return Math.tan(a); 55 | }, 56 | 'ceil': function(a) { 57 | return Math.ceil(a); 58 | }, 59 | 'floor': function(a) { 60 | return Math.floor(a); 61 | }, 62 | 'concat': function(a, b) { 63 | return a.concat(b); 64 | }, 65 | 'substring': function(a, b) { 66 | return a.substring(b[0], b[1]); 67 | }, 68 | 'toLower': function(a) { 69 | return a.toLowerCase(); 70 | }, 71 | 'toUpper': function(a) { 72 | return a.toUpperCase(); 73 | }, 74 | 'flip': function(a) { 75 | return !a; 76 | }, 77 | 'toInt': function(a) { 78 | return a ? 1 : 0; 79 | } 80 | }; 81 | 82 | module.exports = { 83 | operate: function(operator, currentValue, newValue) { 84 | if (newValue) { 85 | if (!(isTypeValid(currentValue) && isTypeValid(newValue))) { 86 | console.warn(' or is not a valid input type'); 87 | throw new Error('Invalid input'); 88 | } 89 | else if (!Array.isArray(currentValue) && Array.isArray(newValue)) { 90 | if (typeof(currentValue) !== 'string') { // special case for 'substring' operation 91 | console.warn('An array can not be used as input to operate on a non-array'); 92 | throw new Error('Invalid input'); 93 | } 94 | } 95 | } 96 | 97 | if (Array.isArray(currentValue)) { 98 | return handleArrayInput(operator, currentValue, newValue); 99 | } 100 | else { 101 | return operations[operator](currentValue, newValue); 102 | } 103 | }, 104 | addOperation: function(name, func) { 105 | operations[name] = func; 106 | } 107 | }; 108 | 109 | 110 | -------------------------------------------------------------------------------- /lib/states/states.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var EventHandler = require('./../utilities/event-handler'); 4 | var FamousConnector = require('./../famous-connector/famous-connector'); 5 | var StateManager = require('./../state-manager/state-manager'); 6 | 7 | var STATE_AUTOTRIGGER_RE = /^[a-zA-Z0-9$].*/i; 8 | 9 | function States(famousNode, initialState) { 10 | EventHandler.apply(this); 11 | var Transitionable = FamousConnector.Transitionable; 12 | this.stateManager = new StateManager(initialState, famousNode, Transitionable); 13 | } 14 | 15 | States.prototype = Object.create(EventHandler.prototype); 16 | States.prototype.constructor = States; 17 | 18 | States.prototype.handleStateChange = function handleStateChange(behaviorDefinition) { 19 | this.emit('behavior-update', behaviorDefinition); 20 | }; 21 | 22 | States.prototype.createBehaviorListener = function createBehaviorListener(behaviorDefinition) { 23 | var params = behaviorDefinition.params; 24 | if (!params || params.length < 1) { 25 | this.stateManager.subscribeToGlobalChange( 26 | this.handleStateChange.bind(this, behaviorDefinition) 27 | ); 28 | } 29 | else { 30 | for (var i = 0; i < params.length; i++) { 31 | this.stateManager.subscribeTo( 32 | params[i], 33 | this.handleStateChange.bind(this, behaviorDefinition) 34 | ); 35 | } 36 | } 37 | }; 38 | 39 | States.prototype.getStateManager = function getStateManager() { 40 | return this.stateManager; 41 | }; 42 | 43 | States.prototype.set = function set(key, value, transition) { 44 | this.stateManager.set(key, value, transition); 45 | }; 46 | 47 | States.prototype.get = function get(key) { 48 | return this.stateManager.get(key); 49 | }; 50 | 51 | States.prototype.subscribeTo = function subscribeTo(key, observer) { 52 | this.stateManager.subscribeTo(key, observer); 53 | }; 54 | 55 | States.prototype.unsubscribeFrom = function unsubscribeFrom (key, observer) { 56 | this.stateManager.unsubscribeFrom(key, observer); 57 | }; 58 | 59 | States.prototype.unsubscribeAllFromKey = function unsubscribeAllFromKey (key) { 60 | this.stateManager._unsubscribeAllFromKey(key); 61 | }; 62 | 63 | States.prototype.triggerGlobalChange = function triggerGlobalChange(whiteList, blackList) { 64 | whiteList = whiteList || STATE_AUTOTRIGGER_RE; 65 | this.stateManager.triggerGlobalChange(whiteList, blackList); 66 | }; 67 | 68 | States.prototype.getValues = function getValues(names) { 69 | var result = []; 70 | for (var i = 0; i < names.length; i++) { 71 | result.push(this.stateManager.get(names[i])); 72 | } 73 | return result; 74 | }; 75 | 76 | States.prototype.getNames = function getNames() { 77 | return Object.keys(this.stateManager._state); 78 | }; 79 | 80 | module.exports = States; 81 | -------------------------------------------------------------------------------- /lib/tree/tree.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var VirtualDOM = require('./../virtual-dom/virtual-dom'); 4 | 5 | var CONTROL_FLOW_ACTION_KEY = 'control-flow-action'; 6 | var EMPTY_STRING = ''; 7 | var REPEAT_INFO_KEY = 'repeat-info'; 8 | 9 | function Tree(rootNode, treeString, dependencies, parentNode) { 10 | this.rootNode = rootNode; 11 | VirtualDOM.addNode(this.rootNode, parentNode); 12 | 13 | this.blueprint = VirtualDOM.clone(this.rootNode); 14 | var blueprintChildrenWrapper = VirtualDOM.parse(treeString || EMPTY_STRING); 15 | 16 | VirtualDOM.transferChildNodes(blueprintChildrenWrapper, this.blueprint); 17 | VirtualDOM.assignChildUIDs(this.blueprint); 18 | Tree.assignDependencyTags(this.blueprint, dependencies); 19 | 20 | this.expandedBlueprint = null; // Set via event after $if/$repeat 21 | this.childrenRoot = null; // Set via event after $yield 22 | } 23 | 24 | Tree.prototype.getBlueprint = function getBlueprint() { 25 | return this.blueprint; 26 | }; 27 | 28 | Tree.prototype.setExpandedBlueprint = function setExpandedBlueprint(expandedBlueprint) { 29 | this.expandedBlueprint = expandedBlueprint; 30 | }; 31 | 32 | Tree.prototype.getExpandedBlueprint = function getExpandedBlueprint() { 33 | return this.expandedBlueprint; 34 | }; 35 | 36 | Tree.prototype.setChildrenRoot = function setChildrenRoot(childrenRoot) { 37 | this.childrenRoot = childrenRoot; 38 | }; 39 | 40 | Tree.prototype.getChildrenRoot = function getChildrenRoot() { 41 | return this.childrenRoot; 42 | }; 43 | 44 | Tree.prototype.getRootNode = function getRootNode() { 45 | return this.rootNode; 46 | }; 47 | 48 | Tree.prototype.eachChild = function eachChild(cb) { 49 | for (var i = 0; i < this.childrenRoot.children.length; i++) { 50 | cb(this.childrenRoot.children[i]); 51 | } 52 | }; 53 | 54 | Tree.assignDependencyTags = function assignDependencyTags(node, dependencies) { 55 | var allNodes = VirtualDOM.query(node, '*'); 56 | for (var i = 0; i < allNodes.length; i++) { 57 | var subNode = allNodes[i]; 58 | var tagName = subNode.tagName.toLowerCase(); 59 | if (dependencies[tagName]) { 60 | VirtualDOM.setTag(subNode, dependencies[tagName]); 61 | } 62 | } 63 | }; 64 | 65 | Tree.removeAttributes = function removeAttributes(nodes, attrName) { 66 | for (var i = 0; i < nodes.length; i++) { 67 | VirtualDOM.removeAttribute(nodes[i], attrName); 68 | } 69 | }; 70 | 71 | Tree.prototype.stripExpandedBlueprintMessages = function stripExpandedBlueprintMessages() { 72 | var targets; 73 | targets = VirtualDOM.queryAttribute(this.expandedBlueprint, CONTROL_FLOW_ACTION_KEY); 74 | Tree.removeAttributes(targets, CONTROL_FLOW_ACTION_KEY); 75 | targets = VirtualDOM.queryAttribute(this.expandedBlueprint, REPEAT_INFO_KEY); 76 | Tree.removeAttributes(targets, REPEAT_INFO_KEY); 77 | }; 78 | 79 | module.exports = Tree; 80 | -------------------------------------------------------------------------------- /lib/utilities/array.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var ObjectUtils = require('./object'); 4 | 5 | // Iterate over the array, passing each element to the given function. 6 | function each(a, cb) { 7 | for (var i = 0; i < a.length; i++) { 8 | cb(a[i]); 9 | } 10 | } 11 | 12 | // Return the set of elements that appear in both arrays `a` and `b`. 13 | function union(a, b) { 14 | var set = {}; 15 | var maxLength = Math.max(a.length, b.length); 16 | var result = []; 17 | var i, key; 18 | 19 | for (i = 0; i < maxLength; i++) { 20 | if (i < a.length) set[a[i]] = true; 21 | if (i < b.length) set[b[i]] = true; 22 | } 23 | 24 | for (key in set) { 25 | result.push(key); 26 | } 27 | return result; 28 | } 29 | 30 | /** 31 | * Iterates over each element in a pair of arrays and returns a result array 32 | * signifying whether elements at a shared index are equal. 33 | * @param {Array} a 34 | * @param {Array} b 35 | * @return {Array} Array of booleans; 'true' signifies that the elements that share 36 | * that index are equal, 'false' signifies that the elements at that 37 | * index are not equal. 38 | */ 39 | function checkElementEquality(a, b) { 40 | var maxLength = Math.max(a.length, b.length); 41 | var result = []; 42 | var isEqual; 43 | 44 | for (var i = 0; i < maxLength; i++) { 45 | isEqual = (a.length > i && b.length > i) ? ObjectUtils.isEqual(a[i], b[i]) : false; 46 | result.push(isEqual); 47 | } 48 | return result; 49 | } 50 | 51 | /** 52 | * Checks to see if two arrays share a given value. 53 | * @param {Array} a 54 | * @param {Array} b 55 | * @return {Boolean} 56 | */ 57 | function shareValue(a, b) { 58 | for (var i = 0; i < a.length; i++) { 59 | if (b.indexOf(a[i]) !== -1) { 60 | return true; 61 | } 62 | } 63 | return false; 64 | } 65 | 66 | module.exports = { 67 | each: each, 68 | union: union, 69 | checkElementEquality: checkElementEquality, 70 | shareValue: shareValue 71 | }; 72 | -------------------------------------------------------------------------------- /lib/utilities/converter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Converter 5 | * 6 | * Converts between 'sweet' (FamousFramework timeline) 7 | * and 'salty' (piecewise timeline) representations 8 | * for easier interfacing of the two timelines. 9 | */ 10 | 11 | /** 12 | * Converts FamousFramework timeline 13 | * to piecewise timeline representation. 14 | */ 15 | function sweetToSalty(sweetTimeline, options) { 16 | var saltyTimeline = {}; 17 | 18 | options = options || {}; 19 | var duration = options.duration || 0; 20 | 21 | for (var selector in sweetTimeline) { 22 | var selectorBehaviors = sweetTimeline[selector]; 23 | 24 | for (var behavior in selectorBehaviors) { 25 | var flexframes = selectorBehaviors[behavior]; 26 | 27 | var name = selector + '|' + behavior; 28 | if (!saltyTimeline[name]) saltyTimeline[name] = []; 29 | 30 | for (var frame in flexframes) { 31 | var change = flexframes[frame]; 32 | 33 | var time = percentToNumber(frame, duration) || 0; 34 | var value = change.value || 0; 35 | var curve = change.curve || 'linear'; 36 | 37 | saltyTimeline[name].push([time, value, curve]); 38 | } 39 | } 40 | } 41 | 42 | return saltyTimeline; 43 | } 44 | 45 | /** 46 | * Converts piecewise timeline 47 | * to FamousFramework timeline representation. 48 | */ 49 | function saltyToSweet(saltyTimeline, options) { 50 | var sweetTimeline = {}; 51 | 52 | options = options || {}; 53 | var duration = options.duration || 5000; 54 | 55 | for (var selectorBehavior in saltyTimeline) { 56 | var flexframes = saltyTimeline[selectorBehavior]; 57 | 58 | var selector = selectorBehavior.split('|')[0]; 59 | var behavior = selectorBehavior.split('|')[1]; 60 | 61 | if (!sweetTimeline[selector]) sweetTimeline[selector] = {}; 62 | sweetTimeline[selector][behavior] = {}; 63 | 64 | for (var i = 0; i < flexframes.length; i++) { 65 | var change = flexframes[i]; 66 | 67 | var time = numberToPercent(change[0], duration); 68 | var value = change[1]; 69 | var curve = change[2]; 70 | 71 | sweetTimeline[selector][behavior][time] = {}; 72 | sweetTimeline[selector][behavior][time].value = value; 73 | 74 | if (curve !== 'linear') 75 | sweetTimeline[selector][behavior][time].curve = curve; 76 | } 77 | } 78 | 79 | return sweetTimeline; 80 | } 81 | 82 | function percentToNumber(percentStr, total) { 83 | return (percentStr.split('%')[0] / 100) * total; 84 | } 85 | 86 | function numberToPercent(number, total) { 87 | return (number / total * 100) + '%'; 88 | } 89 | 90 | module.exports = { 91 | sweetToSalty: sweetToSalty, 92 | saltyToSweet: saltyToSweet 93 | }; 94 | -------------------------------------------------------------------------------- /lib/utilities/function-parser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Returns an array of the passed-in function's arguments. 5 | */ 6 | 7 | var LPAREN = '('; 8 | var RPAREN = ')'; 9 | var REGEXP = /([^\s,]+)/g; 10 | 11 | function getParameterNames(fn) { 12 | var fnString = fn.toString(); 13 | var matches = fnString.slice(fnString.indexOf(LPAREN) + 1, fnString.indexOf(RPAREN)).match(REGEXP); 14 | return matches || []; 15 | } 16 | 17 | module.exports = { 18 | getParameterNames: getParameterNames 19 | }; 20 | -------------------------------------------------------------------------------- /lib/utilities/http.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Make an HTTP GET request to the given URL, returning 4 | // the results to the given callback. 5 | function get(url, cb) { 6 | var xhr = new XMLHttpRequest(); 7 | xhr.onreadystatechange = function() { 8 | if (xhr.readyState === 4 && xhr.status === 200) { 9 | cb(xhr.responseText); 10 | } 11 | }; 12 | xhr.open('GET', url, true); 13 | xhr.send(); 14 | } 15 | 16 | // GET request all of the given URLs, returning the 17 | // collection of results when all have completed. 18 | function join(urls, cb) { 19 | var total = 0; 20 | var length = urls.length; 21 | var out = []; 22 | if (length < 1) { 23 | return cb(out); 24 | } 25 | for (var i = 0; i < length; i++) { 26 | (function(idx) { 27 | var url = urls[idx]; 28 | get(url, function(data) { 29 | total += 1; 30 | // Important! We guarantee that results are returned 31 | // in the same order the URLs were given in, hence 32 | // assigning via index rather than pushing. 33 | out[idx] = data; 34 | if (total === length) { 35 | cb(out); 36 | } 37 | }); 38 | }(i)); 39 | } 40 | } 41 | 42 | module.exports = { 43 | get: get, 44 | join: join 45 | }; 46 | -------------------------------------------------------------------------------- /lib/utilities/uid.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var BLANK_STR = ''; 4 | var GLOBAL_PREFIX = '*'; 5 | var DELIMITER = '-'; 6 | var COUNTS = {}; 7 | 8 | function counter(prefix) { 9 | if (COUNTS[prefix] === undefined) { 10 | COUNTS[prefix] = 0; 11 | return 0; 12 | } 13 | else { 14 | COUNTS[prefix] += 1; 15 | return COUNTS[prefix]; 16 | } 17 | } 18 | 19 | function generate(group) { 20 | var prefix = (group || GLOBAL_PREFIX) + BLANK_STR; 21 | var count = counter(prefix) + BLANK_STR; 22 | var now = Date.now().toString(); 23 | var rand = Math.random().toString(36).slice(2); 24 | return [prefix, count, now, rand].join(DELIMITER); 25 | } 26 | 27 | module.exports = { 28 | generate: generate 29 | }; 30 | -------------------------------------------------------------------------------- /lib/utilities/utilities.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var DataStore = require('./../data-store/data-store'); 4 | var FunctionParser = require('./function-parser'); 5 | var VirtualDOM = require('./../virtual-dom/virtual-dom'); 6 | 7 | var FUNC_TYPE = 'function'; 8 | 9 | function getParameterNames(obj) { 10 | if (typeof obj === FUNC_TYPE) { 11 | return FunctionParser.getParameterNames(obj); 12 | } 13 | else { 14 | return null; 15 | } 16 | } 17 | 18 | function getComponent(node) { 19 | return DataStore.getComponent(VirtualDOM.getUID(node)); 20 | } 21 | 22 | function getParentComponent(node) { 23 | if (!node.parentNode) { 24 | throw new Error('Cannot get a parent component for a virtual dom node that does not have a parent'); 25 | } 26 | 27 | return DataStore.getComponent(VirtualDOM.getParentUID(node)); 28 | } 29 | 30 | function camelCase(input) { 31 | return input.toLowerCase().replace(/-(.)/g, function(match, group1) { 32 | return group1.toUpperCase(); 33 | }); 34 | } 35 | 36 | module.exports = { 37 | camelCase: camelCase, 38 | getComponent: getComponent, 39 | getParameterNames: getParameterNames, 40 | getParentComponent: getParentComponent 41 | }; 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "famous-framework", 3 | "version": "0.12.1", 4 | "description": "A modern take on building reusable components and maintainable applications", 5 | "keywords": [ 6 | "famous", 7 | "framework" 8 | ], 9 | "license": "MIT", 10 | "repository": "Famous/framework", 11 | "bugs": "https://github.com/Famous/framework/issues", 12 | "main": "lib/index.js", 13 | "authors": [ 14 | "Zack Brown ", 15 | "Matthew Trost ", 16 | "Arkady Pevzner ", 17 | "Imtiaz Majeed ", 18 | "Jordan Papaleo ", 19 | "Larry Gordon " 20 | ], 21 | "bin": { 22 | "famous-framework": "bin/famous-framework.js" 23 | }, 24 | "browser": { 25 | "jsdom": "./dev/build-pipeline/shims/jsdom.js" 26 | }, 27 | "scripts": { 28 | "dev": "node bin/famous-framework.js local-only-bootstrap --sourceFolder=lib/core-components --destinationFolder=dev/local-workspace/build --servedFolder=dev/local-workspace --port=1618", 29 | "browserify-build-pipeline": "browserify dev/build-pipeline/index.js -t brfs", 30 | "test-build-pipeline": "node test/build-pipeline/index.spec.js", 31 | "test-runtime": "browserify test/runtime-tests/**/*.spec.js | tap-closer | smokestack", 32 | "test-state-manager": "browserify test/state-manager-tests/*.spec.js | tap-closer | smokestack", 33 | "test-utilities": "browserify test/utilities-tests/*.spec.js | tap-closer | smokestack", 34 | "lint": "eslint --ignore-path .eslintignore ." 35 | }, 36 | "dependencies": { 37 | "async": "1.2.1", 38 | "babel": "5.5.8", 39 | "brfs": "^1.4.0", 40 | "browserify": "10.2.4", 41 | "chokidar": "1.0.3", 42 | "clone": "1.0.2", 43 | "commander": "2.8.1", 44 | "escodegen": "1.6.1", 45 | "esprima": "2.2.0", 46 | "estraverse": "4.1.0", 47 | "express": "4.12.4", 48 | "famous": "Famous/engine#v0.6.2", 49 | "jsdom": "3.1.2", 50 | "livereload": "0.3.7", 51 | "lodash.assign": "^3.2.0", 52 | "lodash.clone": "^3.0.2", 53 | "lodash.debounce": "^3.1.1", 54 | "lodash.defaults": "^3.1.2", 55 | "lodash.filter": "^3.1.1", 56 | "lodash.find": "^3.2.1", 57 | "lodash.first": "^3.0.0", 58 | "lodash.foreach": "^3.0.3", 59 | "lodash.last": "^3.0.0", 60 | "lodash.map": "^3.1.4", 61 | "lodash.pairs": "^3.0.1", 62 | "lodash.uniq": "^3.2.2", 63 | "mkdirp": "0.5.1", 64 | "ncp": "2.0.0", 65 | "pubsub-js": "^1.5.2", 66 | "recursive-readdir": "1.2.1", 67 | "rimraf": "^2.4.0", 68 | "watchify": "3.2.2" 69 | }, 70 | "devDependencies": { 71 | "babel-eslint": "3.1.15", 72 | "eslint": "0.23.0", 73 | "jsdoc": "3.3.2", 74 | "smokestack": "3.3.0", 75 | "tap-closer": "1.0.0", 76 | "tape": "4.0.0" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /test/build-pipeline/index.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Path = require('path'); 4 | var Test = require('tape'); 5 | 6 | var LocalAssistant = require('./../../dev/local-assistant/local-assistant'); 7 | 8 | var COMPONENTS_BASE_FOLDER = Path.join(__dirname, '..', '..', 'lib', 'core-components'); 9 | var DESTINATION_FOLDER = Path.join(__dirname, '..', '..', 'dev', 'local-workspace', 'build'); 10 | 11 | Test('build pipeline', function(t) { 12 | t.plan(3); 13 | 14 | var la = new LocalAssistant({ 15 | sourceFolder: COMPONENTS_BASE_FOLDER, 16 | destinationFolder: DESTINATION_FOLDER 17 | }); 18 | 19 | var componentFolder = Path.join('famous-demos', 'clickable-square'); 20 | 21 | la.buildSingle(COMPONENTS_BASE_FOLDER, componentFolder, function(buildSingleErr, moduleName, files, data) { 22 | if (buildSingleErr) { 23 | return console.error(buildSingleErr); 24 | } 25 | 26 | t.ok(moduleName, 'module name was output'); 27 | t.ok(files, 'files were output'); 28 | t.ok(data, 'data was output'); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/runtime-tests/helpers/virtual-dom-stub.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* 4 | Virtual DOM Stub One: 5 | 6 | wrapper 7 | parent:element#PARENT 8 | child:element.FIRST_CHILD(uid=0) 9 | grandchild:element 10 | greatgrandchild:element 11 | child:element(uid=1) 12 | grandchild:element 13 | child:element(uid=2) 14 | grandchild:element 15 | child:element(uid=3) 16 | child:element(uid=4) 17 | child:element(uid=5) 18 | */ 19 | 20 | var STUB_ONE_INFO = { 21 | PARENT_ID: 'PARENT', 22 | FIRST_CHILD_CLASS_NAME: 'FIRST_CHILD', 23 | CHILD_NAME: 'child:element', 24 | GRANDCHILD_NAME: 'grandchild:element', 25 | GREAT_GRANDCHILD_NAME: 'greatgrandchild:element', 26 | GRANDCHILDREN_COUNT: 3, 27 | CHILD_COUNT: 6, 28 | UID_KEY: 'uid' 29 | }; 30 | 31 | function createStubOne () { 32 | var wrapper = document.createElement('wrapper'); 33 | var parent = document.createElement('parent:element'); 34 | parent.id = STUB_ONE_INFO.PARENT_ID; 35 | wrapper.appendChild(parent); 36 | 37 | var child; 38 | var grandchild; 39 | var greatgrandchild; 40 | for(var i = 0; i < STUB_ONE_INFO.CHILD_COUNT; i++) { 41 | child = document.createElement('child:element'); 42 | child.setAttribute(STUB_ONE_INFO.UID_KEY, i); 43 | parent.appendChild(child); 44 | if (i === 0) { 45 | child.className = STUB_ONE_INFO.FIRST_CHILD_CLASS_NAME; 46 | } 47 | if (i < STUB_ONE_INFO.GRANDCHILDREN_COUNT) { 48 | grandchild = document.createElement(STUB_ONE_INFO.GRANDCHILD_NAME); 49 | if (i === 0) { 50 | greatgrandchild = document.createElement(STUB_ONE_INFO.GREAT_GRANDCHILD_NAME); 51 | grandchild.appendChild(greatgrandchild); 52 | } 53 | child.appendChild(grandchild); 54 | } 55 | } 56 | 57 | return wrapper; 58 | } 59 | 60 | module.exports = { 61 | stubOneInfo: STUB_ONE_INFO, 62 | getStubOne: createStubOne 63 | }; 64 | -------------------------------------------------------------------------------- /test/runtime-tests/main/index.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | window.Famous = require('famous'); 4 | var test = require('tape'); 5 | var FamousFramework = require('./../../../lib'); 6 | var DataStore = require('./../../../lib/data-store/data-store'); 7 | 8 | test('----- FamousFramework', function(t) { 9 | t.plan(1); 10 | 11 | t.test('exports', function(st) { 12 | st.plan(4); 13 | st.ok(FamousFramework, 'FamousFramework exports'); 14 | st.ok(DataStore, 'DataStore exports'); 15 | st.ok(FamousFramework.register && FamousFramework.execute && FamousFramework.message && FamousFramework.deploy, 'FamousFramework exports register/execture/message/deploy'); 16 | st.ok(FamousFramework.register === FamousFramework.scene && FamousFramework.register === FamousFramework.module && FamousFramework.register === FamousFramework.component, 'FamousFramework aliases `scene`/`module`/`component` to `register`.'); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/state-manager-tests/fixtures.js: -------------------------------------------------------------------------------- 1 | var state = { 2 | number: 1, 3 | string: 'two', 4 | array: [3, 3, 3], 5 | boolean: true, 6 | nestedState: { 7 | moreNesting: { 8 | nestingArray: [1, 2, 3] 9 | } 10 | } 11 | }; 12 | 13 | var observerState = { 14 | args: [], 15 | hasFired: false, 16 | hasFiredMoreThanOnce: false 17 | }; 18 | 19 | // Deep-clone the given object. 20 | function clone(b) { 21 | var a; 22 | if (typeof b === 'object') { 23 | a = (b instanceof Array) ? [] : {}; 24 | for (var key in b) { 25 | if (typeof b[key] === 'object' && b[key] !== null) { 26 | if (b[key] instanceof Array) { 27 | a[key] = new Array(b[key].length); 28 | for (var i = 0; i < b[key].length; i++) { 29 | a[key][i] = clone(b[key][i]); 30 | } 31 | } 32 | else { 33 | a[key] = clone(b[key]); 34 | } 35 | } 36 | else { 37 | a[key] = b[key]; 38 | } 39 | } 40 | } 41 | else { 42 | a = b; 43 | } 44 | return a; 45 | } 46 | 47 | module.exports = { 48 | state: state, 49 | clone: clone, 50 | observerState: observerState 51 | }; 52 | -------------------------------------------------------------------------------- /test/utilities-tests/converter.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var test = require('tape'); 4 | 5 | var converter = require('./../../lib/utilities/converter'); 6 | 7 | var toSalty = converter.sweetToSalty; 8 | var toSweet = converter.saltyToSweet; 9 | 10 | var sweetTimeline = { 11 | '#pen': { 12 | 'position': { 13 | '0%' : { value: [0, 0, 0], curve: 'outExpo' }, 14 | '100%' : { value: [1, 1, 1] } 15 | }, 16 | 'size': { 17 | '0%' : { value: [0, 0], curve: 'outExpo' }, 18 | '50%' : { value: [9, 9] } 19 | } 20 | } 21 | }; 22 | 23 | var saltyTimeline = { 24 | '#pen|position': [ 25 | [0, [0, 0, 0], 'outExpo'], 26 | [1000, [1, 1, 1], 'linear'] 27 | ], 28 | '#pen|size': [ 29 | [0, [0, 0], 'outExpo'], 30 | [500, [9, 9], 'linear'] 31 | ] 32 | }; 33 | 34 | test('convert between timeline representations', function(t) { 35 | t.plan(2); 36 | 37 | var options = { duration: 1000 }; 38 | 39 | var actualSaltyTimeline = toSalty(sweetTimeline, options); 40 | t.deepEqual(actualSaltyTimeline, saltyTimeline, 'should convert sweet to salty'); 41 | 42 | var actualySweetTimeline = toSweet(saltyTimeline, options); 43 | t.deepEqual(actualySweetTimeline, sweetTimeline, 'should convert salty to sweet'); 44 | }); 45 | 46 | -------------------------------------------------------------------------------- /test/utilities-tests/function-parser.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var test = require('tape'); 4 | var functionParser = require('./../../lib/utilities/function-parser'); 5 | var getParameterNames = functionParser.getParameterNames; 6 | 7 | var fn = function(one, two, three, four) {}; 8 | function func(one, two, three, four) {} 9 | var fnArgs = ['one', 'two', 'three', 'four']; 10 | 11 | test('getParameterNames', function(t) { 12 | t.plan(3); 13 | t.ok(getParameterNames, 'exports'); 14 | t.same(getParameterNames(fn), fnArgs, 'should return function arguments for function expressions'); 15 | t.same(getParameterNames(func), fnArgs, 'should return function arguments for function declarations'); 16 | t.end(); 17 | }); 18 | --------------------------------------------------------------------------------