├── .editorconfig ├── .ember-cli ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── .watchmanconfig ├── LICENSE.md ├── README.md ├── addon ├── .gitkeep ├── components │ ├── animated-item.js │ ├── pinned-item.js │ └── toggle-item.js ├── mixins │ ├── components │ │ ├── responsive-mixin.js │ │ └── scene-mixin.js │ └── scroll-controllers │ │ ├── component-mixin.js │ │ └── route-mixin.js ├── services │ └── scroll-magic.js ├── templates │ └── components │ │ ├── base-item.hbs │ │ └── pinned-item.hbs └── utils │ └── animations.js ├── app ├── .gitkeep ├── components │ ├── scrollmagic-animated.js │ ├── scrollmagic-pinned.js │ └── scrollmagic-toggle.js ├── mixins │ ├── components │ │ ├── responsive-mixin.js │ │ └── scene-mixin.js │ └── scroll-controllers │ │ ├── component-mixin.js │ │ └── route-mixin.js └── services │ └── scroll-magic.js ├── blueprints └── ember-scrollmagic │ └── index.js ├── config ├── ember-try.js └── environment.js ├── ember-cli-build.js ├── index.js ├── package.json ├── testem.js ├── tests ├── .eslintrc.js ├── dummy │ ├── app │ │ ├── app.js │ │ ├── breakpoints.js │ │ ├── components │ │ │ ├── .gitkeep │ │ │ ├── markdown-content.js │ │ │ ├── ui-button-link-to.js │ │ │ ├── ui-button-link.js │ │ │ ├── ui-button.js │ │ │ ├── ui-navbar.js │ │ │ ├── ui-panel.js │ │ │ └── ui-section.js │ │ ├── controllers │ │ │ ├── .gitkeep │ │ │ ├── application.js │ │ │ └── documentation │ │ │ │ └── examples │ │ │ │ ├── example.js │ │ │ │ └── index.js │ │ ├── examples.js │ │ ├── guides │ │ │ ├── components.md │ │ │ ├── components │ │ │ │ ├── animated.md │ │ │ │ ├── pinned.md │ │ │ │ └── toggle.md │ │ │ ├── custom-usage.md │ │ │ ├── custom-usage │ │ │ │ ├── animations.md │ │ │ │ └── components.md │ │ │ ├── index.md │ │ │ ├── install.md │ │ │ ├── scroll-controllers.md │ │ │ └── scroll-controllers │ │ │ │ ├── application.md │ │ │ │ └── components.md │ │ ├── helpers │ │ │ └── .gitkeep │ │ ├── index.html │ │ ├── initializers │ │ │ ├── responsive.js │ │ │ ├── showdown.js │ │ │ └── urls.js │ │ ├── instance-initializers │ │ │ ├── head-data.js │ │ │ └── inject-config.js │ │ ├── mixins │ │ │ └── ui │ │ │ │ ├── align-mixin.js │ │ │ │ ├── color-mixin.js │ │ │ │ ├── depth-mixin.js │ │ │ │ ├── font-size-mixin.js │ │ │ │ ├── padding-mixin.js │ │ │ │ └── size-mixin.js │ │ ├── models │ │ │ └── .gitkeep │ │ ├── resolver.js │ │ ├── router.js │ │ ├── routes │ │ │ ├── .gitkeep │ │ │ ├── application.js │ │ │ └── documentation │ │ │ │ ├── examples.js │ │ │ │ ├── examples │ │ │ │ ├── example.js │ │ │ │ └── index.js │ │ │ │ ├── guides.js │ │ │ │ └── guides │ │ │ │ ├── index.js │ │ │ │ └── single.js │ │ ├── snippets │ │ │ └── documentation │ │ │ │ └── examples │ │ │ │ └── templates │ │ │ │ ├── basic-animations │ │ │ │ ├── animations.md │ │ │ │ ├── component-lifecycle-hidden.md │ │ │ │ ├── component-lifecycle.md │ │ │ │ ├── dynamic-properties.md │ │ │ │ ├── indicators.md │ │ │ │ ├── intro.md │ │ │ │ ├── reverse.md │ │ │ │ └── toggle.md │ │ │ │ ├── pinned-items │ │ │ │ ├── fullscreen-section.md │ │ │ │ ├── intro.md │ │ │ │ ├── navbar.md │ │ │ │ └── scroll-to-top.md │ │ │ │ └── responsive-animations │ │ │ │ └── intro.md │ │ ├── styles │ │ │ ├── app.scss │ │ │ ├── components │ │ │ │ ├── _.scss │ │ │ │ ├── _config.scss │ │ │ │ ├── buttons │ │ │ │ │ └── _.scss │ │ │ │ ├── footer │ │ │ │ │ └── _.scss │ │ │ │ ├── markdown │ │ │ │ │ ├── _.scss │ │ │ │ │ ├── _menu.scss │ │ │ │ │ └── _prettyprint.scss │ │ │ │ ├── navbar │ │ │ │ │ └── _.scss │ │ │ │ ├── panels │ │ │ │ │ └── _.scss │ │ │ │ └── sections │ │ │ │ │ └── _.scss │ │ │ ├── framework │ │ │ │ ├── _colors.scss │ │ │ │ ├── _fonts.scss │ │ │ │ ├── _grid.scss │ │ │ │ ├── _mixins.scss │ │ │ │ ├── _reset.scss │ │ │ │ ├── _type.scss │ │ │ │ └── _utility.scss │ │ │ ├── main │ │ │ │ ├── _.scss │ │ │ │ └── _config.scss │ │ │ └── routes │ │ │ │ ├── _.scss │ │ │ │ ├── _index.scss │ │ │ │ └── documentation │ │ │ │ └── examples │ │ │ │ ├── _example.scss │ │ │ │ └── _index.scss │ │ ├── templates │ │ │ ├── application.hbs │ │ │ ├── components │ │ │ │ ├── .gitkeep │ │ │ │ ├── ui-button.hbs │ │ │ │ ├── ui-footer.hbs │ │ │ │ ├── ui-navbar.hbs │ │ │ │ ├── ui-panel.hbs │ │ │ │ └── ui-section.hbs │ │ │ ├── documentation.hbs │ │ │ ├── documentation │ │ │ │ ├── examples.hbs │ │ │ │ ├── examples │ │ │ │ │ ├── index.hbs │ │ │ │ │ ├── partials │ │ │ │ │ │ └── next-example.hbs │ │ │ │ │ └── templates │ │ │ │ │ │ ├── basic-animations.hbs │ │ │ │ │ │ ├── component-scrolling.hbs │ │ │ │ │ │ ├── custom-animations.hbs │ │ │ │ │ │ ├── horizontal-scrolling.hbs │ │ │ │ │ │ ├── parallax-sections.hbs │ │ │ │ │ │ ├── pinned-items.hbs │ │ │ │ │ │ ├── responsive-animations.hbs │ │ │ │ │ │ └── section-wipes-&-slides.hbs │ │ │ │ ├── guides.hbs │ │ │ │ └── guides │ │ │ │ │ └── single.hbs │ │ │ ├── head.hbs │ │ │ └── index.hbs │ │ └── utils │ │ │ └── property-class-name-binding.js │ ├── config │ │ ├── environment.js │ │ └── targets.js │ └── public │ │ ├── crossdomain.xml │ │ ├── images │ │ ├── ember-rocket.svg │ │ ├── facebook.jpg │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-64x64.png │ │ ├── favicon.ico │ │ ├── logo-light.svg │ │ └── logo-navbar.png │ │ └── robots.txt ├── helpers │ ├── destroy-app.js │ ├── module-for-acceptance.js │ ├── resolver.js │ └── start-app.js ├── index.html ├── integration │ └── .gitkeep ├── test-helper.js └── unit │ └── .gitkeep ├── vendor ├── .gitkeep └── shims │ └── scrollmagic.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.hbs] 17 | insert_final_newline = false 18 | 19 | [*.{diff,md}] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.ember-cli: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Ember CLI sends analytics information by default. The data is completely 4 | anonymous, but there are times when you might want to disable this behavior. 5 | 6 | Setting `disableAnalytics` to true will prevent any data from being sent. 7 | */ 8 | "disableAnalytics": false 9 | } 10 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | ecmaVersion: 2017, 5 | sourceType: 'module' 6 | }, 7 | extends: 'eslint:recommended', 8 | env: { 9 | browser: true 10 | }, 11 | rules: { 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | tests/dummy/* linguist-vendored 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | /bower_components 10 | 11 | # misc 12 | /.sass-cache 13 | /connect.lock 14 | /coverage/* 15 | /libpeerconnection.log 16 | npm-debug.log* 17 | package-lock.json 18 | yarn-error.log 19 | testem.log 20 | /DEBUG 21 | 22 | # ember-try 23 | .node_modules.ember-try/ 24 | bower.json.ember-try 25 | package.json.ember-try 26 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /bower_components 2 | /config/ember-try.js 3 | /dist 4 | /tests 5 | /tmp 6 | **/.gitkeep 7 | .bowerrc 8 | .editorconfig 9 | .ember-cli 10 | .gitignore 11 | .eslintrc.js 12 | .watchmanconfig 13 | .travis.yml 14 | bower.json 15 | ember-cli-build.js 16 | testem.js 17 | /DEBUG 18 | Icon^M^M 19 | Icon* 20 | 21 | # ember-try 22 | .node_modules.ember-try/ 23 | bower.json.ember-try 24 | package.json.ember-try 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: node_js 3 | node_js: 4 | # we recommend testing addons with the same minimum supported node version as Ember CLI 5 | # so that your addon works for all apps 6 | - "6" 7 | 8 | sudo: false 9 | dist: trusty 10 | 11 | addons: 12 | chrome: stable 13 | 14 | cache: 15 | yarn: true 16 | 17 | env: 18 | global: 19 | # See https://git.io/vdao3 for details. 20 | - JOBS=1 21 | matrix: 22 | # we recommend new addons test the current and previous LTS 23 | # as well as latest stable release (bonus points to beta/canary) 24 | - EMBER_TRY_SCENARIO=ember-lts-2.12 25 | - EMBER_TRY_SCENARIO=ember-lts-2.16 26 | - EMBER_TRY_SCENARIO=ember-release 27 | - EMBER_TRY_SCENARIO=ember-beta 28 | - EMBER_TRY_SCENARIO=ember-canary 29 | 30 | matrix: 31 | fast_finish: true 32 | allow_failures: 33 | - env: EMBER_TRY_SCENARIO=ember-canary 34 | 35 | before_install: 36 | - curl -o- -L https://yarnpkg.com/install.sh | bash 37 | - export PATH=$HOME/.yarn/bin:$PATH 38 | 39 | install: 40 | - yarn install --no-lockfile --non-interactive 41 | 42 | script: 43 | # Usually, it's ok to finish the test scenario without reverting 44 | # to the addon's original dependency state, skipping "cleanup". 45 | - node_modules/.bin/ember try:one $EMBER_TRY_SCENARIO --skip-cleanup 46 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["tmp", "dist"] 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ember ScrollMagic [![Build Status](https://travis-ci.org/willviles/ember-scrollmagic.svg)](https://travis-ci.org/willviles/ember-scrollmagic) [![Ember Observer Score](http://emberobserver.com/badges/ember-scrollmagic.svg)](http://emberobserver.com/addons/ember-scrollmagic) ![Download count all time](https://img.shields.io/npm/dt/ember-scrollmagic.svg) [![npm](https://img.shields.io/npm/v/ember-scrollmagic.svg)](https://www.npmjs.com/package/ember-scrollmagic) 4 | ====== 5 | 6 | Ember ScrollMagic is an Ember addon for using [ScrollMagic](https://github.com/janpaepke/ScrollMagic) - the javascript library for magical scroll interactions. 7 | 8 | ## Installation 9 | 10 | ScrollMagic uses [GSAP (Greensock Animation Platform)](https://github.com/greensock/GreenSock-JS) for full animation tweening. Ember ScrollMagic will automatically install [Ember GSAP](https://github.com/willviles/ember-gsap) into your application. 11 | 12 | ```bash 13 | ember install ember-scrollmagic 14 | ``` 15 | 16 | ## Examples & Documentation 17 | 18 | **Check out the Ember ScrollMagic site for [examples](https://willviles.github.io/ember-scrollmagic/#/documentation/examples) and [guides](https://willviles.github.io/ember-scrollmagic/#/documentation/guides).** 19 | 20 | Please refer to the ScrollMagic [docs](http://scrollmagic.io/docs/index.html) for information on using controllers and scenes. For ideas and inspiration of what to create with ScrollMagic, check out the [examples](http://scrollmagic.io/examples/). 21 | 22 | ## Fastboot 23 | 24 | Ember ScrollMagic >=0.2.0 and [Ember GSAP](https://github.com/willviles/ember-gsap) >=0.3.0 are fully compatible with all versions of [Ember CLI Fastboot](https://github.com/ember-fastboot/ember-cli-fastboot). 25 | 26 | ## Contributing 27 | 28 | * `git clone https://github.com/willviles/ember-scrollmagic.git` 29 | * `cd ember-scrollmagic` 30 | * `npm install` 31 | * `ember serve` 32 | * Visit the dummy app at [http://localhost:4200](http://localhost:4200). 33 | -------------------------------------------------------------------------------- /addon/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/addon/.gitkeep -------------------------------------------------------------------------------- /addon/components/animated-item.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import Mixin from '@ember/object/mixin'; 3 | import { assert } from '@ember/debug'; 4 | 5 | import layout from 'ember-scrollmagic/templates/components/base-item'; 6 | 7 | import { 8 | default as EmberObject, 9 | computed, 10 | get 11 | } from '@ember/object'; 12 | 13 | import ScrollMagic from 'scrollmagic'; 14 | import { TimelineMax, TweenLite } from 'gsap'; 15 | 16 | import defaultAnimations from 'ember-scrollmagic/utils/animations'; 17 | import ScrollMagicSceneMixin from 'ember-scrollmagic/mixins/components/scene-mixin'; 18 | 19 | export const ScrollMagicAnimatedMixin = Mixin.create( 20 | ScrollMagicSceneMixin, { 21 | 22 | layout, 23 | 24 | setupScene() { 25 | let opts = get(this, 'mergedOptions'), 26 | timeline = get(this, 'timeline'); 27 | 28 | return new ScrollMagic.Scene(opts).setTween(timeline) 29 | }, 30 | 31 | animation: computed(function() { 32 | assert(`Please define an animation type for ScrollMagic animated component`); 33 | }), 34 | 35 | animations: computed(function() { 36 | return EmberObject.create(defaultAnimations); 37 | }), 38 | 39 | timeline: computed('animation', function() { 40 | let name = get(this, 'animation'), 41 | animation = get(this, `animations.${name}`); 42 | 43 | assert(`ScrollMagic animation '${name}' does not exist.`, animation); 44 | 45 | return new TimelineMax().add( 46 | TweenLite.fromTo(this.element, 1, ...animation) 47 | ); 48 | 49 | }) 50 | 51 | }); 52 | 53 | export default Component.extend(ScrollMagicAnimatedMixin); 54 | -------------------------------------------------------------------------------- /addon/components/pinned-item.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import Mixin from '@ember/object/mixin'; 3 | import { computed, get } from '@ember/object'; 4 | 5 | import ScrollMagic from 'scrollmagic'; 6 | import ScrollMagicSceneMixin from 'ember-scrollmagic/mixins/components/scene-mixin'; 7 | 8 | import layout from 'ember-scrollmagic/templates/components/pinned-item'; 9 | 10 | export const ScrollMagicPinnedMixin = Mixin.create( 11 | ScrollMagicSceneMixin, { 12 | 13 | layout, 14 | 15 | defaultOptions: computed(function() { 16 | return { 17 | duration: 0, 18 | triggerHook: `onLeave`, 19 | triggerElement: this.element 20 | }; 21 | }), 22 | 23 | pinElementId: computed(function() { 24 | return `scrollmagic-pin-${this.elementId}-target`; 25 | }), 26 | 27 | pinOptions: computed(function() { 28 | return { 29 | pushFollowers: false, 30 | spacerClass: 'scrollmagic-pin-spacer' 31 | } 32 | }), 33 | 34 | setupScene() { 35 | let opts = get(this, 'mergedOptions'), 36 | pinElementId = get(this, 'pinElementId'), 37 | pinOptions = get(this, 'pinOptions'); 38 | 39 | pinOptions = JSON.parse(JSON.stringify(pinOptions)); 40 | 41 | return new ScrollMagic.Scene(opts).setPin(`#${pinElementId}`, pinOptions); 42 | } 43 | }); 44 | 45 | export default Component.extend(ScrollMagicPinnedMixin); 46 | -------------------------------------------------------------------------------- /addon/components/toggle-item.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import Mixin from '@ember/object/mixin'; 3 | import { assert } from '@ember/debug'; 4 | import { computed, get } from '@ember/object'; 5 | 6 | import ScrollMagic from 'scrollmagic'; 7 | import $ from 'jquery'; 8 | 9 | import ScrollMagicSceneMixin from 'ember-scrollmagic/mixins/components/scene-mixin'; 10 | 11 | import layout from 'ember-scrollmagic/templates/components/base-item'; 12 | 13 | export const ScrollMagicToggleMixin = Mixin.create( 14 | ScrollMagicSceneMixin, { 15 | 16 | layout, 17 | 18 | defaultOptions: computed(function() { 19 | return { 20 | duration: 0, 21 | triggerHook: `onEnter`, 22 | triggerElement: this.element 23 | }; 24 | }), 25 | 26 | toggleClasses: computed(function() { 27 | assert(`No classes defined for 'scrollmagic-toggle' to toggle`); 28 | }), 29 | 30 | toggleElement: computed(function() { 31 | return this.element; 32 | }), 33 | 34 | setupScene() { 35 | let opts = get(this, 'mergedOptions'), 36 | toggleElement = get(this, 'toggleElement'), 37 | $toggleElement = $(toggleElement), 38 | toggleClasses = get(this, 'toggleClasses'), 39 | toggleClassesOff = get(this, 'toggleClassesOff'); 40 | 41 | // NOTE: ScrollMagic.Scene().setClassToggle is currently BROKEN! 42 | // 43 | // This will not work when multiple classes are added: 44 | // return new ScrollMagic.Scene(opts).setClassToggle(toggleElementId, toggleClasses); 45 | // 46 | // The following issue is related: 47 | // https://github.com/janpaepke/ScrollMagic/issues/313 48 | // 49 | // The workaround uses scene enter and leave events to achieve the same goal. 50 | 51 | let scene = new ScrollMagic.Scene(opts); 52 | 53 | scene.on(`enter.${this.elementId}-toggle`, () => { 54 | $toggleElement.addClass(toggleClasses); 55 | if (toggleClassesOff) { 56 | $toggleElement.removeClass(toggleClassesOff); 57 | } 58 | }); 59 | 60 | scene.on(`leave.${this.elementId}-toggle`, function(){ 61 | $toggleElement.removeClass(toggleClasses); 62 | if (toggleClassesOff) { 63 | $toggleElement.addClass(toggleClassesOff); 64 | } 65 | }); 66 | 67 | return scene; 68 | }, 69 | 70 | willDestroyElement() { 71 | let scene = get(this, 'scene'); 72 | 73 | if (scene) { 74 | scene.off(`enter.${this.elementId}-toggle`); 75 | scene.off(`leave.${this.elementId}-toggle`); 76 | } 77 | 78 | this._super(...arguments); 79 | } 80 | 81 | }); 82 | 83 | export default Component.extend(ScrollMagicToggleMixin); 84 | -------------------------------------------------------------------------------- /addon/mixins/components/responsive-mixin.js: -------------------------------------------------------------------------------- 1 | import Mixin from '@ember/object/mixin'; 2 | import { getOwner } from '@ember/application'; 3 | import { A } from '@ember/array'; 4 | import { computed, get, getProperties } from '@ember/object'; 5 | import { addObserver, removeObserver } from '@ember/object/observers'; 6 | import { isPresent, typeOf } from '@ember/utils'; 7 | 8 | export default Mixin.create({ 9 | 10 | media: computed(function() { 11 | let owner = getOwner(this); 12 | return owner.lookup('service:media'); 13 | }), 14 | 15 | willRender() { 16 | this._super(...arguments); 17 | this.setResponsiveSceneHandlers(); 18 | }, 19 | 20 | setResponsiveSceneHandlers() { 21 | let { 22 | media, 23 | triggerOnMedia 24 | } = getProperties(this, 'media', 'triggerOnMedia'); 25 | 26 | if (!media || !triggerOnMedia) { return; } 27 | addObserver(media, 'matches.[]', this, 'onResponsiveSizeChange'); 28 | }, 29 | 30 | onResponsiveSizeChange() { 31 | this.setOrRemoveScene(); 32 | }, 33 | 34 | isActiveMediaQuery() { 35 | let media = get(this, 'media'), 36 | triggerOnMedia = get(this, 'triggerOnMedia'); 37 | 38 | if (!media || !triggerOnMedia) { return true; } 39 | 40 | if (typeOf(triggerOnMedia) === 'string') { 41 | triggerOnMedia = A([triggerOnMedia]); 42 | } 43 | 44 | if (typeOf(triggerOnMedia) !== 'array') { return true; } 45 | 46 | let matches = get(media, 'matches'), 47 | match = triggerOnMedia.find(media => { 48 | return matches.includes(media); 49 | }); 50 | 51 | return isPresent(match); 52 | }, 53 | 54 | willDestroyElement() { 55 | this._super(...arguments); 56 | removeObserver(this, 'media.matches.[]', this, 'onResponsiveSizeChange'); 57 | } 58 | 59 | }); 60 | -------------------------------------------------------------------------------- /addon/mixins/components/scene-mixin.js: -------------------------------------------------------------------------------- 1 | import Mixin from '@ember/object/mixin'; 2 | import { A } from '@ember/array'; 3 | import { assert } from '@ember/debug'; 4 | 5 | import { 6 | computed, 7 | get, 8 | getProperties, 9 | getWithDefault, 10 | set 11 | } from '@ember/object'; 12 | 13 | import { assign } from '@ember/polyfills'; 14 | import { inject as service } from '@ember/service'; 15 | import { capitalize } from '@ember/string'; 16 | import { typeOf } from '@ember/utils'; 17 | 18 | import ScrollMagicResponsiveMixin from 'ember-scrollmagic/mixins/components/responsive-mixin'; 19 | 20 | export default Mixin.create( 21 | ScrollMagicResponsiveMixin, { 22 | 23 | scrollMagic: service(), 24 | 25 | scrollController: computed(function() { 26 | return get(this, 'scrollMagic').getController(); 27 | }), 28 | 29 | availableSceneOptions: computed(function() { 30 | return A([ 31 | 'duration', 'loglevel', 'offset', 'reverse', 'triggerElement', 'triggerHook' 32 | ]); 33 | }), 34 | 35 | defaultOptions: computed(function() { 36 | return { 37 | duration: `100%`, 38 | triggerHook: `onEnter`, 39 | triggerElement: this.element 40 | }; 41 | }), 42 | 43 | sceneOptions: computed(function() { 44 | return {}; 45 | }), 46 | 47 | mergedOptions: computed('defaultOptions', 'sceneOptions', function() { 48 | let { defaultOptions, sceneOptions } = getProperties(this, 'defaultOptions', 'sceneOptions'); 49 | if (!defaultOptions || !sceneOptions) { return; } 50 | return assign({}, defaultOptions, sceneOptions); 51 | }), 52 | 53 | setOrRemoveScene() { 54 | let scene = get(this, 'scene'), 55 | match = this.isActiveMediaQuery(); 56 | 57 | if (match && !scene) { 58 | this.setScene(); 59 | } else if (!match && scene) { 60 | this.removeScene(); 61 | } 62 | }, 63 | 64 | setScene() { 65 | let scene = this.setupScene(); 66 | 67 | this.addIndicators(scene); 68 | this.addSceneEventHandlers(scene); 69 | 70 | set(this, 'scene', scene); 71 | 72 | this.addScene(); 73 | }, 74 | 75 | addScene() { 76 | let controller = get(this, 'scrollController'), 77 | scene = get(this, 'scene'); 78 | 79 | controller.addScene(scene); 80 | }, 81 | 82 | setupScene() { 83 | assert(`No setupScene defined.`); 84 | }, 85 | 86 | updateScene(changedValues) { 87 | let scene = get(this, 'scene'); 88 | 89 | Object.keys(changedValues).forEach(key => { 90 | let updateFunc = scene[key], 91 | value = changedValues[key]; 92 | 93 | if (typeOf(updateFunc) === 'function') { 94 | updateFunc(value); 95 | } 96 | }); 97 | 98 | scene.refresh(); 99 | }, 100 | 101 | removeScene() { 102 | let scene = get(this, 'scene'); 103 | if (scene) { 104 | this.removeSceneEventHandlers(scene); 105 | this.removeSceneProps(scene); 106 | scene.remove(); 107 | set(this, 'scene', null); 108 | } 109 | }, 110 | 111 | addIndicators(scene) { 112 | let indicators = getWithDefault(this, 'indicators', false), 113 | type = typeOf(indicators); 114 | 115 | if (indicators === true || type === 'object') { 116 | let options = type === 'object' ? JSON.parse(JSON.stringify(indicators)) : {}; 117 | scene.addIndicators(options); 118 | } 119 | }, 120 | 121 | sceneEvents: computed(function() { 122 | return ['change', 'update', 'progress', 'start', 'end', 'enter', 'leave']; 123 | }), 124 | 125 | onSceneChange() {}, 126 | onSceneUpdate() {}, 127 | onSceneProgress() {}, 128 | onSceneStart() {}, 129 | onSceneEnd() {}, 130 | onSceneEnter() {}, 131 | onSceneLeave() {}, 132 | 133 | addSceneEventHandlers(scene) { 134 | get(this, 'sceneEvents').forEach(key => { 135 | let action = get(this, `onScene${capitalize(key)}`); 136 | scene.on(`${key}.${this.elementId}`, action); 137 | }); 138 | 139 | }, 140 | 141 | removeSceneEventHandlers(scene) { 142 | get(this, 'sceneEvents').forEach(key => { 143 | scene.off(`${key}.${this.elementId}`); 144 | }); 145 | }, 146 | 147 | removeSceneProps() { 148 | this.$().removeAttr('style'); 149 | }, 150 | 151 | didRender() { 152 | this._super(...arguments); 153 | this.setOrRemoveScene(); 154 | }, 155 | 156 | didReceiveAttrs() { 157 | this._super(...arguments); 158 | let availableSceneOptions = get(this, 'availableSceneOptions'), 159 | sceneOptions = get(this, 'sceneOptions'), 160 | scene = get(this, 'scene'); 161 | 162 | if (!sceneOptions || get(this, 'isDestroyed')) { return; } 163 | 164 | let newValues = availableSceneOptions.reduce((values, key) => { 165 | let value = get(this, key); 166 | values[key] = value; 167 | return values; 168 | }, {}); 169 | 170 | let changedValues = {}; 171 | 172 | Object.keys(newValues).forEach(key => { 173 | let value = newValues[key]; 174 | if (value !== sceneOptions[key]) { 175 | sceneOptions[key] = value; 176 | changedValues[key] = value; 177 | } 178 | }); 179 | 180 | set(this, 'sceneOptions', sceneOptions); 181 | 182 | if (get(this, 'sceneInitialized')) { 183 | if (scene) { 184 | this.updateScene(changedValues); 185 | } else { 186 | this.setScene(); 187 | } 188 | 189 | } 190 | }, 191 | 192 | willDestroyElement() { 193 | this._super(...arguments); 194 | this.removeScene(); 195 | } 196 | 197 | }); 198 | -------------------------------------------------------------------------------- /addon/mixins/scroll-controllers/component-mixin.js: -------------------------------------------------------------------------------- 1 | import Mixin from '@ember/object/mixin'; 2 | import { get, set } from '@ember/object'; 3 | import { inject as service } from '@ember/service'; 4 | 5 | export default Mixin.create({ 6 | 7 | scrollMagic: service(), 8 | 9 | willRender() { 10 | this._super(...arguments); 11 | let scrollMagic = get(this, 'scrollMagic'); 12 | let controller = scrollMagic.getController(`${this.elementId}`); 13 | if (controller) { return; } 14 | let scrollController = scrollMagic.addController(`${this.elementId}`); 15 | set(this, 'scrollController', scrollController); 16 | }, 17 | 18 | willDestroyElement() { 19 | this._super(...arguments); 20 | get(this, 'scrollMagic').destroyController(`${this.elementId}`); 21 | set(this, 'scrollController', null); 22 | } 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /addon/mixins/scroll-controllers/route-mixin.js: -------------------------------------------------------------------------------- 1 | import Mixin from '@ember/object/mixin'; 2 | import { get } from '@ember/object'; 3 | import { inject as service } from '@ember/service'; 4 | 5 | export default Mixin.create({ 6 | 7 | scrollMagic: service(), 8 | 9 | activate() { 10 | this._super(...arguments); 11 | get(this, 'scrollMagic').addController(); 12 | }, 13 | 14 | willDestroy() { 15 | this._super(...arguments); 16 | get(this, 'scrollMagic').destroyController(); 17 | } 18 | 19 | }); 20 | -------------------------------------------------------------------------------- /addon/services/scroll-magic.js: -------------------------------------------------------------------------------- 1 | import Service from '@ember/service'; 2 | import { getOwner } from '@ember/application'; 3 | import { warn } from '@ember/debug'; 4 | import { default as EmberObject, computed, get, set } from '@ember/object'; 5 | import { scheduleOnce } from '@ember/runloop'; 6 | 7 | import { task, timeout } from 'ember-concurrency'; 8 | 9 | import ScrollMagic from 'scrollmagic'; 10 | import $ from 'jquery'; 11 | 12 | export default Service.extend({ 13 | 14 | fastboot: computed(function() { 15 | let owner = getOwner(this); 16 | return owner.lookup('service:fastboot'); 17 | }), 18 | 19 | isFastBoot: computed(function() { 20 | return get(this, 'fastboot.isFastBoot') === true; 21 | }), 22 | 23 | init() { 24 | this._super(...arguments); 25 | set(this, 'registry', EmberObject.create({})); 26 | this.addResizeHandler(); 27 | }, 28 | 29 | willDestroy() { 30 | this._super(...arguments); 31 | this.removeResizeHandler(); 32 | }, 33 | 34 | addController(id = `application`, opts = {}) { 35 | if (get(this, 'isFastBoot')) { return; } 36 | let controller = new ScrollMagic.Controller(opts); 37 | set(this, `registry.${id}`, controller); 38 | return controller; 39 | }, 40 | 41 | getController(id = `application`) { 42 | if (get(this, 'isFastBoot')) { return; } 43 | return get(this, `registry.${id}`); 44 | }, 45 | 46 | updateController(id = `application`) { 47 | if (get(this, 'isFastBoot')) { return; } 48 | let controller = get(this, `registry.${id}`); 49 | if (!controller) { 50 | let msg = `Cannot update ScrollMagic controller - not registered.`, 51 | msgid = `scrollmagic-controller-not-registered` 52 | return warn(msg, { id: msgid }); 53 | } 54 | scheduleOnce('afterRender', () => { 55 | controller.update(); 56 | }); 57 | }, 58 | 59 | updateControllers: task(function* () { 60 | yield timeout(200); 61 | let registry = get(this, 'registry'); 62 | Object.keys(registry).forEach(id => { 63 | this.updateController(id); 64 | }); 65 | }).restartable(), 66 | 67 | destroyController(id = `application`) { 68 | if (get(this, 'isFastBoot')) { return; } 69 | let controller = get(this, `registry.${id}`); 70 | if (!controller) { 71 | let msg = `Cannot delete ScrollMagic controller - not registered.`, 72 | msgid = `scrollmagic-controller-not-registered` 73 | return warn(msg, { id: msgid }); 74 | } 75 | controller.destroy(); 76 | set(this, `registry.${id}`, null); 77 | }, 78 | 79 | addResizeHandler() { 80 | if (get(this, 'isFastBoot')) { return; } 81 | $(window).bind('resize.emberScrollMagic', () => { 82 | get(this, 'updateControllers').perform(); 83 | }); 84 | }, 85 | 86 | removeResizeHandler() { 87 | if (get(this, 'isFastBoot')) { return; } 88 | $(window).unbind('resize.emberScrollMagic'); 89 | } 90 | 91 | }); 92 | -------------------------------------------------------------------------------- /addon/templates/components/base-item.hbs: -------------------------------------------------------------------------------- 1 | {{#if hasBlock}} 2 | 3 | {{yield this (hash 4 | animated=(component 'scrollmagic-animated') 5 | pinned=(component 'scrollmagic-pinned') 6 | toggle=(component 'scrollmagic-toggle') 7 | )}} 8 | 9 | {{else}} 10 | 11 | {{yield}} 12 | 13 | {{/if}} 14 | -------------------------------------------------------------------------------- /addon/templates/components/pinned-item.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#if hasBlock}} 3 | 4 | {{yield this (hash 5 | animated=(component 'scrollmagic-animated') 6 | pinned=(component 'scrollmagic-pinned') 7 | toggle=(component 'scrollmagic-toggle') 8 | )}} 9 | 10 | {{else}} 11 | 12 | {{yield}} 13 | 14 | {{/if}} 15 |
16 | -------------------------------------------------------------------------------- /addon/utils/animations.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'fade': [{ 3 | opacity: 0 4 | }, { 5 | opacity: 1 6 | }], 7 | 8 | 'fly-horizontal': [{ 9 | x: '-100%' 10 | }, { 11 | x: '100%' 12 | }] 13 | } 14 | -------------------------------------------------------------------------------- /app/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/app/.gitkeep -------------------------------------------------------------------------------- /app/components/scrollmagic-animated.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-scrollmagic/components/animated-item'; 2 | -------------------------------------------------------------------------------- /app/components/scrollmagic-pinned.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-scrollmagic/components/pinned-item'; 2 | -------------------------------------------------------------------------------- /app/components/scrollmagic-toggle.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-scrollmagic/components/toggle-item'; 2 | -------------------------------------------------------------------------------- /app/mixins/components/responsive-mixin.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-scrollmagic/mixins/components/responsive-mixin'; 2 | -------------------------------------------------------------------------------- /app/mixins/components/scene-mixin.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-scrollmagic/mixins/components/scene-mixin'; 2 | 3 | -------------------------------------------------------------------------------- /app/mixins/scroll-controllers/component-mixin.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-scrollmagic/mixins/scroll-controllers/component-mixin'; 2 | 3 | -------------------------------------------------------------------------------- /app/mixins/scroll-controllers/route-mixin.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-scrollmagic/mixins/scroll-controllers/route-mixin'; 2 | 3 | -------------------------------------------------------------------------------- /app/services/scroll-magic.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-scrollmagic/services/scroll-magic'; 2 | -------------------------------------------------------------------------------- /blueprints/ember-scrollmagic/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node:true */ 2 | /* globals module */ 3 | 4 | module.exports = { 5 | normalizeEntityName: function() {}, 6 | 7 | afterInstall(/*options*/) { 8 | return this.addPackagesToProject( 9 | [ 10 | { name: 'ember-gsap', target: '^0.3.3' } 11 | ] 12 | ); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /config/ember-try.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = { 3 | useYarn: true, 4 | scenarios: [ 5 | { 6 | name: 'ember-lts-2.12', 7 | npm: { 8 | devDependencies: { 9 | 'ember-source': '~2.12.0' 10 | } 11 | } 12 | }, 13 | { 14 | name: 'ember-lts-2.16', 15 | npm: { 16 | devDependencies: { 17 | 'ember-source': '~2.16.0' 18 | } 19 | } 20 | }, 21 | { 22 | name: 'ember-release', 23 | bower: { 24 | dependencies: { 25 | 'ember': 'components/ember#release' 26 | }, 27 | resolutions: { 28 | 'ember': 'release' 29 | } 30 | }, 31 | npm: { 32 | devDependencies: { 33 | 'ember-source': null 34 | } 35 | } 36 | }, 37 | { 38 | name: 'ember-beta', 39 | bower: { 40 | dependencies: { 41 | 'ember': 'components/ember#beta' 42 | }, 43 | resolutions: { 44 | 'ember': 'beta' 45 | } 46 | }, 47 | npm: { 48 | devDependencies: { 49 | 'ember-source': null 50 | } 51 | } 52 | }, 53 | { 54 | name: 'ember-canary', 55 | bower: { 56 | dependencies: { 57 | 'ember': 'components/ember#canary' 58 | }, 59 | resolutions: { 60 | 'ember': 'canary' 61 | } 62 | }, 63 | npm: { 64 | devDependencies: { 65 | 'ember-source': null 66 | } 67 | } 68 | } 69 | ] 70 | }; 71 | -------------------------------------------------------------------------------- /config/environment.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | module.exports = function(/* environment, appConfig */) { 5 | return { }; 6 | }; 7 | -------------------------------------------------------------------------------- /ember-cli-build.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); 5 | 6 | module.exports = function(defaults) { 7 | let app = new EmberAddon(defaults, { 8 | // Add options here 9 | }); 10 | 11 | /* 12 | This build file specifies the options for the dummy test app of this 13 | addon, located in `/tests/dummy` 14 | This build file does *not* influence how the addon or the app using it 15 | behave. You most likely want to be modifying `./index.js` or app's build file 16 | */ 17 | 18 | return app.toTree(); 19 | }; 20 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | const BroccoliDebug = require('broccoli-debug'); 5 | const Funnel = require('broccoli-funnel'); 6 | const mergeTrees = require('broccoli-merge-trees'); 7 | const fastbootTransform = require('fastboot-transform'); 8 | const path = require('path'); 9 | 10 | module.exports = { 11 | name: 'ember-scrollmagic', 12 | 13 | included(app) { 14 | if (typeof app.import !== 'function' && app.app) { 15 | app = app.app; 16 | } 17 | this.app = app; 18 | 19 | this.addonConfig = this.app.project.config(app.env)['ember-scrollmagic'] || {}; 20 | 21 | const vendor = this.treePaths.vendor; 22 | 23 | // Main modules 24 | app.import(vendor + '/scrollmagic/ScrollMagic.js'); 25 | app.import(vendor + '/scrollmagic/plugins/animation.gsap.js'); 26 | 27 | // Add indicators 28 | if (this.addonConfig.indicators) { 29 | app.import(vendor + '/scrollmagic/plugins/debug.addIndicators.js'); 30 | } 31 | 32 | // Expose `import` via a shim 33 | app.import('vendor/shims/scrollmagic.js', { 34 | exports: { 35 | scrollmagic: ['default'] 36 | } 37 | }); 38 | 39 | return this._super.included.apply(this, arguments); 40 | }, 41 | 42 | treeForVendor(vendorTree) { 43 | let debugTree = BroccoliDebug.buildDebugCallback(this.name), 44 | trees = []; 45 | 46 | if (vendorTree) { 47 | trees.push( 48 | debugTree(vendorTree, 'vendorTree') 49 | ); 50 | } 51 | 52 | let js = fastbootTransform( 53 | moduleToFunnel('scrollmagic') 54 | ); 55 | 56 | trees.push( 57 | debugTree(js, 'js') 58 | ); 59 | 60 | return mergeTrees(trees); 61 | }, 62 | 63 | }; 64 | 65 | function moduleToFunnel(moduleName, destination) { 66 | return new Funnel(resolveModulePath(moduleName), { 67 | destDir: destination || moduleName 68 | }); 69 | } 70 | 71 | function resolveModulePath(moduleName) { 72 | return path.dirname(require.resolve(moduleName)); 73 | } 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-scrollmagic", 3 | "version": "1.0.0-beta3", 4 | "description": "An Ember addon for using ScrollMagic - the javascript library for magical scroll interactions.", 5 | "keywords": [ 6 | "ember-addon", 7 | "scrollMagic", 8 | "scroll", 9 | "scrolling", 10 | "animation", 11 | "sticky", 12 | "pin", 13 | "fixed", 14 | "scrollbar", 15 | "scrub", 16 | "sync", 17 | "position", 18 | "progress", 19 | "parallax" 20 | ], 21 | "license": "MIT", 22 | "author": { 23 | "name": "Will Viles", 24 | "email": "will@vil.es", 25 | "url": "https://willviles.com" 26 | }, 27 | "directories": { 28 | "doc": "doc", 29 | "test": "tests" 30 | }, 31 | "homepage": "https://willviles.github.io/ember-scrollmagic", 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/willviles/ember-scrollmagic.git" 35 | }, 36 | "scripts": { 37 | "build": "ember build", 38 | "start": "ember server", 39 | "test": "ember try:each", 40 | "deploy": "ember github-pages:commit --message \"Deploy gh-pages from commit $(git rev-parse HEAD)\"; git push; git checkout master" 41 | }, 42 | "dependencies": { 43 | "broccoli-debug": "^0.6.3", 44 | "ember-cli-babel": "^6.6.0", 45 | "ember-cli-htmlbars": "^2.0.1", 46 | "fastboot-transform": "^0.1.2", 47 | "scrollmagic": "^2.0.5" 48 | }, 49 | "devDependencies": { 50 | "broccoli-asset-rev": "^2.4.5", 51 | "ember-ajax": "^3.0.0", 52 | "ember-cli": "~2.17.1", 53 | "ember-cli-app-version": "^2.0.0", 54 | "ember-cli-autoprefixer": "^0.8.1", 55 | "ember-cli-dependency-checker": "^2.0.0", 56 | "ember-cli-document-title": "^0.3.3", 57 | "ember-cli-eslint": "^4.2.1", 58 | "ember-cli-fastboot": "1.1.0", 59 | "ember-cli-github-pages": "^0.1.2", 60 | "ember-cli-head": "^0.3.1", 61 | "ember-cli-htmlbars-inline-precompile": "^1.0.0", 62 | "ember-cli-inject-live-reload": "^1.4.1", 63 | "ember-cli-markdown-resolver": "0.1.1", 64 | "ember-cli-qunit": "^4.1.1", 65 | "ember-cli-sass": "~6.2.0", 66 | "ember-cli-sassdash": "^0.2.3", 67 | "ember-cli-shims": "^1.2.0", 68 | "ember-cli-showdown": "^4.1.0", 69 | "ember-cli-sri": "^2.1.0", 70 | "ember-cli-uglify": "^2.0.0", 71 | "ember-code-prettify": "^0.0.1", 72 | "ember-composable-helpers": "^2.0.3", 73 | "ember-concurrency": "^0.8.10", 74 | "ember-config-service": "^0.1.6", 75 | "ember-disable-prototype-extensions": "^1.1.2", 76 | "ember-export-application-global": "^2.0.0", 77 | "ember-gsap": "1.0.0", 78 | "ember-load-initializers": "^1.0.0", 79 | "ember-math-helpers": "^2.2.3", 80 | "ember-resolver": "^4.0.0", 81 | "ember-responsive": "^2.0.5", 82 | "ember-router-scroll": "^0.4.0", 83 | "ember-try": "0.2.22", 84 | "loader.js": "^4.2.3", 85 | "bower": "^1.8.2" 86 | }, 87 | "engines": { 88 | "node": "6.* || >= 7.*" 89 | }, 90 | "ember-addon": { 91 | "configPath": "tests/dummy/config", 92 | "demoURL": "https://willviles.github.io/ember-scrollmagic/#/documentation/examples", 93 | "after": [ 94 | "ember-gsap" 95 | ] 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /testem.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = { 3 | test_page: 'tests/index.html?hidepassed', 4 | disable_watching: true, 5 | launch_in_ci: [ 6 | 'Chrome' 7 | ], 8 | launch_in_dev: [ 9 | 'Chrome' 10 | ], 11 | browser_args: { 12 | Chrome: { 13 | mode: 'ci', 14 | args: [ 15 | '--disable-gpu', 16 | '--headless', 17 | '--remote-debugging-port=9222', 18 | '--window-size=1440,900' 19 | ] 20 | }, 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /tests/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | embertest: true 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /tests/dummy/app/app.js: -------------------------------------------------------------------------------- 1 | import Application from '@ember/application'; 2 | import Resolver from './resolver'; 3 | import loadInitializers from 'ember-load-initializers'; 4 | import config from './config/environment'; 5 | 6 | const App = Application.extend({ 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix, 9 | Resolver 10 | }); 11 | 12 | loadInitializers(App, config.modulePrefix); 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /tests/dummy/app/breakpoints.js: -------------------------------------------------------------------------------- 1 | export default { 2 | mobile: '(max-width: 767px)', 3 | tablet: '(min-width: 768px) and (max-width: 991px)', 4 | desktop: '(min-width: 992px)' 5 | }; 6 | -------------------------------------------------------------------------------- /tests/dummy/app/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/app/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/components/markdown-content.js: -------------------------------------------------------------------------------- 1 | import { computed, get } from '@ember/object'; 2 | import { scheduleOnce } from '@ember/runloop'; 3 | import { inject } from '@ember/service'; 4 | 5 | import ShowdownComponent from 'ember-cli-showdown/components/markdown-to-html'; 6 | 7 | export default ShowdownComponent.extend({ 8 | codePrettify: inject(), 9 | 10 | classNames: ['markdown-content'], 11 | 12 | html: computed('markdown', 'converter', function() { 13 | scheduleOnce('afterRender', this, function() { 14 | get(this, 'codePrettify').prettify(); 15 | }); 16 | 17 | return this._super(...arguments); 18 | }).readOnly() 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /tests/dummy/app/components/ui-button-link-to.js: -------------------------------------------------------------------------------- 1 | import Mixin from '@ember/object/mixin'; 2 | import LinkComponent from '@ember/routing/link-component'; 3 | 4 | import { DefaultButtonMixin } from 'dummy/components/ui-button'; 5 | 6 | export let LinkToButtonMixin = Mixin.create( 7 | DefaultButtonMixin, { 8 | classNames: ['btn-link-to'] 9 | }); 10 | 11 | export default LinkComponent.extend(LinkToButtonMixin); 12 | -------------------------------------------------------------------------------- /tests/dummy/app/components/ui-button-link.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | 3 | import { DefaultButtonMixin } from 'dummy/components/ui-button'; 4 | 5 | const ButtonLinkComponent = Component.extend( 6 | DefaultButtonMixin, { 7 | 8 | tagName: 'a', 9 | classNames: ['btn-link'], 10 | attributeBindings: ['target', 'href'] 11 | }); 12 | 13 | ButtonLinkComponent.reopenClass({ 14 | positionalParams: ['linkTitle'] 15 | }); 16 | 17 | export default ButtonLinkComponent; 18 | -------------------------------------------------------------------------------- /tests/dummy/app/components/ui-button.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import Mixin from '@ember/object/mixin'; 3 | 4 | import AlignMixin from 'dummy/mixins/ui/align-mixin'; 5 | import ColorMixin from 'dummy/mixins/ui/color-mixin'; 6 | import DepthMixin from 'dummy/mixins/ui/depth-mixin'; 7 | import FontSizeMixin from 'dummy/mixins/ui/font-size-mixin'; 8 | import PaddingMixin from 'dummy/mixins/ui/padding-mixin'; 9 | import layout from 'dummy/templates/components/ui-button'; 10 | 11 | export let DefaultButtonMixin = Mixin.create( 12 | AlignMixin, 13 | ColorMixin, 14 | DepthMixin, 15 | FontSizeMixin, 16 | PaddingMixin, { 17 | 18 | layout, 19 | 20 | tagName: 'button', 21 | classNames: ['button'], 22 | classNameBindings: ['inline', 'rounded'], 23 | attributeBindings: ['name:data-button'], 24 | 25 | rounded: true 26 | }); 27 | 28 | 29 | export default Component.extend(DefaultButtonMixin); 30 | -------------------------------------------------------------------------------- /tests/dummy/app/components/ui-navbar.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | 3 | export default Component.extend({ 4 | tagName: 'nav', 5 | classNames: ['navbar'], 6 | classNameBindings: ['fixed:fixed:unfixed'], 7 | attributeBindings: ['name:data-name'], 8 | 9 | fixed: true 10 | }) 11 | -------------------------------------------------------------------------------- /tests/dummy/app/components/ui-panel.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import Mixin from '@ember/object/mixin'; 3 | 4 | import AlignMixin from 'dummy/mixins/ui/align-mixin'; 5 | import ColorMixin from 'dummy/mixins/ui/color-mixin'; 6 | import DepthMixin from 'dummy/mixins/ui/depth-mixin'; 7 | import FontSizeMixin from 'dummy/mixins/ui/font-size-mixin'; 8 | import PaddingMixin from 'dummy/mixins/ui/padding-mixin'; 9 | import layout from 'dummy/templates/components/ui-panel'; 10 | 11 | export let DefaultPanelMixin = Mixin.create( 12 | AlignMixin, 13 | ColorMixin, 14 | DepthMixin, 15 | FontSizeMixin, 16 | PaddingMixin, { 17 | 18 | layout, 19 | 20 | classNames: ['panel'], 21 | classNameBindings: ['inline', 'rounded'], 22 | attributeBindings: ['name:data-panel'], 23 | 24 | rounded: true 25 | }); 26 | 27 | 28 | export default Component.extend(DefaultPanelMixin); 29 | -------------------------------------------------------------------------------- /tests/dummy/app/components/ui-section.js: -------------------------------------------------------------------------------- 1 | import Component from '@ember/component'; 2 | import Mixin from '@ember/object/mixin'; 3 | 4 | import AlignMixin from 'dummy/mixins/ui/align-mixin'; 5 | import ColorMixin from 'dummy/mixins/ui/color-mixin'; 6 | import DepthMixin from 'dummy/mixins/ui/depth-mixin'; 7 | import FontSizeMixin from 'dummy/mixins/ui/font-size-mixin'; 8 | import PaddingMixin from 'dummy/mixins/ui/padding-mixin'; 9 | 10 | export const DefaultSectionBaseLayer = Mixin.create( 11 | AlignMixin, 12 | ColorMixin, 13 | DepthMixin, 14 | FontSizeMixin, 15 | PaddingMixin, { 16 | 17 | classNames: ['section'], 18 | name: '' 19 | 20 | }) 21 | 22 | export default Component.extend(DefaultSectionBaseLayer, { 23 | tagName: 'section', 24 | attributeBindings: ['name:data-section'] 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/app/controllers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/controllers/application.js: -------------------------------------------------------------------------------- 1 | import Controller from '@ember/controller'; 2 | import { inject as service } from '@ember/service'; 3 | 4 | export default Controller.extend({ 5 | config: service() 6 | }); 7 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/documentation/examples/example.js: -------------------------------------------------------------------------------- 1 | import Controller from '@ember/controller'; 2 | import { default as EmberObject, computed, get, set } from '@ember/object'; 3 | import { readOnly } from '@ember/object/computed'; 4 | import { inject as service } from '@ember/service'; 5 | 6 | import { TweenLite } from 'gsap'; 7 | 8 | export default Controller.extend({ 9 | 10 | scrollMagic: service(), 11 | 12 | example: readOnly('model.example'), 13 | nextExample: readOnly('model.nextExample'), 14 | 15 | init() { 16 | this._super(...arguments); 17 | 18 | set(this, 'interactivity', EmberObject.create({ 19 | 'basic-animations': { 20 | duration: 100, 21 | durationPercentage: computed('duration', function() { 22 | return `${get(this, 'duration')}%`; 23 | }), 24 | triggerHook: 0.75 25 | }, 26 | 'pinned-items': { 27 | scrollToTop() { 28 | TweenLite.to(window, 0.5, { scrollTo: 0 }); 29 | } 30 | } 31 | })); 32 | }, 33 | 34 | props: computed('example', function() { 35 | let slug = get(this, 'example.slug'); 36 | return get(this, `interactivity.${slug}`); 37 | }) 38 | 39 | }) 40 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/documentation/examples/index.js: -------------------------------------------------------------------------------- 1 | import Controller from '@ember/controller'; 2 | import { readOnly } from '@ember/object/computed'; 3 | 4 | export default Controller.extend({ 5 | 6 | examples: readOnly('model.examples') 7 | 8 | }) 9 | -------------------------------------------------------------------------------- /tests/dummy/app/examples.js: -------------------------------------------------------------------------------- 1 | import { assign } from '@ember/polyfills'; 2 | import { dasherize } from '@ember/string'; 3 | 4 | let definitions = [{ 5 | title: 'Basic Animations', 6 | description: `Build beautiful on-scroll animations using just HTMLbars templates. Fade, fly, zoom and toggle classes using Ember ScrollMagic's components.` 7 | }, { 8 | title: 'Responsive Animations', 9 | description: `Add or remove animation scenes responsively with Ember ScrollMagic's integration with popular addon Ember Responsive.` 10 | }, { 11 | title: 'Custom Animations', 12 | description: `Create complex, custom animations using GSAP timelines and attach them via Ember ScrollMagic's well defined primitives.` 13 | }, { 14 | title: 'Pinned Items', 15 | description: `Use Ember ScrollMagic's out-of-the-box pin component to create 'sticky' sections which stay fixed throughout your page. Perfect for navigation menus!` 16 | }, { 17 | title: 'Parallax Sections', 18 | description: 'Coming soon...' 19 | }, { 20 | title: 'Section Wipes & Slides', 21 | description: 'Coming soon...' 22 | }, { 23 | title: 'Component Scrolling', 24 | description: 'Coming soon...' 25 | }, { 26 | title: 'Horizontal Scrolling', 27 | description: 'Coming soon...' 28 | }]; 29 | 30 | export const examples = definitions.map(example => { 31 | return assign({}, example, { 32 | slug: dasherize(example.title) 33 | }); 34 | }) 35 | 36 | export default examples; 37 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/components.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Components 3 | order: 2 4 | --- 5 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/components/animated.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Animated 3 | order: 0 4 | --- 5 | 6 | 7 | [→ addon/components/animated-item.js](https://github.com/willviles/ember-scrollmagic/blob/master/addon/components/animated-item.js) 8 | 9 | 10 | The `scrollmagic-animated` component can have a name of an animation passed to it, along with all `ScrollMagic.Scene` options. For example: 11 | 12 | ```hbs 13 | {{scrollmagic-animated 14 | animation="fade" 15 | duration="100%" 16 | offset=100 17 | triggerElement=triggerElement 18 | triggerHook="onCenter" 19 | loglevel=3 20 | indicators=true 21 | reverse=false 22 | }} 23 | ``` 24 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/components/pinned.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Pinned 3 | order: 1 4 | --- 5 | 6 | 7 | [→ addon/components/pinned-item.js](https://github.com/willviles/ember-scrollmagic/blob/master/addon/components/pinned-item.js) 8 | 9 | 10 | The `scrollmagic-pinned` component simply requires a duration passed to it. It accepts all other `ScrollMagic.Scene` options too. By default, the pin pushes all following elements. 11 | 12 | ```hbs 13 | {{#scrollmagic-pinned duration="100%"}} 14 | Pinned and pushes content down! 15 | {{/scrollmagic-pinned}} 16 | ``` 17 | 18 | To disable the ScrollMagic `pushFollowers` value, simply pass `pinOptions` to the component. You can also alter the `spacerClass` value: 19 | 20 | ```hbs 21 | 22 | {{#scrollmagic-pinned 23 | duration=0 24 | pinOptions=(hash 25 | pushFollowers=false 26 | spacerClass=".custom-spacer-class" 27 | )}} 28 | Pinned and overlays content! 29 | {{/scrollmagic-pinned}} 30 | ``` 31 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/components/toggle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Toggle 3 | order: 2 4 | --- 5 | 6 | 7 | [→ addon/components/toggle-item.js](https://github.com/willviles/ember-scrollmagic/blob/master/addon/components/toggle-item.js) 8 | 9 | 10 | The `scrollmagic-toggle` component toggles classes on/off the component. 11 | 12 | ```hbs 13 | {{scrollmagic-toggle 14 | toggleClasses="scrolled-to" 15 | toggleClassesOff="scrolled-past" 16 | }} 17 | ``` 18 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/custom-usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Usage 3 | order: 2 4 | --- 5 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/custom-usage/animations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Animation Timelines 3 | order: 0 4 | --- 5 | 6 | Extend the Ember ScrollMagic `animated-item` component and override the `timeline` function with your custom timeline. The example below shows how a simple fade timeline is defined. 7 | 8 | ```javascript 9 | import ScrollMagicAnimatedItem from 'ember-scrollmagic/components/animated-item'; 10 | 11 | export default ScrollMagicAnimatedItem.extend({ 12 | 13 | timeline() { 14 | return new TimelineMax().add( 15 | TweenLite.fromTo(this.element, 1, { 16 | opacity: 0 17 | }, { 18 | opacity: 1 19 | }) 20 | ); 21 | } 22 | 23 | }); 24 | ``` 25 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/custom-usage/components.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Components 3 | order: 1 4 | --- 5 | 6 | #### Custom Components 7 | 8 | Ember ScrollMagic offers a `component-scene-mixin`, which prescribes a method of organizing component animations, exposes scene events as actions and adds and removes the scene to/from the scroll controller using the appropriate component lifecycle hooks. 9 | 10 | ```javascript 11 | import Component from '@ember/component'; 12 | import ScrollMagicComponentMixin from 'ember-scrollmagic/mixins/component-scene-mixin'; 13 | 14 | export default Component.extend( 15 | ScrollMagicComponentMixin, { 16 | 17 | setupScene() { 18 | let opts = get(this, 'mergedOptions'), 19 | scene = new ScrollMagic.Scene(opts); 20 | 21 | // Whatever you want to do with the scene 22 | 23 | return scene; 24 | } 25 | 26 | }); 27 | ``` 28 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Ember ScrollMagic 3 | inTree: false 4 | --- 5 | 6 | Ember ScrollMagic is an Ember addon for using [ScrollMagic](https://github.com/janpaepke/ScrollMagic) - the javascript library for magical scroll interactions. 7 | 8 | ##### About the guides 9 | 10 | 11 | These guides are generated using the [Ember CLI Markdown Resolver](https://github.com/willviles/ember-cli-markdown-resolver) addon. Check it out! 12 | 13 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/install.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | order: 0 4 | --- 5 | 6 | ScrollMagic uses [GSAP (Greensock Animation Platform)](https://github.com/greensock/GreenSock-JS) for full animation tweening. Ember ScrollMagic will automatically install [Ember GSAP](https://github.com/willviles/ember-gsap) into your application. 7 | 8 | ``` 9 | ember install ember-scrollmagic 10 | ``` 11 | 12 | #### Configuration 13 | 14 | To include the indicator plugin, add the following to your `config/environment.js` file. 15 | 16 | ```javascript 17 | ENV['ember-scrollmagic'] = { 18 | indicators: true 19 | }; 20 | ``` 21 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/scroll-controllers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Scroll Controllers 3 | order: 1 4 | --- 5 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/scroll-controllers/application.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Application 3 | order: 0 4 | --- 5 | 6 | #### Application Route Mixin 7 | 8 | 9 | [→ addon/mixins/scroll-controllers/route-mixin.js](https://github.com/willviles/ember-scrollmagic/blob/master/addon/mixins/scroll-controllers/route-mixin.js) 10 | 11 | 12 | By default, Ember ScrollMagic will register all ScrollMagic scenes to a scroll controller named `application`. 13 | 14 | It needs to be registered in your `routes/application.js`: 15 | 16 | ```javascript 17 | import Route from '@ember/routing/route'; 18 | import ScrollControllerRouteMixin from 'ember-scrollmagic/mixins/scroll-controllers/route-mixin'; 19 | 20 | export default Route.extend( 21 | ScrollControllerRouteMixin, { 22 | 23 | }); 24 | ``` 25 | 26 | Now, all scenes without a custom scroll controller attached to them will register and deregister from the application scroll controller. 27 | -------------------------------------------------------------------------------- /tests/dummy/app/guides/scroll-controllers/components.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Components 3 | order: 1 4 | --- 5 | 6 | #### Component Mixin 7 | 8 | 9 | [→ addon/mixins/scroll-controllers/component-mixin.js](https://github.com/willviles/ember-scrollmagic/blob/master/addon/mixins/scroll-controllers/component-mixin.js) 10 | 11 | 12 | It's also possible to register scroll controllers on individual components, which will ensure the scroll is scoped to that particular element's scroll position. 13 | 14 | The mixin registers a `ScrollMagic.Controller` instance on `willRender` and removes it on `willDestroyElement`. It sets the property `scrollController` to the newly created `ScrollMagic.Controller` instance, which can then be used to register scenes. 15 | 16 | ```javascript 17 | import Route from '@ember/routing/route'; 18 | import ScrollControllerComponentMixin from 'ember-scrollmagic/mixins/scroll-controllers/component-mixin'; 19 | 20 | export default Route.extend( 21 | ScrollControllerComponentMixin, { 22 | 23 | registerScenes() { 24 | let scrollController = get(this, 'scrollController'); 25 | // ... 26 | } 27 | }); 28 | ``` 29 | -------------------------------------------------------------------------------- /tests/dummy/app/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/app/helpers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{content-for "head"}} 9 | 10 | 11 | 12 | 13 | {{content-for "head-footer"}} 14 | 15 | 16 | {{content-for "body"}} 17 | 18 | 19 | 20 | 21 | {{content-for "body-footer"}} 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/dummy/app/initializers/responsive.js: -------------------------------------------------------------------------------- 1 | import { initialize } from 'ember-responsive/initializers/responsive'; 2 | 3 | /** 4 | * Ember responsive initializer 5 | * 6 | * Supports auto injecting media service app-wide. 7 | * 8 | * Generated by the ember-responsive addon. Customize initialize to change 9 | * injection. 10 | */ 11 | 12 | export default { 13 | name: 'responsive', 14 | initialize 15 | }; 16 | -------------------------------------------------------------------------------- /tests/dummy/app/initializers/showdown.js: -------------------------------------------------------------------------------- 1 | import showdown from 'showdown'; 2 | 3 | export function initialize() { 4 | showdown.extension('prettify', function() { 5 | return [{ 6 | type: 'output', 7 | filter(source) { 8 | return source.replace(/(]*>)?[\n\s]?]*)>/gi, (match, pre, codeClass) => { 9 | return pre ? 10 | `
` :
11 |             ` `;
12 |         });
13 |       }
14 |     }];
15 |   });
16 | }
17 | 
18 | export default {
19 |   name: 'register-showdown-extensions',
20 |   initialize
21 | };
22 | 


--------------------------------------------------------------------------------
/tests/dummy/app/initializers/urls.js:
--------------------------------------------------------------------------------
 1 | /* eslint ember/alias-model-in-controller: 0 */
 2 | import Component from '@ember/component';
 3 | import Controller from '@ember/controller';
 4 | import { computed, get } from '@ember/object';
 5 | import { readOnly } from '@ember/object/computed';
 6 | import Route from '@ember/routing/route';
 7 | import { inject as service } from '@ember/service';
 8 | 
 9 | export function initialize() {
10 |   let URLMixin = {
11 |     config: service(),
12 |     fastboot: service(),
13 |     baseURL: computed(function() {
14 |       if (get(this, 'fastboot.isFastBoot')) {
15 |         let protocol = get(this, 'fastboot.request.protocol');
16 |         let host = get(this, 'fastboot.request.host');
17 |         return `${protocol}://${host}`;
18 |       } else {
19 |         let pathArray = window.location.href.split('/');
20 |         return `${pathArray[0]}//${pathArray[2]}`;
21 |       }
22 |     }),
23 |     rootURL: readOnly('config.rootURL')
24 |   };
25 | 
26 |   Component.reopen(URLMixin);
27 |   Controller.reopen(URLMixin);
28 |   Route.reopen(URLMixin);
29 | 
30 |   URLMixin = null;
31 | 
32 |   Route.reopen({
33 |     fastboot: service(),
34 |     routeURL: computed(function() {
35 |       return get(this, 'fastboot.isFastBoot') ?
36 |         `${get(this, 'baseURL')}${get(this, 'rootURL')}${get(this, 'fastboot.request.path')}` :
37 |         window.location.href;
38 |     })
39 |   });
40 | 
41 | }
42 | 
43 | export default {
44 |   name: 'inject-urls',
45 |   initialize
46 | };
47 | 


