├── .gitignore
├── tests
└── tests.js
├── lib
├── at_famous_form.js
├── at_famous_oauth.js
├── at_famous_oauth.html
├── full_page_at_famous_form.html
├── full_page_at_famous_form.js
├── at_pwd_form_btn.js
├── at_configure_anim.js
├── default_animations.js
├── at_famous_form.html
└── famous_wrapper.js
├── README.md
├── LICENSE
└── package.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .build*
2 | versions.json
3 |
--------------------------------------------------------------------------------
/tests/tests.js:
--------------------------------------------------------------------------------
1 |
2 | // TODO: write tests!!!
--------------------------------------------------------------------------------
/lib/at_famous_form.js:
--------------------------------------------------------------------------------
1 | // Uses atFamousForm template in place of the original atForm
2 | Template.atFamousForm.replaces("atForm");
--------------------------------------------------------------------------------
/lib/at_famous_oauth.js:
--------------------------------------------------------------------------------
1 | // Uses atFamousOauth template in place of the original atOauth
2 | Template.atFamousOauth.replaces("atOauth");
--------------------------------------------------------------------------------
/lib/at_famous_oauth.html:
--------------------------------------------------------------------------------
1 |
2 | {{#famousEach oauthService}}
3 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
4 | {{> atSocial}}
5 | {{/Surface}}
6 | {{/famousEach}}
7 |
8 |
--------------------------------------------------------------------------------
/lib/full_page_at_famous_form.html:
--------------------------------------------------------------------------------
1 |
2 | {{#View size="[undefined,undefined]"}}
3 | {{#ContainerSurface size="[400,undefined]" origin="[0.5,0]" align="[0.5,0]"}}
4 | {{> atForm}}
5 | {{/ContainerSurface}}
6 | {{/View}}
7 |
--------------------------------------------------------------------------------
/lib/full_page_at_famous_form.js:
--------------------------------------------------------------------------------
1 | // Uses this template in place of the original atForm
2 | Template.fullPageAtFamousForm.replaces("fullPageAtForm");
3 |
4 | Template.fullPageAtFamousForm.helpers({
5 | colSize: function() {
6 | var winW = windowSize().width;
7 | var width;
8 | if (winW > 400)
9 | width = 400 + (winW - 400) / 10;
10 | return [ width, undefined ];
11 | },
12 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | useraccounts:famous-wrapper
2 | ===========================
3 |
4 | A very smart [Famo.us](http://famo.us) wrapper which uses [famous-views](https://atmospherejs.com/gadicohen/famous-views) to wrap up any version of AccountsTemplates to give you animated sign up and sign in templates straight away!
5 |
6 | You can lear how to use it reading [Wrapping Up for Famo.us](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#wrapping-up-for-famo.us) chapter inside the official [Guide](https://github.com/meteor-useraccounts/core/blob/master/Guide.md) for AccountsTemplates.
7 |
8 | Lets have a look at a [live demo application](http://accounts-templates-famous-wrapper.meteor.com)!
9 |
10 |
11 | ## Bring Your Own Famo.us
12 |
13 | Adding this package with `mrt add useraccounts:famous-wrapper` does not add any other packages providing Famo.us. This is to let you choose your preferred way to include Famo.us!
14 |
--------------------------------------------------------------------------------
/lib/at_pwd_form_btn.js:
--------------------------------------------------------------------------------
1 | // Register a 'rendered' callback on the submit button
2 | // to attach _uihooks to the atPwdForm
3 | // this way, every time the atPwdForm content changed
4 | // the container fview is asked to recompute its height
5 |
6 | Template.atPwdFormBtn.rendered = function(){
7 | var fview = FView.from(this);
8 | this.firstNode.parentNode._uihooks = {
9 | // everytime something is inserted...
10 | insertElement: function (node, next) {
11 | // ...asks to recompute the height
12 | fview.autoHeight();
13 | // then simply insert the element as required
14 | $(node).insertBefore(next);
15 | },
16 | // everytime something is removed...
17 | removeElement: function(node) {
18 | // ...asks to recompute the height
19 | fview.autoHeight();
20 | // then simply remove the element as required
21 | $(node).remove();
22 | }
23 | };
24 | };
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 splendido
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/lib/at_configure_anim.js:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------
2 | // Adds configureAnimations to AccountsTemplates
3 | // --------------------------------------------------
4 |
5 | ANIMATION_SUB_PAT = {
6 | default: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
7 | atTitle: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
8 | atSigninLink: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
9 | atSocial: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
10 | atSep: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
11 | atError: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
12 | atResult: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
13 | atMessage: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
14 | atPwdForm: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
15 | atSignupLink: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
16 | atTermsLink: Match.Optional(Match.OneOf(null, Match.Where(_.isFunction))),
17 | };
18 |
19 | ANIMATION_PAT = {
20 | render: Match.Optional(ANIMATION_SUB_PAT),
21 | destroy: Match.Optional(ANIMATION_SUB_PAT),
22 | state_change: Match.Optional(ANIMATION_SUB_PAT),
23 | animQueueDelay: Match.Optional(Number),
24 | animQueueStartDelay: Match.Optional(Number),
25 | setStateDelay: Match.Optional(Number),
26 | };
27 |
28 |
29 | AccountsTemplates.configureAnimations = function(options){
30 | if (Meteor.isClient){
31 | check(options, ANIMATION_PAT);
32 | if (options.render)
33 | this.animations.render = _.defaults(options.render, this.animations.render);
34 | if (options.destroy)
35 | this.animations.destroy = _.defaults(options.destroy, this.animations.destroy);
36 | if (options.state_change)
37 | this.animations.state_change = _.defaults(options.state_change, this.animations.state_change);
38 | options = _.omit(options, "render", "destroy", "state_change");
39 | this.animations = _.defaults(options, this.animations);
40 | }
41 | };
--------------------------------------------------------------------------------
/package.js:
--------------------------------------------------------------------------------
1 | Package.describe({
2 | summary: 'Famo.us wrapper for Accounts Templates.',
3 | version: '1.13.1',
4 | name: 'useraccounts:famous-wrapper',
5 | git: 'https://github.com/meteor-useraccounts/famous-wrapper.git',
6 | });
7 |
8 | Package.on_use(function(api, where) {
9 | api.versionsFrom('METEOR@1.0');
10 |
11 | api.use([
12 | 'reactive-dict',
13 | 'templating',
14 | ], 'client');
15 |
16 | api.use([
17 | 'check',
18 | 'underscore',
19 | 'useraccounts:core',
20 | 'gadicohen:famous-views',
21 | 'aldeed:template-extension'
22 | ], ['client', 'server']);
23 |
24 | api.imply([
25 | 'useraccounts:core@1.13.1',
26 | 'gadicohen:famous-views@0.1.22',
27 | 'aldeed:template-extension@3.1.1',
28 | ], ['client', 'server']);
29 |
30 | //api.use('mjnetworks:famous@0.2.2-1', ['client']/*, { weak: true }*/);
31 |
32 | api.use('useraccounts:bootstrap@1.13.1', ['client', 'server'], {
33 | weak: true
34 | });
35 | api.use('useraccounts:foundation@1.13.1', ['client', 'server'], {
36 | weak: true
37 | });
38 | api.use('useraccounts:ionic@1.8.1', ['client', 'server'], {
39 | weak: true
40 | });
41 | api.use('useraccounts:ratchet@1.8.1', ['client', 'server'], {
42 | weak: true
43 | });
44 | api.use('useraccounts:semantic-ui@1.13.1', ['client', 'server'], {
45 | weak: true
46 | });
47 | api.use('useraccounts:unstyled@1.13.1', ['client', 'server'], {
48 | weak: true
49 | });
50 |
51 | api.add_files([
52 | 'lib/at_famous_form.html',
53 | 'lib/at_famous_form.js',
54 | 'lib/at_famous_oauth.html',
55 | 'lib/at_famous_oauth.js',
56 | 'lib/at_pwd_form_btn.js',
57 | 'lib/full_page_at_famous_form.html',
58 | 'lib/full_page_at_famous_form.js',
59 | 'lib/default_animations.js',
60 | 'lib/famous_wrapper.js',
61 | ], ['client']);
62 |
63 | api.add_files([
64 | 'lib/at_configure_anim.js',
65 | ], ['client', 'server']);
66 | });
67 |
68 | Package.on_test(function(api) {
69 | api.use([
70 | 'useraccounts:core@1.13.1',
71 | ]);
72 | api.use(['tinytest', 'test-helpers'], ['client', 'server']);
73 | api.add_files('tests/tests.js', ['client', 'server']);
74 | });
75 |
--------------------------------------------------------------------------------
/lib/default_animations.js:
--------------------------------------------------------------------------------
1 | var Transform;
2 | var Easing;
3 | FView.ready(function(require) {
4 | Transform = famous.core.Transform;
5 | Easing = famous.transitions.Easing;
6 | });
7 |
8 |
9 | // ---------------------------------------
10 | // Default animation function for entrance
11 | // ---------------------------------------
12 |
13 | fallFromTop = function(fview){
14 | fview.modifier.setTransform(Transform.translate(0, -$(window).height()));
15 | AccountsTemplates.pushToAnimationQueue(function() {
16 | fview.modifier.setTransform(
17 | Transform.translate(0,0),
18 | { duration : 450, curve: Easing.easeOutSine }
19 | );
20 | }, false);
21 | };
22 |
23 |
24 | // -------------------------------------------
25 | // Default animation function for state change
26 | // -------------------------------------------
27 |
28 | vFlip = function(fview){
29 | fview.modifier.setTransform(
30 | Transform.rotate(Math.PI-0.05,0,0),
31 | { duration : AccountsTemplates.animations.setStateDelay, curve: "easeIn" },
32 | function() {
33 | fview.modifier.setTransform(
34 | Transform.rotate(-0.1,0,0),
35 | { duration : AccountsTemplates.animations.setStateDelay, curve: "easeOut" }
36 | );
37 | }
38 | );
39 | };
40 |
41 |
42 | // -------------------------------------------
43 | // Default animation functions for destruction
44 | // -------------------------------------------
45 |
46 | slideRightDestroy = function(fview){
47 | fview.modifier.setTransform(
48 | Transform.translate($(window).width(),0),
49 | { duration : 250, curve: Easing.easeOutSine },
50 | function() { fview.destroy();}
51 | );
52 | };
53 |
54 | blastOutDestroy = function(fview){
55 | var angle = Math.random() * Math.PI;
56 | fview.modifier.setTransform(
57 | Transform.multiply(
58 | Transform.translate( Math.cos(angle) * 1.5 * $(window).height(), Math.sin(angle) * 1.5 * $(window).width()),
59 | Transform.aboutOrigin([200, 21, 0], Transform.rotate(0,0, Math.random() > 0.5 ? Math.PI : -Math.PI))
60 | ),
61 | { duration : 400, curve: Easing.easeOutCirc},
62 | function() { fview.destroy();}
63 | );
64 | };
--------------------------------------------------------------------------------
/lib/at_famous_form.html:
--------------------------------------------------------------------------------
1 |
2 | {{#unless hide}}
3 | {{#ContainerSurface size="[undefined, undefined]" class="at-form"}}
4 | {{#SequentialLayout size="[undefined, auto]"}}
5 | {{#famousIf showTitle}}
6 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
7 | {{> atTitle}}
8 | {{/Surface}}
9 | {{/famousIf}}
10 | {{#famousIf showOauthServices}}
11 | {{> atOauth}}
12 | {{/famousIf}}
13 | {{#famousIf showServicesSeparator}}
14 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
15 | {{> atSep}}
16 | {{/Surface}}
17 | {{/famousIf}}
18 | {{#famousIf showError}}
19 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
20 | {{> atError}}
21 | {{/Surface}}
22 | {{/famousIf}}
23 | {{#famousIf showResult}}
24 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
25 | {{> atResult}}
26 | {{/Surface}}
27 | {{/famousIf}}
28 | {{#famousIf showMessage}}
29 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
30 | {{> atMessage}}
31 | {{/Surface}}
32 | {{/famousIf}}
33 | {{#famousIf showPwdForm}}
34 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
35 | {{> atPwdForm}}
36 | {{/Surface}}
37 | {{/famousIf}}
38 | {{#famousIf showSignInLink}}
39 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
40 | {{> atSigninLink}}
41 | {{/Surface}}
42 | {{/famousIf}}
43 | {{#famousIf showSignUpLink}}
44 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
45 | {{> atSignupLink}}
46 | {{/Surface}}
47 | {{/famousIf}}
48 | {{#famousIf showTermsLink}}
49 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
50 | {{> atTermsLink}}
51 | {{/Surface}}
52 | {{/famousIf}}
53 | {{#famousIf showResendVerificationEmailLink}}
54 | {{#Surface size="[undefined, auto]" modifier="StateModifier"}}
55 | {{> atResendVerificationEmailLink}}
56 | {{/Surface}}
57 | {{/famousIf}}
58 | {{/SequentialLayout}}
59 | {{/ContainerSurface}}
60 | {{/unless}}
61 |
62 |
--------------------------------------------------------------------------------
/lib/famous_wrapper.js:
--------------------------------------------------------------------------------
1 |
2 | // ---------------------------------------------------
3 | // Adds to AccountsTemplates a list of templates to be
4 | // rendered within surfaces with corresponding helpers
5 | // from atForm to be used to determine whether the
6 | // template is visible or not
7 | // ---------------------------------------------------
8 |
9 | AccountsTemplates.surfaces = {
10 | atTitle: AccountsTemplates.atFormHelpers.showTitle,
11 | atSigninLink: AccountsTemplates.atFormHelpers.showSignInLink,
12 | atSocial: AccountsTemplates.atFormHelpers.showOauthServices,
13 | atSep: AccountsTemplates.atFormHelpers.showServicesSeparator,
14 | atError: AccountsTemplates.atFormHelpers.showError,
15 | atResult: AccountsTemplates.atFormHelpers.showResult,
16 | atMessage: AccountsTemplates.atFormHelpers.showMessage,
17 | atPwdForm: AccountsTemplates.atFormHelpers.showPwdForm,
18 | atSignupLink: AccountsTemplates.atFormHelpers.showSignUpLink,
19 | atTermsLink: AccountsTemplates.atFormHelpers.showTermsLink,
20 | };
21 |
22 |
23 | // -----------------------------------------------------
24 | // Adds an object to keep track of rendered famous views
25 | // -----------------------------------------------------
26 |
27 | AccountsTemplates.fviews = {};
28 |
29 |
30 | // --------------------------------------------
31 | // Adds an animation queue to AccountsTemplates
32 | // --------------------------------------------
33 |
34 | AccountsTemplates.animationQueue = [];
35 |
36 | AccountsTemplates.nextAnimation = function(){
37 | var aq = this.animationQueue;
38 | if (aq.length){
39 | aq.shift()();
40 | if (aq.length)
41 | Meteor.setTimeout(function(){AccountsTemplates.nextAnimation();}, this.animations.animQueueDelay);
42 | }
43 | };
44 |
45 | AccountsTemplates.pushToAnimationQueue = function(func, at_begin){
46 | var aq = this.animationQueue;
47 | var firstAnim = !aq.length;
48 | if (at_begin === true)
49 | aq.unshift(func);
50 | else
51 | aq.push(func);
52 | if (firstAnim)
53 | Meteor.setTimeout(function(){AccountsTemplates.nextAnimation();}, this.animations.animQueueStartDelay);
54 | };
55 |
56 | // ----------------------------------------------------------
57 | // Adds default animation configurations to AccountsTemplates
58 | // ----------------------------------------------------------
59 |
60 | AccountsTemplates.animations = {
61 | render: {
62 | default: fallFromTop,
63 | },
64 | destroy: {
65 | //default: spinOutDestroy,
66 | default: slideRightDestroy,
67 | atSocial: blastOutDestroy,
68 | },
69 | state_change: {
70 | default: vFlip,
71 | },
72 | animQueueDelay: 150, // milliseconds
73 | animQueueStartDelay: 200, // milliseconds
74 | setStateDelay: 300, // milliseconds
75 | };
76 |
77 |
78 | // ----------------------------------------------
79 | // Add the animate functions to AccountsTemplates
80 | // ----------------------------------------------
81 |
82 | AccountsTemplates.animate = function(fview, tmplt, kind){
83 | // Retrieves configured animations for 'kind'
84 | // (which can be 'render', 'destroy', 'state_change')
85 | var anims = this.animations[kind];
86 | // Takes the animation for the specified 'tmplt'
87 | // or falls back to the 'default' one (if any...)
88 | var animFunc = anims[tmplt] || anims.default;
89 | // Triggers the animation only in case one was found...
90 | if (animFunc)
91 | animFunc(fview);
92 | else if(kind === 'destroy')
93 | fview.destroy();
94 | };
95 |
96 |
97 | // -----------------------------------------------------------------------------------------
98 | // Overrides the original setState method to be able to trigger switchState renderAnimations
99 | // -----------------------------------------------------------------------------------------
100 |
101 | var originalSetState = AccountsTemplates.setState;
102 | AccountsTemplates.setState = function(state, callback) {
103 | Tracker.nonreactive(function(){
104 | var delay = false;
105 |
106 | // Goes through each rendered surface...
107 | _.each(AccountsTemplates.fviews, function(tmplt, fview_id){
108 | var fview = FView.byId(fview_id);
109 | var visible = AccountsTemplates.surfaces[tmplt];
110 | // ...to check whether it is already visible and will
111 | // still be visible in next state...
112 | if (fview && visible() && visible(state)){
113 | // ...so to trigger a state change animation.
114 | AccountsTemplates.animate(fview, tmplt, 'state_change');
115 | delay = true;
116 | }
117 | });
118 |
119 | // Calls the original setState method that AccountsTemplates overrides
120 | if (delay)
121 | // Applies the new state after a certain delay only
122 | // in case there is some state change animation to perform...
123 | Meteor.setTimeout(function(){
124 | originalSetState.call(AccountsTemplates, state, callback);
125 | }, AccountsTemplates.animations.setStateDelay);
126 | else
127 | // ...otherwise changes state straight away!
128 | originalSetState.call(AccountsTemplates, state, callback);
129 | });
130 | };
131 |
132 |
133 | // Associates to each template to be rendered within a Surface
134 | // a 'rendered' function which triggers the animation for the
135 | // entrance and register another callback to trigger another
136 | // animation on destruction...
137 |
138 | _.each(_.keys(AccountsTemplates.surfaces), function(tmplt){
139 | Template[tmplt].rendered = function(){
140 | var fview = FView.from(this);
141 | // Register the fview among rendered ones...
142 | AccountsTemplates.fviews[fview.id] = tmplt;
143 | // Trigger entrance animation
144 | AccountsTemplates.animate(fview, tmplt, 'render');
145 | // Asks not to destroy the surface right away...
146 | fview.preventDestroy();
147 | // ...and register a destroy callback...
148 | fview.onDestroy = function(){
149 | // ...to trigger destroy animation!
150 | AccountsTemplates.animate(fview, tmplt, 'destroy');
151 | // Finally de-register the surface from the list of rendered ones
152 | delete AccountsTemplates.fviews[fview.id];
153 | };
154 | };
155 | });
156 |
--------------------------------------------------------------------------------