--------------------------------------------------------------------------------
/tests/dummy/app/instance-initializers/head-data.js:
--------------------------------------------------------------------------------
 1 | import { get, set, setProperties } from '@ember/object';
 2 | import { assign } from '@ember/polyfills';
 3 | import Route from '@ember/routing/route';
 4 | import Router from '@ember/routing/router';
 5 | import { inject } from '@ember/service';
 6 | import { typeOf } from '@ember/utils';
 7 | 
 8 | export function initialize() {
 9 | 
10 |   Router.reopen({
11 |     headData: inject(),
12 |     setTitle(title) { set(get(this, 'headData'), 'title', title); }
13 |   });
14 | 
15 |   Route.reopen({
16 |     headData: inject(),
17 |     afterModel(model) {
18 |       this._super(...arguments);
19 |       if (typeOf(this.metadata) === 'function') {
20 |         const metadata = this.metadata(model);
21 |         const url = get(this, 'routeURL');
22 |         setProperties(get(this, 'headData'), assign(metadata, { url }));
23 |       }
24 |     }
25 |   });
26 | 
27 | }
28 | 
29 | export default {
30 |   name: 'head-data',
31 |   initialize
32 | };
33 | 


--------------------------------------------------------------------------------
/tests/dummy/app/instance-initializers/inject-config.js:
--------------------------------------------------------------------------------
 1 | import Component from '@ember/component';
 2 | import Controller from '@ember/controller';
 3 | import { computed } from '@ember/object';
 4 | import Mixin from '@ember/object/mixin';
 5 | import Route from '@ember/routing/route';
 6 | import ENV from 'dummy/config/environment';
 7 | 
 8 | const { rootURL } = ENV;
 9 | 
10 | export function initialize(appInstance) {
11 |   let fastbootService = appInstance.lookup('service:fastboot');
12 |   let isFastBoot = fastbootService && fastbootService.get('isFastBoot');
13 | 
14 |   let baseURL;
15 | 
16 |   if (isFastBoot) {
17 |     let protocol = fastbootService.get('request.protocol');
18 |     let host = fastbootService.get('request.host');
19 |     baseURL = `${protocol}://${host}`;
20 | 
21 |   } else {
22 |     let pathArray = window.location.href.split('/');
23 |     baseURL = `${pathArray[0]}//${pathArray[2]}`;
24 | 
25 |   }
26 | 
27 |   let URLMixin = Mixin.create({
28 |     baseURL, rootURL
29 |   });
30 | 
31 |   let RouteURLMixin = Mixin.create({
32 |     routeURL: computed(function() {
33 |       return isFastBoot ?
34 |         `${baseURL}${rootURL}${fastbootService.get('request.path')}` :
35 |         window.location.href;
36 |     })
37 | 
38 |   });
39 | 
40 |   Component.reopen(URLMixin);
41 |   Controller.reopen(URLMixin);
42 |   Route.reopen(URLMixin, RouteURLMixin);
43 | 
44 | }
45 | 
46 | export default {
47 |   name: 'urls',
48 |   initialize
49 | };
50 | 


--------------------------------------------------------------------------------
/tests/dummy/app/mixins/ui/align-mixin.js:
--------------------------------------------------------------------------------
 1 | import Mixin from '@ember/object/mixin';
 2 | 
 3 | import propertyClassNameBinding from 'dummy/utils/property-class-name-binding';
 4 | 
 5 | export default Mixin.create({
 6 | 
 7 |   classNameBindings: ['_align'],
 8 | 
 9 |   align: false,
10 |   _align: propertyClassNameBinding('align')
11 | 
12 | });
13 | 


--------------------------------------------------------------------------------
/tests/dummy/app/mixins/ui/color-mixin.js:
--------------------------------------------------------------------------------
 1 | import Mixin from '@ember/object/mixin';
 2 | 
 3 | import propertyClassNameBinding from 'dummy/utils/property-class-name-binding';
 4 | 
 5 | export default Mixin.create({
 6 | 
 7 |   classNameBindings: ['_bg', '_bgHover', '_color', '_colorHover'],
 8 | 
 9 |   bg: false,
10 |   _bg: propertyClassNameBinding('bg'),
11 | 
12 |   bgHover: false,
13 |   _bgHover: propertyClassNameBinding('bgHover'),
14 | 
15 |   color: false,
16 |   _color: propertyClassNameBinding('color'),
17 | 
18 |   colorHover: false,
19 |   _colorHover: propertyClassNameBinding('colorHover')
20 | 
21 | });
22 | 


--------------------------------------------------------------------------------
/tests/dummy/app/mixins/ui/depth-mixin.js:
--------------------------------------------------------------------------------
 1 | import Mixin from '@ember/object/mixin';
 2 | 
 3 | import propertyClassNameBinding from 'dummy/utils/property-class-name-binding';
 4 | 
 5 | export default Mixin.create({
 6 | 
 7 |   classNameBindings: ['_depth', '_depthHover'],
 8 | 
 9 |   depth: false,
10 |   _depth: propertyClassNameBinding('depth'),
11 | 
12 |   depthHover: false,
13 |   _depthHover: propertyClassNameBinding('depthHover')
14 | 
15 | });
16 | 


--------------------------------------------------------------------------------
/tests/dummy/app/mixins/ui/font-size-mixin.js:
--------------------------------------------------------------------------------
 1 | import Mixin from '@ember/object/mixin';
 2 | 
 3 | import propertyClassNameBinding from 'dummy/utils/property-class-name-binding';
 4 | 
 5 | export default Mixin.create({
 6 | 
 7 |   classNameBindings: ['_fontSize'],
 8 | 
 9 |   fontSize: false,
10 |   _fontSize: propertyClassNameBinding('fontSize')
11 | 
12 | });
13 | 


--------------------------------------------------------------------------------
/tests/dummy/app/mixins/ui/padding-mixin.js:
--------------------------------------------------------------------------------
 1 | import Mixin from '@ember/object/mixin';
 2 | 
 3 | import propertyClassNameBinding from 'dummy/utils/property-class-name-binding';
 4 | 
 5 | export default Mixin.create({
 6 | 
 7 |   classNameBindings: ['_padding'],
 8 | 
 9 |   padding: false,
10 |   _padding: propertyClassNameBinding('padding', {
11 |     values: ['top', 'right', 'bottom', 'left']
12 |   })
13 | 
14 | });
15 | 


--------------------------------------------------------------------------------
/tests/dummy/app/mixins/ui/size-mixin.js:
--------------------------------------------------------------------------------
 1 | import Mixin from '@ember/object/mixin';
 2 | 
 3 | import propertyClassNameBinding from 'dummy/utils/property-class-name-binding';
 4 | 
 5 | export default Mixin.create({
 6 | 
 7 |   classNameBindings: ['_size'],
 8 | 
 9 |   size: false,
10 |   _size: propertyClassNameBinding('size')
11 | 
12 | });
13 | 


--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/app/models/.gitkeep


--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 | 
3 | export default Resolver;
4 | 


--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
 1 | import EmberRouter from '@ember/routing/router';
 2 | import config from './config/environment';
 3 | 
 4 | import RouterScroll from 'ember-router-scroll';
 5 | 
 6 | const Router = EmberRouter.extend(
 7 |   RouterScroll, {
 8 |   location: config.locationType,
 9 |   rootURL: config.rootURL
10 | });
11 | 
12 | Router.map(function() {
13 | 
14 |   this.route('documentation', function() {
15 |     this.route('guides', function() {
16 |       this.route('single', { path: '/*path' });
17 |     });
18 | 
19 |     this.route('examples', function() {
20 |       this.route('example', { path: '/:example_slug'});
21 |     });
22 |   });
23 | 
24 | });
25 | 
26 | export default Router;
27 | 


--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/app/routes/.gitkeep


--------------------------------------------------------------------------------
/tests/dummy/app/routes/application.js:
--------------------------------------------------------------------------------
 1 | import Route from '@ember/routing/route';
 2 | import { getProperties } from '@ember/object';
 3 | 
 4 | import ScrollControllerRouteMixin from 'ember-scrollmagic/mixins/scroll-controllers/route-mixin';
 5 | 
 6 | export default Route.extend(
 7 |   ScrollControllerRouteMixin, {
 8 | 
 9 |   title(tokens) {
10 |     return tokens.length ?
11 |       `${tokens.join(' – ')} – Ember ScrollMagic` :
12 |       'Ember ScrollMagic';
13 |   },
14 | 
15 |   metadata() {
16 |     let { baseURL, rootURL } = getProperties(this, 'baseURL', 'rootURL');
17 |     return {
18 |       appName: `Ember ScrollMagic`,
19 |       description: `An Ember addon for using ScrollMagic - the javascript library for magical scroll interactions.`,
20 |       keywords: `ember-addon, scrollMagic, scroll, scrolling, animation, sticky, pin, fixed, scrollbar, scrub, sync, position, progress, parallax`,
21 |       image: `${baseURL}${rootURL}images/facebook.jpg`,
22 |       favicon: `${baseURL}${rootURL}images/favicon`
23 |     };
24 |   }
25 | 
26 | });
27 | 


--------------------------------------------------------------------------------
/tests/dummy/app/routes/documentation/examples.js:
--------------------------------------------------------------------------------
1 | import Route from '@ember/routing/route';
2 | 
3 | export default Route.extend({
4 | 
5 |   titleToken: 'Examples'
6 |   
7 | });
8 | 


--------------------------------------------------------------------------------
/tests/dummy/app/routes/documentation/examples/example.js:
--------------------------------------------------------------------------------
 1 | import Route from '@ember/routing/route';
 2 | import { A } from '@ember/array';
 3 | import { get } from '@ember/object';
 4 | import { hash, reject } from 'rsvp';
 5 | 
 6 | import { examples } from '../../../examples';
 7 | 
 8 | export default Route.extend({
 9 | 
10 |   titleToken({ example }) {
11 |     return get(example, 'title');
12 |   },
13 | 
14 |   model({ example_slug: slug }) {
15 |     let examplesRegistry = A(examples),
16 |         nextExample;
17 | 
18 |     let example = examplesRegistry.find((example, i) => {
19 |       let e = get(example, 'slug') === slug;
20 |       nextExample = examplesRegistry.objectAt(i + 1);
21 |       return e;
22 |     });
23 | 
24 |     if (!example) { return reject(); }
25 | 
26 |     return hash({
27 |       example,
28 |       nextExample
29 |     });
30 |   },
31 | 
32 |   renderTemplate(controller, model) {
33 |     let exampleSlug = get(model, 'example.slug');
34 | 
35 |     this.render(`documentation.examples.templates.${exampleSlug}`);
36 |     this.render(`documentation.examples.partials.next-example`, {
37 |       controller,
38 |       outlet: 'next-example'
39 |     })
40 |   }
41 | 
42 | })
43 | 


--------------------------------------------------------------------------------
/tests/dummy/app/routes/documentation/examples/index.js:
--------------------------------------------------------------------------------
 1 | import Route from '@ember/routing/route';
 2 | import { hash } from 'rsvp';
 3 | 
 4 | import { examples } from '../../../examples';
 5 | 
 6 | export default Route.extend({
 7 | 
 8 |   model() {
 9 |     return hash({
10 |       examples
11 |     })
12 |   }
13 | 
14 | });
15 | 


--------------------------------------------------------------------------------
/tests/dummy/app/routes/documentation/guides.js:
--------------------------------------------------------------------------------
 1 | import Route from '@ember/routing/route';
 2 | import { get } from '@ember/object';
 3 | import { inject } from '@ember/service';
 4 | import RSVP from 'rsvp';
 5 | 
 6 | const { hash } = RSVP;
 7 | 
 8 | export default Route.extend({
 9 | 
10 |   titleToken: 'Guides',
11 | 
12 |   markdownResolver: inject(),
13 | 
14 |   model() {
15 |     return hash({
16 |       tree: get(this, 'markdownResolver').tree('guides')
17 |     });
18 |   },
19 | 
20 |   setupController(controller, model) {
21 |     controller.setProperties(model);
22 |   }
23 | 
24 | });
25 | 


--------------------------------------------------------------------------------
/tests/dummy/app/routes/documentation/guides/index.js:
--------------------------------------------------------------------------------
 1 | import Route from '@ember/routing/route';
 2 | import { get } from '@ember/object';
 3 | import { inject } from '@ember/service';
 4 | import RSVP from 'rsvp';
 5 | 
 6 | const { hash } = RSVP;
 7 | 
 8 | export default Route.extend({
 9 | 
10 |   titleToken: 'Introduction',
11 | 
12 |   templateName: 'documentation.guides.single',
13 | 
14 |   markdownResolver: inject(),
15 | 
16 |   model() {
17 |     return hash({
18 |       guide: get(this, 'markdownResolver').file('guides', 'index')
19 |     });
20 |   },
21 | 
22 |   setupController(controller, model) {
23 |     controller.setProperties(model);
24 |   }
25 | 
26 | });
27 | 


--------------------------------------------------------------------------------
/tests/dummy/app/routes/documentation/guides/single.js:
--------------------------------------------------------------------------------
 1 | import Route from '@ember/routing/route';
 2 | import { get } from '@ember/object';
 3 | import { inject } from '@ember/service';
 4 | import RSVP from 'rsvp';
 5 | 
 6 | const { hash } = RSVP;
 7 | 
 8 | export default Route.extend({
 9 | 
10 |   titleToken({ guide }) {
11 |     return get(guide, 'attributes.title');
12 |   },
13 | 
14 |   markdownResolver: inject(),
15 | 
16 |   model({ path }) {
17 |     return hash({
18 |       guide: get(this, 'markdownResolver').file('guides', path)
19 |     });
20 |   },
21 | 
22 |   afterModel({ guide }) {
23 |     if (!guide) {
24 |       this.transitionTo('error', { type: '404' });
25 |     }
26 |   },
27 | 
28 |   setupController(controller, model) {
29 |     controller.setProperties(model);
30 |   }
31 | 
32 | });
33 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/basic-animations/animations.md:
--------------------------------------------------------------------------------
 1 | ### Out-of-the-box Animations
 2 | 
 3 | Pass the name of the animation via the `animation` property.
 4 | 
 5 | ```handlebars
 6 | {{#scrollmagic-animated animation='fade'}}
 7 |   Your content
 8 | {{/scrollmagic-animated}}
 9 | ```
10 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/basic-animations/component-lifecycle-hidden.md:
--------------------------------------------------------------------------------
1 | ### You've Removed Everything!
2 | 
3 | Every `ScrollMagic.Scene` instance and all attached events were torn down gracefully.
4 | 
5 | Why not add everything back?
6 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/basic-animations/component-lifecycle.md:
--------------------------------------------------------------------------------
1 | ### Component Lifecycle
2 | 
3 | All `ScrollMagic.Scene` instances are attached to `ScrollMagic.Controller` instances using Ember Component lifecycle hooks.
4 | 
5 | Give it a try... 
6 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/basic-animations/dynamic-properties.md:
--------------------------------------------------------------------------------
 1 | ### Dynamic Properties
 2 | 
 3 | All `ScrollMagic.Scene` properties can have dynamic values attached to them. Updating a property will automatically refresh the scene.
 4 | 
 5 | ```hbs
 6 | {{#scrollmagic-animated
 7 |   animation='fly-horizontal'
 8 |   duration=duration
 9 |   triggerHook=triggerHook }}
10 |   Your content
11 | {{/scrollmagic-animated}}
12 | ```
13 | 
14 | Update the `duration` and `triggerHook` values below to see how the spaceship scene is affected in real-time:
15 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/basic-animations/indicators.md:
--------------------------------------------------------------------------------
 1 | ### Indicators
 2 | 
 3 | Add generated indicators by defining `indicators=true`.
 4 | 
 5 | ```handlebars
 6 | {{#scrollmagic-animated indicators=true}}
 7 |   Your content
 8 | {{/scrollmagic-animated}}
 9 | ```
10 | 
11 | Or add custom indicators by passing a hash.
12 | 
13 | ```handlebars
14 | {{#scrollmagic-animated
15 |   indicators=(hash
16 |     name='Check out these indicators!'
17 |     colorStart='#1682fc'
18 |     colorEnd='#1682fc'
19 |     colorTrigger='transparent'
20 |   )}}
21 |   Your content
22 | {{/scrollmagic-animated}}
23 | ```
24 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/basic-animations/intro.md:
--------------------------------------------------------------------------------
1 | The `scrollmagic-animated` component accepts all `ScrollMagic.Scene` options and offers a number of animations out-of-the-box, such as `fade`, `fly` and `zoom`.
2 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/basic-animations/reverse.md:
--------------------------------------------------------------------------------
 1 | ### Using reverse: false
 2 | 
 3 | Passing `reverse=false` will ensure that once you've scrolled past the scene, it won't animate again.
 4 | 
 5 | ```hbs
 6 | {{#scrollmagic-animated animation='fade' reverse=false}}
 7 |   Your content
 8 | {{/scrollmagic-animated}}
 9 | ```
10 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/basic-animations/toggle.md:
--------------------------------------------------------------------------------
 1 | ### Toggle Classes
 2 | 
 3 | Use the `scrollmagic-toggle` component to toggle classes on scroll.
 4 | 
 5 | Watch this go blue!
 6 | 
 7 | ```hbs
 8 | {{#scrollmagic-toggle toggleClasses="bg-blue" toggleClassesOff="bg-lt-gray"}}
 9 |   Your content
10 | {{/scrollmagic-toggle}}
11 | ```
12 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/pinned-items/fullscreen-section.md:
--------------------------------------------------------------------------------
 1 | ### Fullscreen Section Example
 2 | 
 3 | Pinned page sections can be created by setting `pushFollowers=true` inside the `pinOptions` hash. You can also give the pin spacer a custom class name.
 4 | 
 5 | ```hbs
 6 | {{#scrollmagic-pinned
 7 |   duration="125%"
 8 |   pinOptions=(hash
 9 |     pushFollowers=true
10 |     spacerClass='custom-pin-spacer-class'
11 |   )}}
12 |   Content
13 | {{/scrollmagic-pinned}}
14 | ```
15 | 
16 | This will ensure any inline content following the section will be pushed down for the duration of the pin. The example below pins for 125% of the viewport height.
17 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/pinned-items/intro.md:
--------------------------------------------------------------------------------
1 | The `scrollmagic-pinned` component is useful for creating fixed navigation menus and pinned items.
2 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/pinned-items/navbar.md:
--------------------------------------------------------------------------------
 1 | ### Navigation Example
 2 | 
 3 | Set the duration to a percentage or absolute pixel value to unpin the component further down the page. The `offset` value can also be set to move the component's pinned position underneath navigation bars or other content.
 4 | 
 5 | ```hbs
 6 | {{#scrollmagic-pinned duration="100%" offset="-50px"}}
 7 |   Content
 8 | {{/scrollmagic-pinned}}
 9 | ```
10 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/pinned-items/scroll-to-top.md:
--------------------------------------------------------------------------------
 1 | ### Scroll-to-Top Button Example
 2 | 
 3 | By default, `duration=0` is set, which will ensure the component is pinned indefinitely.
 4 | 
 5 | ```hbs
 6 | {{#scrollmagic-pinned}}
 7 |   Content
 8 | {{/scrollmagic-pinned}}
 9 | ```
10 | 


--------------------------------------------------------------------------------
/tests/dummy/app/snippets/documentation/examples/templates/responsive-animations/intro.md:
--------------------------------------------------------------------------------
 1 | Ember ScrollMagic's integration with popular addon [Ember Responsive](https://github.com/freshbooks/ember-responsive) allows animation scenes to be enabled or disabled at different `@media screen` breakpoints.
 2 | 
 3 | Firstly, ensure [Ember Responsive](https://github.com/freshbooks/ember-responsive) is installed:
 4 | 
 5 | ```bash
 6 | ember install ember-responsive
 7 | ```
 8 | 
 9 | Then, enabling and disabling scenes is as simple as passing an array of breakpoint keys via the `triggerOnMedia` property.
10 | 
11 | ```handlebars
12 | {{scrollmagic-animated
13 |   animation="fade"
14 |   triggerOnMedia=(array 'desktop')}}
15 | ```
16 | 
17 | Resize the viewport to see the animation below only plays on desktop:
18 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.scss:
--------------------------------------------------------------------------------
 1 | @import 'framework/reset';
 2 | @import 'framework/mixins';
 3 | @import 'sassdash';
 4 | 
 5 | @import 'main/config';
 6 | @import 'components/config';
 7 | 
 8 | @import 'framework/grid';
 9 | @import 'framework/fonts';
10 | @import 'framework/type';
11 | @import 'framework/colors';
12 | @import 'framework/utility';
13 | 
14 | @import 'components/_';
15 | @import 'main/_';
16 | @import 'routes/_';
17 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/_.scss:
--------------------------------------------------------------------------------
1 | @import 'buttons/_';
2 | @import 'footer/_';
3 | @import 'markdown/_';
4 | @import 'navbar/_';
5 | @import 'panels/_';
6 | @import 'sections/_';
7 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/_config.scss:
--------------------------------------------------------------------------------
 1 | // Components config
 2 | 
 3 | $--navbar: (
 4 |   height: (50px, 50px, 60px, 70px, 90px),
 5 |   background-color: _get($--colors, 'blue'),
 6 |   color: _get($--colors, 'white'),
 7 |   item-horiz-padding: (.5rem, .5rem, .66rem, .75rem, .9rem),
 8 |   fixed: false
 9 | );
10 | 
11 | $--buttons: (
12 |   font-size: (.7rem, 1rem, 1.2rem, 1.5rem, 2rem),
13 |   padding: (.5rem, .75rem, 1rem, 2rem, 3rem),
14 |   padding-horiz-ratio: 1.5,
15 |   line-height: (160%, 150%, 140%, 130%, 120%),
16 |   border-radius: .25rem,
17 |   disabled-bg: rgba(_get($--colors, 'lt-gray'), .33),
18 |   disabled-color: rgba(_get($--colors, 'black'), .5)
19 | );
20 | 
21 | $--sections: (
22 |   font-size: (.7rem, .9rem, 1rem, 1.1rem, 1.2rem),
23 |   padding: (3rem, 5rem, 7rem, 10rem, 20rem)
24 | );
25 | 
26 | $--panels: (
27 |   font-size: (.7rem, 1rem, 1.2rem, 1.5rem, 2rem),
28 |   padding: (.5rem, .75rem, 1rem, 2rem, 3rem),
29 |   padding-horiz-ratio: 1.5,
30 |   border-radius: .25rem
31 | );
32 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/buttons/_.scss:
--------------------------------------------------------------------------------
 1 | //----------------------------------------------------------------------
 2 | 
 3 | // Buttons
 4 | //
 5 | 
 6 | button {
 7 |   border: none;
 8 |   padding: 0 0 0 0;
 9 |   background-color: transparent;
10 |   cursor: pointer;
11 |   color: inherit;
12 |   font-size: 100%;
13 |   font-family: inherit;
14 |   font-style: inherit;
15 | 
16 |   &:focus { outline: 0; }
17 |   &.active {
18 |     font-weight: bold;
19 |     text-decoration: underline;
20 |   }
21 | 
22 | }
23 | 
24 | .button {
25 |   display: inline-flex;
26 |   align-items: center;
27 |   cursor: pointer;
28 |   justify-content: center;
29 | 
30 |   &.align-left { justify-content: left; }
31 |   &.align-right { justify-content: right; }
32 | 
33 |   &.rounded {
34 |     border-radius: _get($--buttons, 'border-radius');
35 |   }
36 | 
37 |   &:not(.inline) {
38 |     display: flex;
39 |     width: 100%;
40 |     box-sizing: border-box;
41 |   }
42 | 
43 |   &.transparent {
44 |     background-color: rgba(white, 0);
45 |     color: inherit !important;
46 |   }
47 | 
48 |   @for $i from 1 through length(_get($--grid, 'breakpoints')) {
49 |     $breakpoints: _keys(_get($--grid, 'breakpoints'));
50 |     $breakpoint: nth($breakpoints, $i);
51 | 
52 |     line-height: nth(_get($--buttons, 'line-height'), $i);
53 | 
54 |     &.padding-#{$breakpoint} {
55 |       $padding: nth(_get($--buttons, 'padding'), $i);
56 |       $horiz-ratio: _get($--buttons, 'padding-horiz-ratio');
57 |       padding: $padding #{$padding * $horiz-ratio};
58 |     }
59 | 
60 |     &.font-size-#{$breakpoint} {
61 |       $font-size: nth(_get($--buttons, 'font-size'), $i);
62 |       font-size: $font-size;
63 |     }
64 |   }
65 | 
66 |   @each $name, $hex in $--colors {
67 |     &.bg-#{$name}:not([class*=' bg-hover']):not(:disabled) {
68 |       &:hover { background-color: darken($hex, 5%) !important; }
69 |     }
70 |   }
71 | 
72 |   &:disabled {
73 |     background-color: _get($--buttons, 'disabled-bg') !important;
74 |     color: _get($--buttons, 'disabled-color') !important;
75 |     cursor: auto !important;
76 |   }
77 | 
78 |   &.pending {
79 |     background-color: _get($--buttons, 'pending-bg') !important;
80 |     color: _get($--buttons, 'pending-color') !important;
81 |     cursor: auto;
82 |   }
83 | }
84 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/footer/_.scss:
--------------------------------------------------------------------------------
 1 | footer {
 2 |   padding: 2rem 0 3rem 0;
 3 |   ul {
 4 |     li {
 5 |       display: inline-block;
 6 |       font-size: _get($--type, 'small');
 7 |       margin: .5em .5em;
 8 |       & > a {
 9 |         &.active, &:hover {
10 |           @include set-font('header');
11 |         }
12 |         &.active {
13 |           text-decoration: underline;
14 |         }
15 |       }
16 |     }
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/markdown/_.scss:
--------------------------------------------------------------------------------
  1 | @import 'menu';
  2 | @import 'prettyprint';
  3 | 
  4 | article, .markdown-content {
  5 |   h1, h2, h3, h4, h5, h6 {
  6 |     @include set-font('header');
  7 |     margin-bottom: 1em;
  8 |   }
  9 |   p {
 10 |     a {
 11 |       @include set-font('header');
 12 |       &:hover {
 13 |         text-decoration: underline;
 14 |       }
 15 |     }
 16 |   }
 17 |   .codelink {
 18 |     display: block;
 19 |     background: _get($--colors, 'lt-gray');
 20 |     color: inherit;
 21 |     padding: .2em .5em;
 22 |     border-radius: .25rem;
 23 |     white-space: nowrap;
 24 |     overflow-x: scroll;
 25 |     a {
 26 |       font-size: .8em;
 27 |     }
 28 |   }
 29 |   & > ul, & > ol {
 30 |     @include media-breakpoint-up('sm') {
 31 |       padding-left: _get($--grid, 'margin');
 32 |       padding-right: _get($--grid, 'margin');
 33 |     }
 34 |   }
 35 |   ul, ol {
 36 |     font-size: 1.2rem;
 37 |     ul, ol {
 38 |       margin-left: 2rem;
 39 |       font-size: 0.8em;
 40 |     }
 41 |     li {
 42 |       line-height: 2em;
 43 |       list-style-position: inside;
 44 |       & > p {
 45 |         display: inline-block;
 46 |         font-size: inherit;
 47 |       }
 48 |     }
 49 |   }
 50 |   ol {
 51 |     li {
 52 |       list-style-type: decimal-leading-zero;
 53 |       list-style-position: inside;
 54 |     }
 55 |   }
 56 |   ul {
 57 |     li {
 58 |       &:not(.task-list-item) {
 59 |         list-style-type: circle;
 60 |       }
 61 |       &.task-list-item {
 62 |         [type="checkbox"] {
 63 |           margin-right: 1em;
 64 |         }
 65 |       }
 66 |     }
 67 |   }
 68 |   pre {
 69 |     & > ul, & > ol {
 70 |       font-size: 1rem;
 71 |       li {
 72 |         line-height: 1.5em;
 73 |       }
 74 |     }
 75 |   }
 76 |   blockquote {
 77 |     position: relative;
 78 |     margin-bottom: 3rem;
 79 |     padding-bottom: 2rem;
 80 |     p {
 81 |       font-size: 1.33em;
 82 |     }
 83 |     &:before {
 84 |       content: '“';
 85 |       font-size: 4em;
 86 |       opacity: .5;
 87 |     }
 88 |     &:after {
 89 |       content: '';
 90 |       position: absolute;
 91 |       top: 100%; left: 0;
 92 |       height: 3px; width: 4em;
 93 |       background-color: rgba(_get($--colors, 'black'), 0.33);
 94 |     }
 95 |     p {
 96 |       margin-top: -1em;
 97 |     }
 98 |     @include media-breakpoint-up('md') {
 99 |       margin-left: -#{_get($--grid, 'margin')};
100 |       margin-right: -#{_get($--grid, 'margin')};
101 |     }
102 |   }
103 | }
104 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/markdown/_menu.scss:
--------------------------------------------------------------------------------
 1 | .markdown-menu {
 2 |   .markdown-menu-title {
 3 |     font-weight: 800;
 4 |     font-size: 1.1em;
 5 |     text-transform: capitalize;
 6 |     margin-bottom: .75em;
 7 |   }
 8 |   & > ul {
 9 |     a {
10 |       padding: .5em 0;
11 |       &[href] {
12 |         &:hover {
13 |           font-weight: 800;
14 |         }
15 |         &.active {
16 |           color: _get($--colors, 'blue');
17 |           font-weight: 800;
18 |         }
19 |       }
20 |       &:not([href]):focus {
21 |         outline: 0;
22 |       }
23 |     }
24 |     ul {
25 |       margin-left: 1em;
26 |     }
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/markdown/_prettyprint.scss:
--------------------------------------------------------------------------------
 1 | .prettyprint {
 2 | 
 3 |   @at-root pre#{&} {
 4 |     background: _get($--colors, 'gray');
 5 |     color: _get($--colors, 'white');
 6 |     margin: 0 0 2em 0;
 7 |     padding: 1em;
 8 | 
 9 |   }
10 | 
11 |   @at-root code#{&} {
12 |     background: _get($--colors, 'lt-gray');
13 |     color: inherit;
14 |     padding: .2em .5em;
15 | 
16 |     @at-root .prettyprint-gray #{&} {
17 |       background: _get($--colors, 'gray');
18 |     }
19 | 
20 |     @at-root .prettyprint-white #{&} {
21 |       background: _get($--colors, 'white');
22 |     }
23 |   }
24 | 
25 |   font-family: Menlo, Monaco, Consolas, monospace;
26 |   border: 0 !important;
27 |   border-radius: .25rem;
28 |   overflow-x: scroll;
29 | 
30 |   li {
31 |     padding-left: .5em;
32 |     padding-right: .5em;
33 |     line-height: 1.5em;
34 |     // &.L4, &.L9 {
35 |     //   list-style-type: none !important;
36 |     // }
37 |   }
38 | 
39 |   // Hide the text until it's prettyprinted
40 |   &:not(.prettyprinted) {
41 |     & > code {
42 |       visibility: hidden;
43 |     }
44 |   }
45 | }
46 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/navbar/_.scss:
--------------------------------------------------------------------------------
  1 | .navbar, .navbar > .container {
  2 |   display: flex;
  3 |   align-items: stretch;
  4 | }
  5 | 
  6 | .navbar {
  7 | 
  8 |   &:not(.unfixed) {
  9 |     position: fixed;
 10 |     z-index: 60;
 11 |     top: 0; left: 0; width: 100%;
 12 |   }
 13 | 
 14 |   background-color: _get($--navbar, 'background-color');
 15 |   color: _get($--navbar, 'color');
 16 | 
 17 |   @for $i from length(_get($--grid, 'breakpoints'))*-1 through -1 {
 18 |     $breakpoints: _keys(_get($--grid, 'breakpoints'));
 19 |     $breakpoint: nth($breakpoints, abs($i));
 20 |     @include media-breakpoint-down($breakpoint) {
 21 |       height: nth(_get($--navbar, 'height'), abs($i));
 22 |     }
 23 |   }
 24 | 
 25 |   & > .container {
 26 |     flex-grow: 1;
 27 |   }
 28 |   .navbar-content {
 29 |     display: flex;
 30 |     flex-grow: 1;
 31 |     & > * {
 32 |       display: flex;
 33 |       align-items: stretch;
 34 |     }
 35 |     .left, .right, .center {
 36 |       flex-grow: 1;
 37 |       & > * {
 38 |         display: inline-flex;
 39 |       }
 40 |       a {
 41 |         display: inline-flex;
 42 |         align-items: center;
 43 |         &.active {
 44 |           text-decoration: underline;
 45 |           @include set-font('header');
 46 |         }
 47 |       }
 48 |       ul li {
 49 |         display: inline-flex;
 50 |         align-items: stretch;
 51 |         a {
 52 |           @for $i from 1 through length(_get($--grid, 'breakpoints')) {
 53 |             $breakpoints: _keys(_get($--grid, 'breakpoints'));
 54 |             $breakpoint: nth($breakpoints, $i);
 55 |             @include media-breakpoint-down($breakpoint) {
 56 |               padding-left: nth(_get($--navbar, 'item-horiz-padding'), $i);
 57 |               padding-right: nth(_get($--navbar, 'item-horiz-padding'), $i);
 58 |             }
 59 |           }
 60 |         }
 61 |       }
 62 |     }
 63 |     .left {
 64 |       justify-content: flex-start;
 65 |       @include media-breakpoint-down('sm') {
 66 |         flex-basis: 100%;
 67 |         // justify-content: center;
 68 |       }
 69 |     }
 70 |     .center {
 71 |       justify-content: center;
 72 |     }
 73 |     .right {
 74 |       justify-content: flex-end;
 75 |     }
 76 |     // Custom components
 77 |     .unauthenticated {
 78 |       a {
 79 |         display: inline-flex;
 80 |         align-items: center;
 81 |         padding-left: .3em;
 82 |         padding-right: .3em;
 83 |       }
 84 |       & > span {
 85 |         align-self: center;
 86 |       }
 87 |     }
 88 |     .logo {
 89 |       @include media-breakpoint-down('sm') {
 90 |         flex-grow: 1;
 91 |       }
 92 |       img {
 93 |         transform: translateY(5%);
 94 |         max-height: 50%;
 95 |         @include media-breakpoint-down('lg') {
 96 |           max-height: 55%;
 97 |         }
 98 |         @include media-breakpoint-down('sm') {
 99 |           margin: auto;
100 |           max-height: 66%;
101 |         }
102 |       }
103 |     }
104 |     .burger {
105 |       font-size: 2rem;
106 |       padding: 0 _get($--grid, 'gutter');
107 |       &.left {
108 |         margin-left: -#{_get($--grid, 'margin')};
109 |         padding-left: _get($--grid, 'margin');
110 |       }
111 |       &:not(.left) {
112 |         margin-right: -#{_get($--grid, 'margin')};
113 |         padding-right: _get($--grid, 'margin');
114 |       }
115 |     }
116 |   }
117 | }
118 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/panels/_.scss:
--------------------------------------------------------------------------------
 1 | .panel {
 2 | 
 3 |   &.rounded {
 4 |     border-radius: _get($--panels, 'border-radius');
 5 |     overflow: hidden;
 6 |   }
 7 | 
 8 |   @for $i from 1 through length(_get($--grid, 'breakpoints')) {
 9 |     $breakpoints: _keys(_get($--grid, 'breakpoints'));
10 |     $breakpoint: nth($breakpoints, $i);
11 | 
12 |     &.padding-#{$breakpoint} {
13 |       $padding: nth(_get($--panels, 'padding'), $i);
14 |       $horiz-ratio: _get($--panels, 'padding-horiz-ratio');
15 |       padding: $padding #{$padding * $horiz-ratio};
16 |     }
17 | 
18 |     &.font-size-#{$breakpoint} {
19 |       font-size: nth(_get($--panels, 'font-size'), $i);
20 |     }
21 |   }
22 | 
23 | }
24 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/components/sections/_.scss:
--------------------------------------------------------------------------------
 1 | .section {
 2 |   @for $i from 1 through length(_get($--grid, 'breakpoints')) {
 3 |     $breakpoints: _keys(_get($--grid, 'breakpoints'));
 4 |     $breakpoint: nth($breakpoints, $i);
 5 |     $padding: nth(_get($--sections, 'padding'), $i);
 6 | 
 7 |     &.padding-#{$breakpoint}, &.padding-top-#{$breakpoint} {
 8 |       padding-top: $padding;
 9 | 
10 |       @include media-breakpoint-down('lg') {
11 |         padding-top: $padding * 0.8;
12 |       }
13 | 
14 |       @include media-breakpoint-down('md') {
15 |         padding-top: $padding * 0.6;
16 |       }
17 | 
18 |       @include media-breakpoint-down('sm') {
19 |         padding-top: $padding * 0.4;
20 |       }
21 | 
22 |       @include media-breakpoint-down('xs') {
23 |         padding-top: _get($--grid, 'gutter') * 2;
24 |       }
25 |     }
26 | 
27 |     &.padding-#{$breakpoint}, &.padding-bottom-#{$breakpoint} {
28 |       padding-bottom: $padding;
29 | 
30 |       @include media-breakpoint-down('lg') {
31 |         padding-bottom: $padding * 0.8;
32 |       }
33 | 
34 |       @include media-breakpoint-down('md') {
35 |         padding-bottom: $padding * 0.6;
36 |       }
37 | 
38 |       @include media-breakpoint-down('sm') {
39 |         padding-bottom: $padding * 0.4;
40 |       }
41 | 
42 |       @include media-breakpoint-down('xs') {
43 |         padding-bottom: _get($--grid, 'gutter') * 2;
44 |       }
45 |     }
46 | 
47 |     &.font-size-#{$breakpoint} {
48 |       $font-size: nth(_get($--sections, 'font-size'), $i);
49 |       font-size: $font-size;
50 |     }
51 |   }
52 | }
53 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/framework/_colors.scss:
--------------------------------------------------------------------------------
 1 | //----------------------------------------------------------------------
 2 | 
 3 | // Colors
 4 | //
 5 | 
 6 | @each $name, $hex in $--colors {
 7 |   // Give each color a unique color class
 8 |   .color-#{$name} { color: $hex !important; }
 9 |   // Give each color a unique bg class
10 |   .bg-#{$name} { background-color: $hex !important; }
11 |   // Give each color a unique bg hover class
12 |   .bg-hover-#{$name}:hover { background-color: $hex !important; }
13 |   // Give each color a unique color hover class
14 |   .color-hover-#{$name}:hover { color: $hex !important; }
15 | }
16 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/framework/_fonts.scss:
--------------------------------------------------------------------------------
 1 | //----------------------------------------------------------------------
 2 | 
 3 | // Fonts
 4 | //
 5 | 
 6 | // Give each font style a class
 7 | @each $name, $styles in $--font-styles {
 8 |   .font-#{$name} { @include set-font($name); }
 9 | }
10 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/framework/_grid.scss:
--------------------------------------------------------------------------------
  1 | //----------------------------------------------------------------------
  2 | 
  3 | // Grid
  4 | //
  5 | 
  6 | $grid-columns: _get($--grid, 'columns') !default;
  7 | $gutter-width: _get($--grid, 'gutter') !default;
  8 | $outer-margin: _get($--grid, 'margin') !default;
  9 | $breakpoints: _get($--grid, 'breakpoints') !default;
 10 | $flexboxgrid-max-width: _get($--grid, 'max-width') !default;
 11 | 
 12 | $gutter-compensation: $gutter-width * .5 * -1;
 13 | $half-gutter-width: $gutter-width * .5;
 14 | 
 15 | .flex {
 16 |   display: flex;
 17 | }
 18 | 
 19 | .inline-flex {
 20 |   display: inline-flex;
 21 | }
 22 | 
 23 | .wrapper {
 24 |   box-sizing: border-box;
 25 |   max-width: $flexboxgrid-max-width;
 26 |   margin: 0 auto;
 27 | }
 28 | 
 29 | .container, .container-fluid {
 30 |   margin-right: auto;
 31 |   margin-left: auto;
 32 |   padding-right: $outer-margin;
 33 |   padding-left: $outer-margin;
 34 | }
 35 | 
 36 | .row, .row-fluid {
 37 |   box-sizing: border-box;
 38 |   @include flexbox();
 39 |   @include flex(0, 1, auto);
 40 |   @include flex-direction(row);
 41 |   @include flex-wrap(wrap);
 42 | }
 43 | 
 44 | .row {
 45 |   margin-right: $gutter-compensation;
 46 |   margin-left: $gutter-compensation;
 47 | }
 48 | 
 49 | .row.reverse {
 50 |   @include flex-direction(row-reverse);
 51 | }
 52 | 
 53 | .col.reverse {
 54 |   @include flex-direction(column-reverse);
 55 | }
 56 | 
 57 | @mixin flexboxgrid-sass-col-common {
 58 |   box-sizing: border-box;
 59 | 
 60 |   // split @include flex(0, 0, auto) into individual props
 61 |   @include flex-grow(0);
 62 |   @include flex-shrink(0);
 63 | 
 64 |   // we leave @include flex-basis(auto) out of common because
 65 |   // in some spots we need it and some we dont
 66 |   // more why here: https://github.com/kristoferjoseph/flexboxgrid/issues/126
 67 | 
 68 |   padding-right: $half-gutter-width;
 69 |   padding-left: $half-gutter-width;
 70 | }
 71 | 
 72 | @each $value in $breakpoints {
 73 | 
 74 |   $name: nth($value, 1);
 75 |   $breakpoint: nth($value, 2);
 76 | 
 77 |   // If is smallest breakpoint
 78 |   @if index(map-keys($breakpoints), $name) == 1 {
 79 | 
 80 |     .col-#{$name} {
 81 |       @include flexboxgrid-sass-col-common;
 82 |       @include flex-basis(auto);
 83 |     }
 84 |     @for $i from 1 through $grid-columns {
 85 |       .col.#{$name}#{$i} {
 86 |         @include flexboxgrid-sass-col-common;
 87 |         @include flex-basis(100% / $grid-columns * $i);
 88 |         max-width: 100% / $grid-columns * $i;
 89 |       }
 90 |     }
 91 |     @for $i from 0 through $grid-columns {
 92 |       .col.offset-#{$name}#{$i} {
 93 |         @include flexboxgrid-sass-col-common;
 94 |         @if $i == 0 {
 95 |           margin-left: 0;
 96 |         } @else {
 97 |           margin-left: 100% / $grid-columns * $i;
 98 |         }
 99 |       }
100 |     }
101 |     .col.#{$name} {
102 |       @include flex-grow(1);
103 |       @include flex-basis(0);
104 |       max-width: 100%;
105 |       margin-left: _get($--grid, 'gutter') / 2;
106 |       margin-right: _get($--grid, 'gutter') / 2;
107 |     }
108 |     .start-#{$name} {
109 |       @include justify-content(flex-start);
110 |       text-align: start;
111 |     }
112 | 
113 |     .center-#{$name} {
114 |       @include justify-content(center);
115 |       text-align: center;
116 |     }
117 | 
118 |     .end-#{$name} {
119 |       @include justify-content(flex-end);
120 |       text-align: end;
121 |     }
122 | 
123 |     .top-#{$name} {
124 |       @include align-items(flex-start);
125 |     }
126 | 
127 |     .middle-#{$name} {
128 |       @include align-items(center);
129 |     }
130 | 
131 |     .bottom-#{$name} {
132 |       @include align-items(flex-end);
133 |     }
134 | 
135 |     .stretch-#{name} {
136 |       @include align-items(stretch);
137 |     }
138 | 
139 |     .around-#{$name} {
140 |       @include justify-content(space-around);
141 |     }
142 | 
143 |     .between-#{$name} {
144 |       @include justify-content(space-between);
145 |     }
146 | 
147 |     .first-#{$name} {
148 |       order: -1;
149 |     }
150 | 
151 |     .last-#{$name} {
152 |       order: 1;
153 |     }
154 | 
155 |   // Otherwise, let's use
156 | 
157 |   } @else {
158 | 
159 |     $size: nth($breakpoint, 1);
160 |     $container: nth($breakpoint, 2);
161 | 
162 |     @include media-breakpoint-up($name) {
163 |       .container {
164 |         max-width: $container;
165 |       }
166 | 
167 |       .col.#{$name} {
168 |         @include flexboxgrid-sass-col-common;
169 |         @include flex-basis(auto);
170 |       }
171 |       @for $i from 1 through $grid-columns {
172 |         .col.#{$name}#{$i} {
173 |           @include flexboxgrid-sass-col-common;
174 |           @include flex-basis(100% / $grid-columns * $i);
175 |           max-width: 100% / $grid-columns * $i;
176 |         }
177 |       }
178 |       @for $i from 0 through $grid-columns {
179 |         .col.offset-#{$name}#{$i} {
180 |           @include flexboxgrid-sass-col-common;
181 |           @if $i == 0 {
182 |             margin-left: 0;
183 |           } @else {
184 |             margin-left: 100% / $grid-columns * $i;
185 |           }
186 |         }
187 |       }
188 |       .col.#{$name} {
189 |         @include flex-grow(1);
190 |         @include flex-basis(0);
191 |         max-width: 100%;
192 |       }
193 |       .start-#{$name} {
194 |         @include justify-content(flex-start);
195 |         text-align: start;
196 |       }
197 | 
198 |       .center-#{$name} {
199 |         @include justify-content(center);
200 |         text-align: center;
201 |       }
202 | 
203 |       .end-#{$name} {
204 |         @include justify-content(flex-end);
205 |         text-align: end;
206 |       }
207 | 
208 |       .top-#{$name} {
209 |         @include align-items(flex-start);
210 |       }
211 | 
212 |       .middle-#{$name} {
213 |         @include align-items(center);
214 |       }
215 | 
216 |       .bottom-#{$name} {
217 |         @include align-items(flex-end);
218 |       }
219 | 
220 |       .around-#{$name} {
221 |         @include justify-content(space-around);
222 |       }
223 | 
224 |       .between-#{$name} {
225 |         @include justify-content(space-between);
226 |       }
227 | 
228 |       .first-#{$name} {
229 |         order: -1;
230 |       }
231 | 
232 |       .last-#{$name} {
233 |         order: 1;
234 |       }
235 |     }
236 |   }
237 | }
238 | 
239 | //----------------------------------------------------------------------
240 | 
241 | // Responsive classes
242 | //
243 | // Hide elements responsively using classes.
244 | 
245 | @each $name, $value in _get($--grid, 'breakpoints') {
246 | 
247 |   .hide-#{$name} {
248 |     @include media-breakpoint-only($name) {
249 |       display: none !important;
250 |     }
251 |   }
252 | 
253 |   .hide-#{$name}-up {
254 |     @include media-breakpoint-up($name) {
255 |       display: none !important;
256 |     }
257 |   }
258 |   .hide-#{$name}-down {
259 |     @include media-breakpoint-down($name) {
260 |       display: none !important;
261 |     }
262 |   }
263 | 
264 | }
265 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/framework/_mixins.scss:
--------------------------------------------------------------------------------
  1 | //----------------------------------------------------------------------
  2 | 
  3 | // Map Reverse
  4 | //
  5 | // Reverse the order of a sass map.
  6 | //
  7 | // values: Sass Map
  8 | 
  9 | @function _map-reverse($map) {
 10 |   $result: null;
 11 | 
 12 |   @if type-of($map) == "map" {
 13 |     $keys: map-keys($map);
 14 |     $map-reversed: ();
 15 | 
 16 |     @for $i from length($keys) through 1 {
 17 |       $map-reversed: map-merge(
 18 |           $map-reversed,
 19 |           (nth($keys, $i): _get($map, nth($keys, $i)))
 20 |       );
 21 |     }
 22 | 
 23 |     @if type-of($map-reversed) == "map" {
 24 |       $result: $map-reversed;
 25 |     } @else {
 26 |       @warn 'There was an error reversing the order of "#{$map}"';
 27 |     }
 28 |   } @else {
 29 |     @warn '"#{$map}" is not a valid map';
 30 |   }
 31 | 
 32 |   @return $result;
 33 | }
 34 | 
 35 | //----------------------------------------------------------------------
 36 | 
 37 | // Background
 38 | //
 39 | // Adds a background
 40 | //
 41 | // Values: file, width, height, position
 42 | // Default: row
 43 | //
 44 | // @include bg('image.jpg' 1440px 900px center);
 45 | 
 46 | @mixin bg($values) {
 47 |   $file: nth($values, 1);
 48 |   $width: nth($values, 2);
 49 |   $height: nth($values, 3);
 50 |   $position: nth($values, 4);
 51 | 
 52 |   background-image: url($file);
 53 |   background-repeat: no-repeat;
 54 |   background-position: $position;
 55 |   background-size: $width $height;
 56 | }
 57 | 
 58 | //----------------------------------------------------------------------
 59 | 
 60 | // Retina Background
 61 | //
 62 | // Adds a retina background
 63 | //
 64 | // Values: file, width, type height, position
 65 | // Default: row
 66 | //
 67 | // @include bg2x('image' 'jpg' 1440px 900px center);
 68 | 
 69 | @mixin bg2x($values) {
 70 |   $file: nth($values, 1);
 71 |   $extension: nth($values, 2);
 72 |   $width: nth($values, 3);
 73 |   $height: nth($values, 4);
 74 |   $position: nth($values, 5);
 75 | 
 76 |   background-image: url($file + '.' + $extension);
 77 |   background-repeat: no-repeat;
 78 |   background-position: $position;
 79 |   @media (min-resolution: 2dppx) {
 80 |     & {
 81 |       background-image: url($file + '@2x.' + $extension);
 82 |       background-size: $width $height;
 83 |     }
 84 |   }
 85 | }
 86 | 
 87 | //----------------------------------------------------------------------
 88 | 
 89 | // Flexbox Containers
 90 | //
 91 | // The 'flex' value causes an element to generate a block-level flex
 92 | // container box.
 93 | //
 94 | // The 'inline-flex' value causes an element to generate a inline-level
 95 | // flex container box.
 96 | //
 97 | // display: flex | inline-flex
 98 | //
 99 | // http://w3.org/tr/css3-flexbox/#flex-containers
100 | //
101 | // (Placeholder selectors for each type, for those who rather @extend)
102 | 
103 | @mixin flexbox {
104 | 	display: -webkit-box;
105 | 	display: -webkit-flex;
106 | 	display: -moz-flex;
107 | 	display: -ms-flexbox;
108 | 	display: flex;
109 | }
110 | 
111 | %flexbox { @include flexbox; }
112 | 
113 | //----------------------------------
114 | 
115 | @mixin inline-flex {
116 | 	display: -webkit-inline-box;
117 | 	display: -webkit-inline-flex;
118 | 	display: -moz-inline-flex;
119 | 	display: -ms-inline-flexbox;
120 | 	display: inline-flex;
121 | }
122 | 
123 | %inline-flex { @include inline-flex; }
124 | 
125 | //----------------------------------------------------------------------
126 | 
127 | // Flexbox Direction
128 | //
129 | // The 'flex-direction' property specifies how flex items are placed in
130 | // the flex container, by setting the direction of the flex container's
131 | // main axis. This determines the direction that flex items are laid out in.
132 | //
133 | // Values: row | row-reverse | column | column-reverse
134 | // Default: row
135 | //
136 | // http://w3.org/tr/css3-flexbox/#flex-direction-property
137 | 
138 | @mixin flex-direction($value: row) {
139 | 	@if $value == row-reverse {
140 | 		-webkit-box-direction: reverse;
141 | 		-webkit-box-orient: horizontal;
142 | 	} @else if $value == column {
143 | 		-webkit-box-direction: normal;
144 | 		-webkit-box-orient: vertical;
145 | 	} @else if $value == column-reverse {
146 | 		-webkit-box-direction: reverse;
147 | 		-webkit-box-orient: vertical;
148 | 	} @else {
149 | 		-webkit-box-direction: normal;
150 | 		-webkit-box-orient: horizontal;
151 | 	}
152 | 	-webkit-flex-direction: $value;
153 | 	-moz-flex-direction: $value;
154 | 	-ms-flex-direction: $value;
155 | 	flex-direction: $value;
156 | }
157 | 	// Shorter version:
158 | 	@mixin flex-dir($args...) { @include flex-direction($args...); }
159 | 
160 | //----------------------------------------------------------------------
161 | 
162 | // Flexbox Wrap
163 | //
164 | // The 'flex-wrap' property controls whether the flex container is single-line
165 | // or multi-line, and the direction of the cross-axis, which determines
166 | // the direction new lines are stacked in.
167 | //
168 | // Values: nowrap | wrap | wrap-reverse
169 | // Default: nowrap
170 | //
171 | // http://w3.org/tr/css3-flexbox/#flex-wrap-property
172 | 
173 | @mixin flex-wrap($value: nowrap) {
174 | 	// No Webkit Box fallback.
175 | 	-webkit-flex-wrap: $value;
176 | 	-moz-flex-wrap: $value;
177 | 	@if $value == nowrap {
178 | 		-ms-flex-wrap: none;
179 | 	} @else {
180 | 		-ms-flex-wrap: $value;
181 | 	}
182 | 	flex-wrap: $value;
183 | }
184 | 
185 | //----------------------------------------------------------------------
186 | 
187 | // Flexbox Flow (shorthand)
188 | //
189 | // The 'flex-flow' property is a shorthand for setting the 'flex-direction'
190 | // and 'flex-wrap' properties, which together define the flex container's
191 | // main and cross axes.
192 | //
193 | // Values:  | 
194 | // Default: row nowrap
195 | //
196 | // http://w3.org/tr/css3-flexbox/#flex-flow-property
197 | 
198 | @mixin flex-flow($values: (row nowrap)) {
199 | 	// No Webkit Box fallback.
200 | 	-webkit-flex-flow: $values;
201 | 	-moz-flex-flow: $values;
202 | 	-ms-flex-flow: $values;
203 | 	flex-flow: $values;
204 | }
205 | 
206 | //----------------------------------------------------------------------
207 | 
208 | // Flexbox Order
209 | //
210 | // The 'order' property controls the order in which flex items appear within
211 | // their flex container, by assigning them to ordinal groups.
212 | //
213 | // Default: 0
214 | //
215 | // http://w3.org/tr/css3-flexbox/#order-property
216 | 
217 | @mixin order($int: 0) {
218 | 	-webkit-box-ordinal-group: $int + 1;
219 | 	-webkit-order: $int;
220 | 	-moz-order: $int;
221 | 	-ms-flex-order: $int;
222 | 	order: $int;
223 | }
224 | 
225 | //----------------------------------------------------------------------
226 | 
227 | // Flexbox Grow
228 | //
229 | // The 'flex-grow' property sets the flex grow factor. Negative numbers
230 | // are invalid.
231 | //
232 | // Default: 0
233 | //
234 | // http://w3.org/tr/css3-flexbox/#flex-grow-property
235 | 
236 | @mixin flex-grow($int: 0) {
237 | 	-webkit-box-flex: $int;
238 | 	-webkit-flex-grow: $int;
239 | 	-moz-flex-grow: $int;
240 | 	-ms-flex-positive: $int;
241 | 	flex-grow: $int;
242 | }
243 | 
244 | //----------------------------------------------------------------------
245 | 
246 | // Flexbox Shrink
247 | //
248 | // The 'flex-shrink' property sets the flex shrink factor. Negative numbers
249 | // are invalid.
250 | //
251 | // Default: 1
252 | //
253 | // http://w3.org/tr/css3-flexbox/#flex-shrink-property
254 | 
255 | @mixin flex-shrink($int: 1) {
256 | 	-webkit-flex-shrink: $int;
257 | 	-moz-flex-shrink: $int;
258 | 	-ms-flex-negative: $int;
259 | 	flex-shrink: $int;
260 | }
261 | 
262 | //----------------------------------------------------------------------
263 | 
264 | // Flexbox Basis
265 | //
266 | // The 'flex-basis' property sets the flex basis. Negative lengths are invalid.
267 | //
268 | // Values: Like "width"
269 | // Default: auto
270 | //
271 | // http://www.w3.org/TR/css3-flexbox/#flex-basis-property
272 | 
273 | @mixin flex-basis($value: auto) {
274 | 	-webkit-flex-basis: $value;
275 | 	-moz-flex-basis: $value;
276 | 	-ms-flex-preferred-size: $value;
277 | 	flex-basis: $value;
278 | }
279 | 
280 | //----------------------------------------------------------------------
281 | 
282 | // Flexbox "Flex" (shorthand)
283 | //
284 | // The 'flex' property specifies the components of a flexible length: the
285 | // flex grow factor and flex shrink factor, and the flex basis. When an
286 | // element is a flex item, 'flex' is consulted instead of the main size
287 | // property to determine the main size of the element. If an element is
288 | // not a flex item, 'flex' has no effect.
289 | //
290 | // Values: none |   || 
291 | // Default: See individual properties (1 1 0).
292 | //
293 | // http://w3.org/tr/css3-flexbox/#flex-property
294 | 
295 | @mixin flex($fg: 1, $fs: null, $fb: null) {
296 | 
297 | 	// Set a variable to be used by box-flex properties
298 | 	$fg-boxflex: $fg;
299 | 
300 | 	// Box-Flex only supports a flex-grow value so let's grab the
301 | 	// first item in the list and just return that.
302 | 	@if type-of($fg) == 'list' {
303 | 		$fg-boxflex: nth($fg, 1);
304 | 	}
305 | 
306 | 	-webkit-box-flex: $fg-boxflex;
307 | 	-webkit-flex: $fg $fs $fb;
308 | 	-moz-box-flex: $fg-boxflex;
309 | 	-moz-flex: $fg $fs $fb;
310 | 	-ms-flex: $fg $fs $fb;
311 | 	flex: $fg $fs $fb;
312 | }
313 | 
314 | //----------------------------------------------------------------------
315 | 
316 | // Flexbox Justify Content
317 | //
318 | // The 'justify-content' property aligns flex items along the main axis
319 | // of the current line of the flex container. This is done after any flexible
320 | // lengths and any auto margins have been resolved. Typically it helps distribute
321 | // extra free space leftover when either all the flex items on a line are
322 | // inflexible, or are flexible but have reached their maximum size. It also
323 | // exerts some control over the alignment of items when they overflow the line.
324 | //
325 | // Note: 'space-*' values not supported in older syntaxes.
326 | //
327 | // Values: flex-start | flex-end | center | space-between | space-around
328 | // Default: flex-start
329 | //
330 | // http://w3.org/tr/css3-flexbox/#justify-content-property
331 | 
332 | @mixin justify-content($value: flex-start) {
333 | 	@if $value == flex-start {
334 | 		-webkit-box-pack: start;
335 | 		-ms-flex-pack: start;
336 | 	} @else if $value == flex-end {
337 | 		-webkit-box-pack: end;
338 | 		-ms-flex-pack: end;
339 | 	} @else if $value == space-between {
340 | 		-webkit-box-pack: justify;
341 | 		-ms-flex-pack: justify;
342 | 	} @else if $value == space-around {
343 | 		-ms-flex-pack: distribute;
344 | 	} @else {
345 | 		-webkit-box-pack: $value;
346 | 		-ms-flex-pack: $value;
347 | 	}
348 | 	-webkit-justify-content: $value;
349 | 	-moz-justify-content: $value;
350 | 	justify-content: $value;
351 | }
352 | 	// Shorter version:
353 | 	@mixin flex-just($args...) { @include justify-content($args...); }
354 | 
355 | //----------------------------------------------------------------------
356 | 
357 | // Flexbox Align Items
358 | //
359 | // Flex items can be aligned in the cross axis of the current line of the
360 | // flex container, similar to 'justify-content' but in the perpendicular
361 | // direction. 'align-items' sets the default alignment for all of the flex
362 | // container's items, including anonymous flex items. 'align-self' allows
363 | // this default alignment to be overridden for individual flex items. (For
364 | // anonymous flex items, 'align-self' always matches the value of 'align-items'
365 | // on their associated flex container.)
366 | //
367 | // Values: flex-start | flex-end | center | baseline | stretch
368 | // Default: stretch
369 | //
370 | // http://w3.org/tr/css3-flexbox/#align-items-property
371 | 
372 | @mixin align-items($value: stretch) {
373 | 	@if $value == flex-start {
374 | 		-webkit-box-align: start;
375 | 		-ms-flex-align: start;
376 | 	} @else if $value == flex-end {
377 | 		-webkit-box-align: end;
378 | 		-ms-flex-align: end;
379 | 	} @else {
380 | 		-webkit-box-align: $value;
381 | 		-ms-flex-align: $value;
382 | 	}
383 | 	-webkit-align-items: $value;
384 | 	-moz-align-items: $value;
385 | 	align-items: $value;
386 | }
387 | 
388 | //----------------------------------
389 | 
390 | // Flexbox Align Self
391 | //
392 | // Values: auto | flex-start | flex-end | center | baseline | stretch
393 | // Default: auto
394 | 
395 | @mixin align-self($value: auto) {
396 | 	// No Webkit Box Fallback.
397 | 	-webkit-align-self: $value;
398 | 	-moz-align-self: $value;
399 | 	@if $value == flex-start {
400 | 		-ms-flex-item-align: start;
401 | 	} @else if $value == flex-end {
402 | 		-ms-flex-item-align: end;
403 | 	} @else {
404 | 		-ms-flex-item-align: $value;
405 | 	}
406 | 	align-self: $value;
407 | }
408 | 
409 | //----------------------------------------------------------------------
410 | 
411 | // Flexbox Align Content
412 | //
413 | // The 'align-content' property aligns a flex container's lines within the
414 | // flex container when there is extra space in the cross-axis, similar to
415 | // how 'justify-content' aligns individual items within the main-axis. Note,
416 | // this property has no effect when the flexbox has only a single line.
417 | //
418 | // Values: flex-start | flex-end | center | space-between | space-around | stretch
419 | // Default: stretch
420 | //
421 | // http://w3.org/tr/css3-flexbox/#align-content-property
422 | 
423 | @mixin align-content($value: stretch) {
424 | 	// No Webkit Box Fallback.
425 | 	-webkit-align-content: $value;
426 | 	-moz-align-content: $value;
427 | 	@if $value == flex-start {
428 | 		-ms-flex-line-pack: start;
429 | 	} @else if $value == flex-end {
430 | 		-ms-flex-line-pack: end;
431 | 	} @else {
432 | 		-ms-flex-line-pack: $value;
433 | 	}
434 | 	align-content: $value;
435 | }
436 | 
437 | //----------------------------------------------------------------------
438 | 
439 | // Breakpoint Mixins
440 | 
441 | @function breakpoint-next($name, $breakpoints: _get($--grid, 'breakpoints'), $breakpoint-names: map-keys($breakpoints)) {
442 |   $n: index($breakpoint-names, $name);
443 |   @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
444 | }
445 | 
446 | // Minimum breakpoint width. Null for the smallest (first) breakpoint.
447 | //
448 | //    >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px))
449 | //    576px
450 | @function breakpoint-min($name, $breakpoints: _get($--grid, 'breakpoints')) {
451 |   $breakpoint: _get($breakpoints, $name);
452 |   $min: nth($breakpoint, 1);
453 |   @return if($min != 0, $min, null);
454 | }
455 | 
456 | // Maximum breakpoint width. Null for the largest (last) breakpoint.
457 | // The maximum value is calculated as the minimum of the next one less 0.1.
458 | //
459 | //    >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px))
460 | //    767px
461 | @function breakpoint-max($name, $breakpoints: _get($--grid, 'breakpoints')) {
462 |   $next: breakpoint-next($name, $breakpoints);
463 |   @return if($next, breakpoint-min($next, $breakpoints) - 1px, null);
464 | }
465 | 
466 | // Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
467 | // Makes the @content apply to the given breakpoint and wider.
468 | @mixin media-breakpoint-up($name, $breakpoints: _get($--grid, 'breakpoints')) {
469 |   $min: breakpoint-min($name, $breakpoints);
470 |   @if $min {
471 |     @media (min-width: $min) {
472 |       @content;
473 |     }
474 |   } @else {
475 |     @content;
476 |   }
477 | }
478 | 
479 | // Media of at most the maximum breakpoint width. No query for the largest breakpoint.
480 | // Makes the @content apply to the given breakpoint and narrower.
481 | @mixin media-breakpoint-down($name, $breakpoints: _get($--grid, 'breakpoints')) {
482 |   $max: breakpoint-max($name, $breakpoints);
483 |   @if $max {
484 |     @media (max-width: $max) {
485 |       @content;
486 |     }
487 |   } @else {
488 |     @content;
489 |   }
490 | }
491 | 
492 | // Media that spans multiple breakpoint widths.
493 | // Makes the @content apply between the min and max breakpoints
494 | @mixin media-breakpoint-between($lower, $upper, $breakpoints: _get($--grid, 'breakpoints')) {
495 |   @include media-breakpoint-up($lower, $breakpoints) {
496 |     @include media-breakpoint-down($upper, $breakpoints) {
497 |       @content;
498 |     }
499 |   }
500 | }
501 | 
502 | // Media between the breakpoint's minimum and maximum widths.
503 | // No minimum for the smallest breakpoint, and no maximum for the largest one.
504 | // Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
505 | @mixin media-breakpoint-only($name, $breakpoints: _get($--grid, 'breakpoints')) {
506 |   @include media-breakpoint-between($name, $name, $breakpoints) {
507 |     @content;
508 |   }
509 | }
510 | 
511 | //----------------------------------------------------------------------
512 | 
513 | // Button style mixin
514 | // Generate coloured buttons with modular hover color states.
515 | 
516 | @mixin btn-style($name, $normal, $hover) {
517 |   .btn, .btn-round {
518 |     &.btn--#{$name} {
519 |       color: nth($normal, 1) !important;
520 |       background-color: nth($normal, 2);
521 |       &:hover {
522 |         color: nth($hover, 1) !important;
523 |         background-color: nth($hover, 2);
524 |       }
525 |     }
526 | 
527 |     &.btn--hover-#{$name}:hover {
528 |       color: nth($normal, 1) !important;
529 |       background-color: nth($normal, 2) !important;
530 |     }
531 |   }
532 | 
533 | }
534 | 
535 | //----------------------------------------------------------------------
536 | 
537 | // Responsive Font Scale
538 | // Set a responsive font scale which weights down across breakpoints.
539 | 
540 | @mixin responsive-font-scale($fontsize: 1rem, $ratio: 1, $breakpoints: _get($--grid, 'breakpoints')) {
541 | 
542 |   $breakpoints: _map-reverse($breakpoints);
543 | 
544 |   @each $breakpoint in $breakpoints {
545 |     $name: nth($breakpoint, 1);
546 |     $i: index(map-keys($breakpoints), $name);
547 | 
548 |     // Ensure we're not setting a responsive scale on the largest breakpoint
549 |     @if $i != 1 {
550 | 
551 |       // Get the total number of breakpoints
552 |       $n: length($breakpoints);
553 | 
554 |       // Get decimal representation of breakpoint increment
555 |       $b: $i / $n;
556 | 
557 |       // Get full intended decrement across all breakpoints
558 |       $d: 1 - $ratio;
559 | 
560 |       // Get decrement for just this breakpoint
561 |       $bd: $d * $b;
562 | 
563 |       // Represent the proper value
564 |       $br: 1 - $bd;
565 | 
566 |       // Get the responsive fontsize
567 |       $rf: $fontsize * $br;
568 | 
569 |       @include media-breakpoint-down($name) {
570 |         font-size: $rf;
571 |       }
572 |     }
573 |   }
574 | 
575 | }
576 | 
577 | //----------------------------------------------------------------------
578 | 
579 | // Font mixins
580 | // Get and set fonts using the
581 | 
582 | @function font($name, $fonts: $--font-faces) {
583 |   $font: _get($fonts, $name);
584 |   @if $font == null {
585 |     @error "Font isn't defined.";
586 |   } @else {
587 |     $family: _get($font, 'family');
588 |     $type: _get($font, 'type');
589 |     @return '#{$family}', #{$type};
590 |   }
591 | }
592 | 
593 | // Set Font
594 | @mixin set-font($font, $font-styles: $--font-styles) {
595 | 
596 |   $setup: _get($font-styles, $font);
597 | 
598 |   $family: _get($setup, 'family');
599 |   @if $family != null { font-family: $family; }
600 | 
601 |   $style: _get($setup, 'style');
602 |   @if $style != null { font-style: $style; }
603 | 
604 |   $weight: _get($setup, 'weight');
605 |   @if $weight != null { font-weight: $weight; }
606 | 
607 |   $spacing: _get($setup, 'letter-spacing');
608 |   @if $spacing != null { letter-spacing: $spacing; }
609 | 
610 |   $text-transform: _get($setup, 'text-transform');
611 |   @if $text-transform != null { text-transform: $text-transform; }
612 | 
613 | }
614 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/framework/_reset.scss:
--------------------------------------------------------------------------------
 1 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
 2 |     margin: 0;
 3 |     padding: 0;
 4 |     border: 0;
 5 |     font: inherit;
 6 |     vertical-align: baseline;
 7 |   }
 8 | 
 9 |   // HTML5 display-role reset for older browsers
10 |   article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
11 |     display: block;
12 |   }
13 |   body {
14 |     line-height: 1;
15 |   }
16 |   ol, ul {
17 |     list-style: none;
18 |   }
19 |   blockquote, q {
20 |     quotes: none;
21 |   }
22 |   blockquote {
23 |     &:before, &:after {
24 |       content: "";
25 |       content: none;
26 |     }
27 |   }
28 |   q {
29 |     &:before, &:after {
30 |       content: "";
31 |       content: none;
32 |     }
33 |   }
34 |   table {
35 |     border-collapse: collapse;
36 |     border-spacing: 0;
37 |   }
38 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/framework/_type.scss:
--------------------------------------------------------------------------------
 1 | //----------------------------------------------------------------------
 2 | 
 3 | // Type
 4 | //
 5 | 
 6 | $html: _get($--type, 'html');
 7 | $headers: _get($--type, 'headers');
 8 | $breakpoints: map-reverse(_get($--grid, 'breakpoints'));
 9 | $paragraph: _get($--type, 'p');
10 | $small: _get($--type, 'small');
11 | 
12 | 
13 | html{
14 |   font-size: nth($html, 1);
15 |   line-height: nth($html, 2);
16 | 
17 |   @include responsive-font-scale(nth($html, 1), nth($html, 3));
18 | }
19 | 
20 | @each $size, $value in $headers {
21 | 
22 |   $fontsize: nth($value, 1);
23 |   $ratio: nth($value, 3);
24 | 
25 |   #{$size} {
26 |     font-size: $fontsize;
27 |     line-height: nth($value, 2);
28 |     margin: $fontsize;
29 | 
30 |     @include responsive-font-scale($fontsize, $ratio);
31 | 
32 |   }
33 | 
34 | }
35 | 
36 | small { font-size: $small; }
37 | 
38 | p {
39 |   font-size: nth($paragraph, 1);
40 |   line-height: nth($paragraph, 2);
41 |   padding-bottom: nth($paragraph, 3);
42 | }
43 | 
44 | article {
45 |   // padding: 0 _get($--grid, 'margin') _get($--grid, 'margin') _get($--grid, 'margin');
46 |   p {
47 |     font-size: 1.1em;
48 |   }
49 | }
50 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/framework/_utility.scss:
--------------------------------------------------------------------------------
  1 | //----------------------------------------------------------------------
  2 | 
  3 | // Alignment classes
  4 | //
  5 | // Align element content using classes.
  6 | 
  7 | .align-left { text-align: left; }
  8 | .align-right { text-align: right; }
  9 | .align-center { text-align: center; }
 10 | .float-left { float: left !important; }
 11 | .float-right { float: right !important; }
 12 | 
 13 | //----------------------------------------------------------------------
 14 | 
 15 | // Depth classes
 16 | //
 17 | // Add depth to elements using classes.
 18 | 
 19 | $depth-color: _get($--colors, 'gray');
 20 | 
 21 | $--depths: (
 22 |   xs: #{0 1px 2px 0 rgba($depth-color, 0.1),
 23 |         0 2px 6px 0 rgba($depth-color, 0.1)},
 24 |   sm: #{0 1px 3px 0 rgba($depth-color, 0.2),
 25 |         0 2px 8px 0 rgba($depth-color, 0.1)},
 26 |   md: #{0 1px 4px 0 rgba($depth-color, 0.3),
 27 |         0 3px 12px 0 rgba($depth-color, 0.1)},
 28 |   lg: #{0 8px 17px 0 rgba($depth-color, 0.2),
 29 |         0 6px 20px 0 rgba($depth-color, 0.19)},
 30 |   xl: #{0 12px 15px 0 rgba($depth-color, 0.24),
 31 |         0 17px 50px 0 rgba($depth-color, 0.19)}
 32 | );
 33 | 
 34 | @each $name, $depth in $--depths {
 35 |   &.depth-#{$name} {
 36 |     box-shadow: $depth;
 37 |   }
 38 |   &.depth-hover-#{$name}:hover {
 39 |     box-shadow: $depth;
 40 |   }
 41 | }
 42 | 
 43 | // .depth-none {
 44 | //   box-shadow: none !important;
 45 | // }
 46 | //
 47 | // .depth-xs {
 48 | //   box-shadow: 0 1px 2px 0 rgba($depth-color, 0.1), 0 2px 6px 0 rgba($depth-color, 0.1);
 49 | // }
 50 | //
 51 | // .depth-sm {
 52 | //   box-shadow: 0 1px 3px 0 rgba($depth-color, 0.2), 0 2px 8px 0 rgba($depth-color, 0.1);
 53 | // }
 54 | //
 55 | // .depth-md {
 56 | //   box-shadow: 0 1px 4px 0 rgba($depth-color, 0.3), 0 3px 12px 0 rgba($depth-color, 0.1);
 57 | // }
 58 | //
 59 | // .depth-lg {
 60 | //   box-shadow: 0 8px 17px 0 rgba($depth-color, 0.2), 0 6px 20px 0 rgba($depth-color, 0.19);
 61 | // }
 62 | //
 63 | // .depth-xl {
 64 | //   box-shadow: 0 12px 15px 0 rgba($depth-color, 0.24), 0 17px 50px 0 rgba($depth-color, 0.19);
 65 | // }
 66 | 
 67 | //----------------------------------------------------------------------
 68 | 
 69 | // Responsive media
 70 | //
 71 | // Responsive images and embedded video
 72 | 
 73 | img.responsive-img,
 74 | video.responsive-video {
 75 |   max-width: 100%;
 76 |   height: auto;
 77 |   &.fullwidth {
 78 |     min-width: 100%;
 79 |   }
 80 | }
 81 | 
 82 | .container-video {
 83 |   position: relative;
 84 |   padding-bottom: 56.25%;
 85 |   height: 0;
 86 |   overflow: hidden;
 87 | 
 88 |   iframe, object, embed {
 89 |     position: absolute;
 90 |     top: 0;
 91 |     left: 0;
 92 |     width: 100%;
 93 |     height: 100%;
 94 |   }
 95 | }
 96 | 
 97 | 
 98 | //----------------------------------------------------------------------
 99 | 
100 | // Truncate
101 | //
102 | // Truncate element text in the UI.
103 | 
104 | .truncate {
105 |   display: block;
106 |   white-space: nowrap;
107 |   overflow: hidden;
108 |   text-overflow: ellipsis;
109 | }
110 | 
111 | //----------------------------------------------------------------------
112 | 
113 | // Clearfix
114 | //
115 | // Using flexbox should remove the need for clearfix, but you can use it to ensure elements float correctly.
116 | 
117 | .clearfix {
118 |   clear: both;
119 |   &:before, &:after {
120 |     flex-basis: 0;
121 |     order: 1;
122 |   }
123 | }
124 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/main/_.scss:
--------------------------------------------------------------------------------
 1 | //----------------------------------------------------------------------
 2 | 
 3 | // Main
 4 | //
 5 | 
 6 | * {
 7 |   &::selection {
 8 |     color: _get($--main, 'selection-color');
 9 |     background-color: _get($--main, 'selection-background-color');
10 |   }
11 | }
12 | 
13 | html {
14 |   @include set-font('content');
15 | }
16 | 
17 | body {
18 |   overflow-x: hidden;
19 |   overflow-y: auto;
20 |   -webkit-font-smoothing: antialiased;
21 | 
22 |   color: _get($--main, 'body-color');
23 |   background-color: _get($--main, 'body-background-color');
24 | 
25 |   &.no-scroll { overflow: hidden; }
26 | 
27 | }
28 | 
29 | //----------------------------------------------------------------------
30 | 
31 | // Headers
32 | // Add header styles.
33 | 
34 | h1, h2, h3, h4, h5, h6 {
35 |   @include set-font('display');
36 | 
37 |   // Ensure there's a margin on each header
38 |   margin: .5em 0;
39 | 
40 |   // Other styles to attach to all headers
41 |   a { font-weight: inherit; }
42 | }
43 | 
44 | //----------------------------------------------------------------------
45 | 
46 | // Links
47 | // Add link styles.
48 | 
49 | a {
50 |   text-decoration: none;
51 |   &, &:visited, &:active { display: inline-block; color: inherit; }
52 | }
53 | 
54 | //----------------------------------------------------------------------
55 | 
56 | // Type
57 | // Defaults for type styles
58 | 
59 | i { font-style: italic; }
60 | b { font-weight: 700; }
61 | em { font-style: italic; }
62 | strong { font-weight: 500; }
63 | .uppercase { text-transform: uppercase !important; }
64 | 
65 | hr {
66 |   border: none; height: 1px; background-color: darken(_get($--colors, 'lt-gray'), 5%);
67 | }
68 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/main/_config.scss:
--------------------------------------------------------------------------------
  1 | // Main config
  2 | 
  3 | $--grid: (
  4 |   // Set the number of columns you want to use on your layout.
  5 |   columns: 12,
  6 |   // Set the gutter between columns.
  7 |   gutter: 1rem,
  8 |   // Set a margin for the container sides.
  9 |   margin: 2rem,
 10 |   // Define breakpoints.
 11 |   breakpoints: (
 12 |     xs: default, // Less than 576px wide - Portrait phones
 13 |     sm: 576px 540px, // Between 576 and 767 - Landscape Phones
 14 |     md: 768px 720px, // Between 768 and 991 - Tablets
 15 |     lg: 992px 960px, // Between 992 and 1199 - Desktops
 16 |     xl: 1280px 1024px // 1200 upwards - Extra large devices
 17 |   ),
 18 |   // Max width of container
 19 |   max-width: 1024px
 20 | );
 21 | 
 22 | $--font-faces: (
 23 |   'overpass': (
 24 |     family: 'Overpass',
 25 |     type: sans-serif
 26 |   )
 27 | );
 28 | 
 29 | $--font-styles: (
 30 |   'display': (
 31 |     family: font('overpass'),
 32 |     style: normal,
 33 |     weight: 300,
 34 |     letter-spacing: -.02em
 35 |   ),
 36 |   'header': (
 37 |     family: font('overpass'),
 38 |     style: normal,
 39 |     weight: 800,
 40 |     letter-spacing: -0.01em
 41 |   ),
 42 |   'content': (
 43 |     family: font('overpass'),
 44 |     transform: inherit,
 45 |     weight: 400,
 46 |     letter-spacing: 0em
 47 |   )
 48 | );
 49 | 
 50 | $--type: (
 51 |   // HTML Base Font
 52 |   // @params font-size, line-height, responsive-ratio
 53 |   html: (15px, 150%, 1.1),
 54 | 
 55 |   // Headers
 56 |   // @params font-size, line-height, responsive-ratio
 57 |   headers: (
 58 |     h1: (3.33rem, 110%, 0.6),
 59 |     h2: (2rem, 120%, 0.8),
 60 |     h3: (1.66rem, 130%, 0.85),
 61 |     h4: (1.33rem, 140%, 0.9),
 62 |     h5: (1.2rem, 160%, 0.95),
 63 |     h6: (1rem, 180%, 1)
 64 |   ),
 65 | 
 66 |   // Paragraph
 67 |   // @params font-size, line-height, padding-bottom
 68 |   p: (1rem, 200%, 1em),
 69 | 
 70 |   // Small
 71 |   // @params font-size
 72 |   small: 0.9em
 73 | );
 74 | 
 75 | $--colors: (
 76 |   'blue': #1682fc,
 77 |   'blue-dk': darken(#1682fc, 10%),
 78 | 
 79 |   // Monochrome
 80 |   'white': white,
 81 |   'black': black,
 82 | 
 83 |   // Mid tones
 84 |   'gray': #262f3a,
 85 |   'lt-gray': darken(white, 5%),
 86 |   'mid-gray': darken(white, 33%),
 87 |   'dk-gray': #1b2026,
 88 | 
 89 |   // Success, Error & Warning
 90 |   'green': #2ecc71,
 91 |   'red': #EF2038,
 92 |   'yellow': #FFDF2E
 93 | );
 94 | 
 95 | $--main: (
 96 |   body-color: _get($--colors, 'gray'),
 97 |   body-background-color: _get($--colors, 'white'),
 98 |   selection-background-color: _get($--colors, 'blue'),
 99 |   selection-color: _get($--colors, 'white')
100 | );
101 | 
102 | $--easing: (
103 |   'cubic': (
104 |     in: cubic-bezier(0.550, 0.055, 0.675, 0.190),
105 |     out: cubic-bezier(0.215, 0.610, 0.355, 1.000),
106 |     in-out: cubic-bezier(0.645, 0.045, 0.355, 1.000)
107 |   ),
108 |   'expo': (
109 |     in: cubic-bezier(0.950, 0.050, 0.795, 0.035),
110 |     out: cubic-bezier(0.190, 1.000, 0.220, 1.000),
111 |     in-out: cubic-bezier(1.000, 0.000, 0.000, 1.000)
112 |   ),
113 |   'back': (
114 |     in: cubic-bezier(0.600, -0.280, 0.735, 0.045),
115 |     out: cubic-bezier(0.175, 0.885, 0.320, 1.275),
116 |     in-out: cubic-bezier(0.680, -0.550, 0.265, 1.550)
117 |   ),
118 |   'jump': (
119 |     out: cubic-bezier(.25,1.4,.55,.99),
120 |     in-out: cubic-bezier(.87,-.41,.19,1.44),
121 |   ),
122 |   'leap': (
123 |     out: cubic-bezier(.25,1.9,.55,.99),
124 |     in-out: cubic-bezier(.78,-0.81,.27,1.7)
125 |   )
126 | 
127 | );
128 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/routes/_.scss:
--------------------------------------------------------------------------------
 1 | @import 'index';
 2 | @import 'documentation/examples/index';
 3 | @import 'documentation/examples/example';
 4 | 
 5 | .toggle-in-view {
 6 |   font-weight: bold;
 7 |   color: green;
 8 |   transition: color 1s linear;
 9 | }
10 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/routes/_index.scss:
--------------------------------------------------------------------------------
 1 | [data-route="index"] {
 2 |   [data-section="header"] {
 3 |     display: flex;
 4 |     align-items: center;
 5 |     height: 100vh;
 6 | 
 7 |     .lead-image {
 8 |       max-width: 400px;
 9 |     }
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/routes/documentation/examples/_example.scss:
--------------------------------------------------------------------------------
 1 | [data-route="documentation.examples.example"] {
 2 | 
 3 |   // pins
 4 | 
 5 |   [data-panel="pin-pushfollowers"] {
 6 |     display: flex;
 7 |     height: 100vh;
 8 |     align-items: center;
 9 |     justify-content: center;
10 |   }
11 | 
12 |   .pinned-nav {
13 |     background-color: white;
14 |     ul {
15 |       li {
16 |         padding: 2rem;
17 |       }
18 |     }
19 |     border-bottom: 1px solid _get($--colors, 'blue');
20 |   }
21 | 
22 |   .scroll-top-pin-spacer {
23 |     z-index: 1000;
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/tests/dummy/app/styles/routes/documentation/examples/_index.scss:
--------------------------------------------------------------------------------
 1 | [data-route="documentation.examples.index"] {
 2 |   [data-section="examples-list"] {
 3 |     ul {
 4 |       display: flex;
 5 |       align-items: stretch;
 6 |       li {
 7 |         display: flex;
 8 |         & > .panel {
 9 |           display: flex;
10 |           flex-grow: 1;
11 |           flex-direction: column;
12 |           margin: 1.5rem 0;
13 |           .header-container {
14 |             padding: 2rem 0 1rem 0;
15 |           }
16 |           .description-container {
17 |             flex-grow: 1;
18 |             p {
19 |               margin: 0 2rem 1rem 2rem;
20 |             }
21 |           }
22 |         }
23 |       }
24 |     }
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 | 
2 | {{outlet}} 3 |
4 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/app/templates/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/ui-button.hbs: -------------------------------------------------------------------------------- 1 | {{#if linkTitle}}{{linkTitle}}{{else}}{{yield}}{{/if}} 2 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/ui-footer.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section tagName="footer" padding=(hash top="xs" bottom="sm") bg="lt-gray"}} 2 |
3 |
4 | 5 |
6 |
    7 |
  • 8 | {{link-to 'Guides' 'documentation.guides'}} 9 |
  • 10 |
  • 11 | {{link-to 'Examples' 'documentation.examples'}} 12 |
  • 13 |
  • 14 | 15 | GitHub 16 | 17 |
  • 18 |
19 |
20 | 21 |
22 |

23 | 24 | 2017 - Ember ScrollMagic.
25 | Made for the awesome Ember.js community by Will Viles.
26 | Guides made using Ember CLI Markdown Resolver. 27 |
28 |

29 |
30 | 31 |
32 |
33 | {{/ui-section}} 34 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/ui-navbar.hbs: -------------------------------------------------------------------------------- 1 |
2 | 32 |
33 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/ui-panel.hbs: -------------------------------------------------------------------------------- 1 | {{yield this}} 2 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/ui-section.hbs: -------------------------------------------------------------------------------- 1 | {{yield this}} 2 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation.hbs: -------------------------------------------------------------------------------- 1 | {{ui-navbar fixed=false}} 2 | 3 | {{outlet}} 4 | 5 | {{partial 'components/ui-footer'}} 6 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples.hbs: -------------------------------------------------------------------------------- 1 | {{outlet}} 2 | {{outlet 'next-example'}} 3 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/index.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" padding=(hash top="sm")}} 2 |
3 |
4 |
5 |

Examples

6 |
7 |
8 |
9 | {{/ui-section}} 10 | 11 | {{#ui-section name="examples-list" padding="xs"}} 12 |
13 | {{#if examples}} 14 |
    15 | {{#each examples as | example i |}} 16 |
  • 17 | {{#ui-panel depth="sm" depthHover="md"}} 18 | 19 |
    20 | {{#link-to 'documentation.examples.example' example.slug}} 21 |
    22 | {{add i 1}}. {{example.title}} 23 |
    24 | {{/link-to}} 25 |
    26 | 27 |
    28 |

    29 | {{example.description}} 30 |

    31 |
    32 | 33 |
    34 | {{ui-button-link-to 'View' 'documentation.examples.example' example.slug 35 | bg="blue" 36 | color="white" 37 | padding="sm" 38 | depthHover="md" 39 | rounded=false}} 40 |
    41 | 42 | {{/ui-panel}} 43 | 44 |
  • 45 | {{/each}} 46 |
47 | {{/if}} 48 |
49 | {{/ui-section}} 50 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/partials/next-example.hbs: -------------------------------------------------------------------------------- 1 | {{#if nextExample}} 2 |
3 | {{#ui-section name="next-example" padding="md"}} 4 |
5 |
6 |
7 |
Next Example...
8 |

{{nextExample.title}}

9 |

10 | {{#ui-button-link-to 'documentation.examples.example' nextExample.slug 11 | bg="blue" 12 | color="white" 13 | padding="md" 14 | inline=true}} 15 | Go! 16 | {{/ui-button-link-to}} 17 |
18 |
19 |
20 | {{/ui-section}} 21 | {{/if}} 22 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/templates/basic-animations.hbs: -------------------------------------------------------------------------------- 1 | {{#unless hide}} 2 | 3 | {{#ui-section name="header" padding=(hash top="md" bottom="sm")}} 4 |
5 |

{{example.title}}

6 |
7 |
8 | {{markdown-content 9 | (get-markdown-content 'snippets' 'documentation/examples/templates/basic-animations/intro') 10 | extensions="prettify"}} 11 |
12 |
13 |
14 | {{/ui-section}} 15 | 16 | {{#scrollmagic-animated animation='fade' triggerHook=0.9 duration='66%'}} 17 | {{#ui-section name="animations" padding="lg" bg="lt-gray" class="prettyprint-white"}} 18 |
19 |
20 |
21 | {{markdown-content 22 | (get-markdown-content 'snippets' 'documentation/examples/templates/basic-animations/animations') 23 | extensions="prettify"}} 24 |
25 |
26 |
27 | {{/ui-section}} 28 | {{/scrollmagic-animated}} 29 | 30 | {{#ui-section name="reverse" padding="lg"}} 31 |
32 |
33 |
34 | {{#scrollmagic-animated reverse=false animation='fade' triggerHook=0.9 duration='66%'}} 35 | {{markdown-content 36 | (get-markdown-content 'snippets' 'documentation/examples/templates/basic-animations/reverse') 37 | extensions="prettify"}} 38 | {{/scrollmagic-animated}} 39 |
40 |
41 |
42 | {{/ui-section}} 43 | 44 | {{#scrollmagic-animated animation='fade' triggerHook=0.9 duration='66%'}} 45 | {{#ui-section name="toggle" padding="lg" bg="lt-gray" class="prettyprint-white" as | section |}} 46 |
47 |
48 |
49 | {{#scrollmagic-toggle 50 | triggerHook=0.33 51 | triggerElement=section.element 52 | toggleElement=section.element 53 | toggleClasses='bg-blue color-white prettyprint-gray' 54 | toggleClassesOff='bg-lt-gray prettyprint-white'}} 55 | 56 | {{markdown-content 57 | (get-markdown-content 'snippets' 'documentation/examples/templates/basic-animations/toggle') 58 | extensions="prettify"}} 59 | 60 | {{/scrollmagic-toggle}} 61 |
62 |
63 |
64 | {{/ui-section}} 65 | {{/scrollmagic-animated}} 66 | 67 | {{#ui-section name="indicators" padding="lg"}} 68 |
69 | 70 |
71 |
72 | {{#scrollmagic-animated 73 | animation='fade' 74 | duration='50%' 75 | triggerHook=0.8 76 | indicators=(hash 77 | name='Check out these indicators!' 78 | colorStart='#1682fc' 79 | colorEnd='#1682fc' 80 | colorTrigger='transparent' 81 | ) 82 | }} 83 | {{markdown-content 84 | (get-markdown-content 'snippets' 'documentation/examples/templates/basic-animations/indicators') 85 | extensions="prettify"}} 86 | {{/scrollmagic-animated}} 87 |
88 |
89 |
90 | 91 | {{/ui-section}} 92 | 93 | {{#scrollmagic-animated animation='fade' triggerHook=0.9 duration='66%'}} 94 | 95 | {{#ui-section name="dynamic-properties" padding="lg" bg="dk-gray" color="white" class="prettyprint-gray"}} 96 |
97 | 98 |
99 |
100 | {{markdown-content 101 | (get-markdown-content 'snippets' 'documentation/examples/templates/basic-animations/dynamic-properties') 102 | extensions="prettify"}} 103 | 104 |

105 | triggerHook= {{input value=props.triggerHook type="number" min="0" max="1" step="0.05"}}   106 | duration= {{input value=props.duration type="number" min="1" max="200" step="1"}}% 107 | 108 |

109 |
110 |
111 |
112 | 113 |





114 | 115 | {{#scrollmagic-animated 116 | animation='fly-horizontal' 117 | duration=props.durationPercentage 118 | triggerHook=props.triggerHook}} 119 |
120 | Ember Rocket 121 |
122 | {{/scrollmagic-animated}} 123 | 124 | {{/ui-section}} 125 | {{/scrollmagic-animated}} 126 | 127 | {{#ui-section name="component-lifecycle" padding="lg"}} 128 |
129 |
130 |
131 | 132 | {{#scrollmagic-animated animation='fade' triggerHook=0.9 duration='66%'}} 133 | {{markdown-content 134 | (get-markdown-content 'snippets' 'documentation/examples/templates/basic-animations/component-lifecycle') 135 | extensions="prettify"}} 136 | 137 | {{#ui-button click=(toggle 'hide' this) bg="blue" color="white" padding="sm" inline=true}} 138 | {{if hide 'Show All Animations!' 'Hide All Animations!'}} 139 | {{/ui-button}} 140 | {{/scrollmagic-animated}} 141 | 142 |
143 |
144 |
145 | {{/ui-section}} 146 | 147 | {{else}} 148 | {{#ui-section name="hidden" padding="lg" bg="dk-gray" color="white" class="prettyprint-gray"}} 149 |
150 |
151 |
152 | {{markdown-content 153 | (get-markdown-content 'snippets' 'documentation/examples/templates/basic-animations/component-lifecycle-hidden') 154 | extensions="prettify"}} 155 | 156 | {{#ui-button click=(toggle 'hide' this) bg="blue" color="white" padding="sm" inline=true}} 157 | {{if hide 'Show All Animations!' 'Hide All Animations!'}} 158 | {{/ui-button}} 159 |
160 |
161 |
162 | {{/ui-section}} 163 | {{/unless}} 164 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/templates/component-scrolling.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" padding="md"}} 2 |
3 |

{{example.title}}

4 |
5 |
6 |

7 | Example coming soon... 8 |

9 |
10 |
11 |
12 | {{/ui-section}} 13 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/templates/custom-animations.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" padding="md"}} 2 |
3 |

{{example.title}}

4 |
5 |
6 |

7 | Example coming soon... 8 |

9 |
10 |
11 |
12 | {{/ui-section}} 13 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/templates/horizontal-scrolling.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" padding="md"}} 2 |
3 |

{{example.title}}

4 |
5 |
6 |

7 | Example coming soon... 8 |

9 |
10 |
11 |
12 | {{/ui-section}} 13 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/templates/parallax-sections.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" padding="md"}} 2 |
3 |

{{example.title}}

4 |
5 |
6 |

7 | Example coming soon... 8 |

9 |
10 |
11 |
12 | {{/ui-section}} 13 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/templates/pinned-items.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" padding="md"}} 2 |
3 |

{{example.title}}

4 |
5 |
6 | {{markdown-content 7 | (get-markdown-content 'snippets' 'documentation/examples/templates/pinned-items/intro') 8 | extensions="prettify"}} 9 |
10 |
11 |
12 | {{/ui-section}} 13 | 14 | {{#ui-section bg="lt-gray" padding=(hash top="md" bottom="md") class="prettyprint-white"}} 15 |
16 | 17 |
18 |
19 | {{markdown-content 20 | (get-markdown-content 'snippets' 'documentation/examples/templates/pinned-items/scroll-to-top') 21 | extensions="prettify"}} 22 |
23 |
24 | 25 |


26 | 27 | {{#scrollmagic-pinned triggerHook="onEnter" offset="50px" pinOptions=(hash spacerClass='scroll-top-pin-spacer')}} 28 |
29 | {{#ui-button click=(action interactivity.pinned-items.scrollToTop) 30 | bg="blue-dk" bgHover="blue" color="white" padding="sm" inline=true }} 31 | Top! 32 | {{/ui-button}} 33 |
34 | {{/scrollmagic-pinned}} 35 | 36 |


37 | 38 |
39 | 40 | {{/ui-section}} 41 | 42 | {{#ui-section padding=(hash top='md' bottom="md")}} 43 |
44 | 45 |
46 |
47 | {{markdown-content 48 | (get-markdown-content 'snippets' 'documentation/examples/templates/pinned-items/navbar') 49 | extensions="prettify"}} 50 |
51 |
52 | 53 |



54 | 55 | {{#scrollmagic-pinned duration=900 class="pin-navigation"}} 56 |
57 |
    58 |
  • 59 | Sticky Nav! 60 |
  • 61 |
  • 62 | Item 1 63 |
  • 64 |
  • 65 | Item 2 66 |
  • 67 |
  • 68 | Item 3 69 |
  • 70 |
71 |
72 | {{/scrollmagic-pinned}} 73 | 74 |
75 |








76 |

Content goes underneath!

77 |

78 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sic enim censent, oportunitatis esse beate vivere. Paulum, cum regem Persem captum adduceret, eodem flumine invectio? Idemne, quod iucunde? Duo Reges: constructio interrete. Invidiosum nomen est, infame, suspectum. Quae quo sunt excelsiores, eo dant clariora indicia naturae. Quae contraria sunt his, malane? Isto modo, ne si avia quidem eius nata non esset. Quae diligentissime contra Aristonem dicuntur a Chryippo. 79 |

80 |

81 | Quid est, quod ab ea absolvi et perfici debeat? Itaque hic ipse iam pridem est reiectus; Sed non alienum est, quo facilius vis verbi intellegatur, rationem huius verbi faciendi Zenonis exponere. Hoc non est positum in nostra actione. Duo Reges: constructio interrete. Ergo adhuc, quantum equidem intellego, causa non videtur fuisse mutandi nominis. Qui ita affectus, beatum esse numquam probabis; Aliter enim explicari, quod quaeritur, non potest. Prave, nequiter, turpiter cenabat; Huius ego nunc auctoritatem sequens idem faciam. 82 |

83 |

84 | At, illa, ut vobis placet, partem quandam tuetur, reliquam deserit. Et homini, qui ceteris animantibus plurimum praestat, praecipue a natura nihil datum esse dicemus? Duo Reges: constructio interrete. Qui igitur convenit ab alia voluptate dicere naturam proficisci, in alia summum bonum ponere? Si mala non sunt, iacet omnis ratio Peripateticorum. 85 |

86 |

87 | Si longus, levis. Quamquam id quidem, infinitum est in hac urbe; Aliter enim explicari, quod quaeritur, non potest. Duo Reges: constructio interrete. Non enim iam stirpis bonum quaeret, sed animalis. 88 |

89 |

90 | Dolere malum est: in crucem qui agitur, beatus esse non potest. Qui non moveatur et offensione turpitudinis et comprobatione honestatis? Ergo ita: non posse honeste vivi, nisi honeste vivatur? Nam Pyrrho, Aristo, Erillus iam diu abiecti. Isto modo, ne si avia quidem eius nata non esset. Quae diligentissime contra Aristonem dicuntur a Chryippo. Duo Reges: constructio interrete. Ergo adhuc, quantum equidem intellego, causa non videtur fuisse mutandi nominis. 91 |

92 |
93 |
94 | {{/ui-section}} 95 | 96 | {{#ui-section bg="lt-gray" padding=(hash top="md" bottom=false) class="prettyprint-white"}} 97 |
98 | 99 |
100 |
101 | {{markdown-content 102 | (get-markdown-content 'snippets' 'documentation/examples/templates/pinned-items/fullscreen-section') 103 | extensions="prettify"}} 104 |
105 |
106 | 107 |
108 | 109 |
110 |
111 |
112 |
113 |
114 | 115 | {{#scrollmagic-pinned duration='125%' pinOptions=(hash pushFollowers=true)}} 116 | {{#ui-panel name="pin-pushfollowers" bg="blue" color="white" rounded=false}} 117 |
118 |

I'm coming with you!

119 |
120 | {{/ui-panel}} 121 | {{/scrollmagic-pinned}} 122 | {{/ui-section}} 123 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/templates/responsive-animations.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" padding="md"}} 2 |
3 |

{{example.title}}

4 |
5 |
6 | {{markdown-content 7 | (get-markdown-content 'snippets' 'documentation/examples/templates/responsive-animations/intro') 8 | extensions="prettify"}} 9 |
10 |
11 | 12 |
13 |
14 |
15 |
16 | 17 | {{#scrollmagic-animated triggerHook=0.75 triggerOnMedia=(array "desktop") duration="100%" animation="fly-horizontal"}} 18 |
19 | Ember Rocket 20 |
21 | {{/scrollmagic-animated}} 22 | 23 |
24 | {{/ui-section}} 25 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/examples/templates/section-wipes-&-slides.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" padding="md"}} 2 |
3 |

{{example.title}}

4 |
5 |
6 |

7 | Example coming soon... 8 |

9 |
10 |
11 |
12 | {{/ui-section}} 13 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/guides.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section padding="xs"}} 2 |
3 |
4 |
5 |
6 | {{markdown-menu tree=tree linkTo='documentation.guides.single'}} 7 |
8 |
9 | {{ui-button-link-to 'View Examples' 'documentation.examples.index' 10 | bg="blue" 11 | color="white" 12 | padding="sm" 13 | depth="sm" 14 | depthHover="md"}} 15 |
16 |
17 |
18 |
19 | {{outlet}} 20 |
21 |
22 |
23 |
24 |
25 |
26 | {{/ui-section}} 27 | 28 | {{!partial 'components/ui-footer'}} 29 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/documentation/guides/single.hbs: -------------------------------------------------------------------------------- 1 | {{#if guide.content}} 2 |
3 | {{#if guide.attributes.title}} 4 |

{{guide.attributes.title}}

5 |
6 |
7 | {{/if}} 8 | {{markdown-content guide.content extensions="prettify"}} 9 |
10 | {{/if}} 11 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/head.hbs: -------------------------------------------------------------------------------- 1 | {{!-- 2 | Add content you wish automatically added to the documents head 3 | here. The 'model' available in this template can be populated by 4 | setting values on the 'head-data' service. 5 | --}} 6 | 7 | {{model.title}} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/index.hbs: -------------------------------------------------------------------------------- 1 | {{#ui-section name="header" bg="blue" color="white"}} 2 |
3 |
4 |
5 | 6 | Ember ScrollMagic 7 | 8 |


9 | 10 |
Build magical scroll interactions Ember using ScrollMagic.js.
11 | 12 |

13 | 14 | {{ui-button-link-to 'View Examples' 'documentation.examples' 15 | bg="blue-dk" 16 | bgHover="white" 17 | color="white" 18 | colorHover="blue" 19 | inline=true 20 | padding="md" 21 | depth="xs" depthHover="md" }} 22 |   23 | {{ui-button-link-to 'Read Guides' 'documentation.guides' 24 | bg="blue-dk" 25 | bgHover="white" 26 | color="white" 27 | colorHover="blue" 28 | inline=true 29 | padding="md" 30 | depth="xs" depthHover="md" }} 31 |   32 | {{ui-button-link 'GitHub' 33 | href="https://github.com/willviles/ember-scrollmagic" 34 | target="_blank" 35 | bg="blue-dk" 36 | bgHover="white" 37 | color="white" 38 | colorHover="blue" 39 | inline=true 40 | padding="md" 41 | depth="xs" depthHover="md" }} 42 | 43 |
44 |
45 |
46 | {{/ui-section}} 47 | -------------------------------------------------------------------------------- /tests/dummy/app/utils/property-class-name-binding.js: -------------------------------------------------------------------------------- 1 | import { assign } from '@ember/polyfills'; 2 | import { computed, get } from '@ember/object'; 3 | import { dasherize } from '@ember/string'; 4 | import { typeOf } from '@ember/utils'; 5 | 6 | export default function(property, opts) { 7 | return computed(property, function() { 8 | let value = get(this, property); 9 | 10 | opts = assign({ 11 | prefix: dasherize(property), 12 | values: false 13 | }, opts); 14 | 15 | if (typeOf(value) === 'string') { 16 | return `${opts.prefix}-${value}`; 17 | } else if (typeOf(value) === 'boolean') { 18 | return value; 19 | } else if (typeOf(value) === 'object') { 20 | if (typeOf(opts.values) === 'array') { 21 | return opts.values.reduce((arr, key) => { 22 | return value[key] ? 23 | [...arr, `${opts.prefix}-${key}-${value[key]}`] : 24 | [...arr]; 25 | }, []).join(' '); 26 | } else { 27 | return; 28 | } 29 | 30 | } 31 | }); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /tests/dummy/config/environment.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | 4 | module.exports = function(environment) { 5 | let ENV = { 6 | modulePrefix: 'dummy', 7 | environment, 8 | rootURL: '/', 9 | locationType: 'router-scroll', 10 | historySupportMiddleware: true, 11 | EmberENV: { 12 | FEATURES: { 13 | // Here you can enable experimental features on an ember canary build 14 | // e.g. 'with-controller': true 15 | }, 16 | EXTEND_PROTOTYPES: { 17 | // Prevent Ember Data from overriding Date.parse. 18 | Date: false 19 | } 20 | }, 21 | 22 | APP: { 23 | // Here you can pass flags/options to your application instance 24 | // when it is created 25 | } 26 | 27 | }; 28 | 29 | // @addon Ember ScrollMagic 30 | // @url https://github.com/willviles/ember-scrollmagic 31 | 32 | ENV['ember-scrollmagic'] = { 33 | indicators: true 34 | }; 35 | 36 | // @addon Ember GSAP 37 | // @url https://github.com/willviles/ember-gsap 38 | 39 | ENV['ember-gsap'] = { 40 | plugins: [ 41 | 'scrollTo' 42 | ] 43 | }; 44 | 45 | // @addon Ember CLI Fastboot 46 | // @url https://github.com/ember-fastboot/ember-cli-fastboot 47 | 48 | ENV['fastboot'] = { 49 | hostWhitelist: [/^localhost:\d+$/] 50 | }; 51 | 52 | // @addon Ember CLI Markdown Resolver 53 | // @url https://github.com/willviles/ember-cli-markdown-resolver 54 | 55 | ENV['ember-cli-markdown-resolver'] = { 56 | folders: { 57 | guides: 'app/guides', 58 | snippets: 'app/snippets' 59 | } 60 | }; 61 | 62 | // @addon Ember Code Prettify 63 | // @url https://github.com/willviles/ember-code-prettify 64 | 65 | ENV['ember-code-prettify'] = { 66 | languages: ['css', 'yaml'], 67 | skin: 'desert' 68 | }; 69 | 70 | // @addon Ember CLI Google Fonts 71 | // @url https://github.com/damiencaselli/ember-cli-google-fonts 72 | 73 | ENV['googleFonts'] = [ 74 | 'Overpass:300,400,800' 75 | ]; 76 | 77 | if (environment === 'development') { 78 | // ENV.APP.LOG_RESOLVER = true; 79 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 80 | // ENV.APP.LOG_TRANSITIONS = true; 81 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 82 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 83 | } 84 | 85 | if (environment === 'test') { 86 | // Testem prefers this... 87 | ENV.locationType = 'none'; 88 | 89 | // keep test console output quieter 90 | ENV.APP.LOG_ACTIVE_GENERATION = false; 91 | ENV.APP.LOG_VIEW_LOOKUPS = false; 92 | 93 | ENV.APP.rootElement = '#ember-testing'; 94 | } 95 | 96 | if (environment === 'production') { 97 | ENV.locationType = 'hash'; 98 | ENV.rootURL = '/ember-scrollmagic/'; 99 | // here you can enable a production-specific feature 100 | } 101 | 102 | return ENV; 103 | }; 104 | -------------------------------------------------------------------------------- /tests/dummy/config/targets.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = { 3 | browsers: [ 4 | 'ie 9', 5 | 'last 1 Chrome versions', 6 | 'last 1 Firefox versions', 7 | 'last 1 Safari versions' 8 | ] 9 | }; 10 | -------------------------------------------------------------------------------- /tests/dummy/public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /tests/dummy/public/images/ember-rocket.svg: -------------------------------------------------------------------------------- 1 | ember-rocket -------------------------------------------------------------------------------- /tests/dummy/public/images/facebook.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/public/images/facebook.jpg -------------------------------------------------------------------------------- /tests/dummy/public/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/public/images/favicon-16x16.png -------------------------------------------------------------------------------- /tests/dummy/public/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/public/images/favicon-32x32.png -------------------------------------------------------------------------------- /tests/dummy/public/images/favicon-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/public/images/favicon-64x64.png -------------------------------------------------------------------------------- /tests/dummy/public/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/public/images/favicon.ico -------------------------------------------------------------------------------- /tests/dummy/public/images/logo-navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/dummy/public/images/logo-navbar.png -------------------------------------------------------------------------------- /tests/dummy/public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /tests/helpers/destroy-app.js: -------------------------------------------------------------------------------- 1 | import { run } from '@ember/runloop'; 2 | 3 | export default function destroyApp(application) { 4 | run(application, 'destroy'); 5 | } 6 | -------------------------------------------------------------------------------- /tests/helpers/module-for-acceptance.js: -------------------------------------------------------------------------------- 1 | import { module } from 'qunit'; 2 | import { resolve } from 'rsvp'; 3 | import startApp from '../helpers/start-app'; 4 | import destroyApp from '../helpers/destroy-app'; 5 | 6 | export default function(name, options = {}) { 7 | module(name, { 8 | beforeEach() { 9 | this.application = startApp(); 10 | 11 | if (options.beforeEach) { 12 | return options.beforeEach.apply(this, arguments); 13 | } 14 | }, 15 | 16 | afterEach() { 17 | let afterEach = options.afterEach && options.afterEach.apply(this, arguments); 18 | return resolve(afterEach).then(() => destroyApp(this.application)); 19 | } 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /tests/helpers/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from '../../resolver'; 2 | import config from '../../config/environment'; 3 | 4 | const resolver = Resolver.create(); 5 | 6 | resolver.namespace = { 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix 9 | }; 10 | 11 | export default resolver; 12 | -------------------------------------------------------------------------------- /tests/helpers/start-app.js: -------------------------------------------------------------------------------- 1 | import Application from '../../app'; 2 | import config from '../../config/environment'; 3 | import { merge } from '@ember/polyfills'; 4 | import { run } from '@ember/runloop'; 5 | 6 | export default function startApp(attrs) { 7 | let attributes = merge({}, config.APP); 8 | attributes = merge(attributes, attrs); // use defaults, but you can override; 9 | 10 | return run(() => { 11 | let application = Application.create(attributes); 12 | application.setupForTesting(); 13 | application.injectTestHelpers(); 14 | return application; 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dummy Tests 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | {{content-for "test-head"}} 12 | 13 | 14 | 15 | 16 | 17 | {{content-for "head-footer"}} 18 | {{content-for "test-head-footer"}} 19 | 20 | 21 | {{content-for "body"}} 22 | {{content-for "test-body"}} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {{content-for "body-footer"}} 31 | {{content-for "test-body-footer"}} 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/integration/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/integration/.gitkeep -------------------------------------------------------------------------------- /tests/test-helper.js: -------------------------------------------------------------------------------- 1 | import Application from '../app'; 2 | import { setApplication } from '@ember/test-helpers'; 3 | import { start } from 'ember-qunit'; 4 | 5 | setApplication(Application.create({ autoboot: false })); 6 | 7 | start(); 8 | -------------------------------------------------------------------------------- /tests/unit/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/tests/unit/.gitkeep -------------------------------------------------------------------------------- /vendor/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willviles/ember-scrollmagic/03625a813e9f68c2d79cc7f1277a5ac1a7570120/vendor/.gitkeep -------------------------------------------------------------------------------- /vendor/shims/scrollmagic.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node:true */ 2 | 3 | (function() { 4 | /* globals define, self */ 5 | 6 | function scrollMagicUndefined() { 7 | var error = "ScrollMagic is not available. Either the bower package is missing or your app is in Fastboot Mode."; 8 | 9 | function throwError() { 10 | throw Error(error); 11 | } 12 | 13 | this.Scene = throwError(); 14 | this.Controller = throwError(); 15 | 16 | throwError(); 17 | } 18 | 19 | define('scrollmagic', [], function() { 20 | 'use strict'; 21 | return { 'default': self['ScrollMagic'] || scrollMagicUndefined }; 22 | }); 23 | 24 | })(); 25 | --------------------------------------------------------------------------------