├── .versions ├── README.md ├── accounts-ui-react-tests.js ├── accounts-ui-react.js ├── composeWithTracker.js ├── package.js └── style.css /.versions: -------------------------------------------------------------------------------- 1 | accounts-base@1.2.4 2 | accounts-ui@1.1.7 3 | accounts-ui-unstyled@1.1.10 4 | allow-deny@1.0.2 5 | babel-compiler@6.5.2 6 | babel-runtime@0.1.7 7 | base64@1.0.9 8 | binary-heap@1.0.9 9 | blaze@2.1.5 10 | blaze-html-templates@1.0.2 11 | blaze-tools@1.0.10 12 | boilerplate-generator@1.0.6 13 | caching-compiler@1.0.2 14 | caching-html-compiler@1.0.4 15 | callback-hook@1.0.9 16 | check@1.1.3 17 | ddp@1.2.3 18 | ddp-client@1.2.3 19 | ddp-common@1.2.3 20 | ddp-rate-limiter@1.0.2 21 | ddp-server@1.2.4 22 | deps@1.0.12 23 | diff-sequence@1.0.6 24 | ecmascript@0.4.1 25 | ecmascript-runtime@0.2.9 26 | ejson@1.0.12 27 | geojson-utils@1.0.7 28 | html-tools@1.0.11 29 | htmljs@1.0.11 30 | id-map@1.0.8 31 | jquery@1.11.7 32 | jsx@0.2.4 33 | less@2.5.6 34 | local-test:okgrow:accounts-ui-react@0.8.0 35 | localstorage@1.0.7 36 | logging@1.0.12 37 | meteor@1.1.16 38 | minifier-js@1.1.13 39 | minimongo@1.0.12 40 | modules@0.5.2 41 | modules-runtime@0.6.5 42 | mongo@1.1.5 43 | mongo-id@1.0.2 44 | npm-mongo@1.4.45 45 | observe-sequence@1.0.9 46 | okgrow:accounts-ui-react@0.8.0 47 | ordered-dict@1.0.8 48 | promise@0.6.6 49 | random@1.0.7 50 | rate-limit@1.0.2 51 | reactive-dict@1.1.5 52 | reactive-var@1.0.10 53 | retry@1.0.5 54 | routepolicy@1.0.8 55 | service-configuration@1.0.7 56 | session@1.1.3 57 | spacebars@1.0.9 58 | spacebars-compiler@1.0.12 59 | templating@1.1.7 60 | templating-tools@1.0.2 61 | thereactivestack:blazetoreact@1.0.2 62 | tinytest@1.0.8 63 | tmeasday:check-npm-versions@0.2.0 64 | tracker@1.0.15 65 | ui@1.0.9 66 | underscore@1.0.9 67 | webapp@1.2.6 68 | webapp-hashing@1.0.7 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # accounts-ui-react 2 | 3 | The Meteor accounts-ui we know and love, wrapped in React. 4 | 5 | ## Installation 6 | 7 | Assuming you've already got a React project up and running: 8 | 9 | **Add the meteor package** 10 | 11 | ``` 12 | meteor add okgrow:accounts-ui-react 13 | ``` 14 | 15 | **Add the npm dependencies for this package** 16 | 17 | ``` 18 | npm install --save react-komposer classnames 19 | ``` 20 | 21 | **Add at least one [accounts login provider](https://guide.meteor.com/accounts.html#accounts-ui). For example:** 22 | 23 | ``` 24 | meteor add accounts-password 25 | ``` 26 | 27 | ## Basic Usage 28 | 29 | Simply import and use the `` component. For example: 30 | 31 | ``` 32 | import React from 'react'; 33 | import { LoginButtons } from 'meteor/okgrow:accounts-ui-react'; 34 | 35 | const App = () => ( 36 |
37 |

App

38 | 39 |
40 | ); 41 | 42 | export default App; 43 | ``` 44 | Example at: [https://github.com/okgrow/accounts-ui-react-example](https://github.com/okgrow/accounts-ui-react-example) 45 | 46 | ## Advanced Usage via Props 47 | 48 | ### Visible 49 | 50 | The login form is hidden by default with a dropdown behavior. If you want to show the dropdown by default, use the `visible` prop. 51 | 52 | `` 53 | 54 | ### State 55 | 56 | Set the initial state of the login form using the `state` prop. Choose from `signUp` and `forgotPassword`. `signIn` is the default behavior. 57 | 58 | `` 59 | 60 | ### hideLinks 61 | 62 | Stop your user changing the state using the `hideLinks` prop. A good example of this might be when you are separating our your signUp and signIn forms onto different routes. 63 | 64 | `` 65 | 66 | This will generate a `signUp` form that the user can't toggle or hide. 67 | 68 | ## Styles 69 | 70 | We have made the styles a little simpler than the original ones, but recommend you skin the form to match your app. 71 | 72 | ## Known limitations 73 | 74 | ### static-html vs blaze-html-templates 75 | 76 | This package uses the original Blaze accounts-ui package under the hood and is therefore incompatible with the static-html package. If you get this error when starting your app: 77 | 78 | ``` 79 | error: conflict: two packages included in the app (templating and static-html) are both trying to handle *.html 80 | ``` 81 | 82 | then you will need to run the following: 83 | 84 | ``` 85 | meteor remove static-html 86 | meteor add blaze-html-templates 87 | ``` 88 | ### Target container is not a DOM element 89 | 90 | If you remove this package as usual with `meteor remove okgrow:accounts-ui-react`, but don't have `blaze-html-templates`installed, your app may fail to render, throwing an error in the browser console: 91 | 92 | ``` 93 | Uncaught Invariant Violation: _registerComponent(...): Target container is not a DOM element. 94 | ``` 95 | 96 | To solve this, you can add either `static-html` or `blaze-html-templates` as appropriate to your app's needs. 97 | 98 | ## Update Note 99 | 100 | ###v0.8 101 | Note that this package uses `composeWithTracker`, which was removed in Komposer2.0. 102 | In `v0.8` of this package, the following snippet which was copied into `composeWithTracker.js` is used to bring back `composeWithTracker`'s functionality. 103 | https://github.com/TobyEalden/react-komposer/blob/3c87a1724590cb24303a2c4d7ec8ed88f834e5db/README.md#for-meteors-tracker 104 | 105 | 106 | ## Todo 107 | 108 | - Add tests 109 | - Verify social logins 110 | -------------------------------------------------------------------------------- /accounts-ui-react-tests.js: -------------------------------------------------------------------------------- 1 | // Import Tinytest from the tinytest Meteor package. 2 | import { Tinytest } from "meteor/tinytest"; 3 | 4 | // Import and rename a variable exported by accounts-ui-react.js. 5 | import { name as packageName } from "meteor/okgrow:accounts-ui-react"; 6 | 7 | // Write your tests here! 8 | // Here is an example. 9 | Tinytest.add('accounts-ui-react - example', function (test) { 10 | test.equal(packageName, "accounts-ui-react"); 11 | }); 12 | -------------------------------------------------------------------------------- /accounts-ui-react.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved */ 2 | import BlazeToReact from 'meteor/thereactivestack:blazetoreact'; 3 | import React from 'react'; 4 | import { Session } from 'meteor/session'; 5 | import classNames from 'classnames'; 6 | import composeWithTracker from './composeWithTracker'; 7 | 8 | const composer = (props, onData) => { 9 | const { state, visible, hideLinks } = props; 10 | 11 | // Generate classnames that identify the props and the flow 12 | let className = ''; 13 | className = classNames({ 14 | 'accounts-ui-react': true, 15 | visible, 16 | hideLinks, 17 | changePassword: Session.get('Meteor.loginButtons.inChangePasswordFlow'), 18 | }); 19 | 20 | // If visible is set, keep the Session value as true 21 | if (visible && !Session.get('Meteor.loginButtons.dropdownVisible')) { 22 | Session.set('Meteor.loginButtons.dropdownVisible', true); 23 | } 24 | 25 | // Set a specific state based on props 26 | if (state === 'signUp') Session.set('Meteor.loginButtons.inSignupFlow', true); 27 | if (state === 'forgotPassword') Session.set('Meteor.loginButtons.inForgotPasswordFlow', true); 28 | 29 | onData(null, { className }); 30 | }; 31 | 32 | const LoginButtonsComponent = (props) => { 33 | const { className } = props; 34 | 35 | const BlazeLoginButtons = BlazeToReact('loginButtons'); 36 | return ( 37 |
38 | 39 |
40 | ); 41 | }; 42 | 43 | LoginButtonsComponent.propTypes = { 44 | className: React.PropTypes.string, 45 | }; 46 | 47 | export const LoginButtons = composeWithTracker(composer)(LoginButtonsComponent); 48 | -------------------------------------------------------------------------------- /composeWithTracker.js: -------------------------------------------------------------------------------- 1 | import { Tracker } from 'meteor/tracker'; 2 | import { compose } from 'react-komposer'; 3 | 4 | const getTrackerLoader = reactiveMapper => ( 5 | (props, onData, env) => { 6 | let trackerCleanup = null; 7 | const handler = Tracker.nonreactive(() => 8 | Tracker.autorun(() => { 9 | // assign the custom clean-up function. 10 | trackerCleanup = reactiveMapper(props, onData, env); 11 | }) 12 | ); 13 | 14 | return () => { 15 | if (typeof trackerCleanup === 'function') trackerCleanup(); 16 | return handler.stop(); 17 | }; 18 | } 19 | ); 20 | 21 | const composeWithTracker = data => ( 22 | compose(getTrackerLoader(data)) 23 | ); 24 | 25 | export default composeWithTracker; 26 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | Package.describe({ 3 | name: 'okgrow:accounts-ui-react', 4 | version: '0.8.0', 5 | // Brief, one-line summary of the package. 6 | summary: 'Accounts-ui wrapped in React.', 7 | // URL to the Git repository containing the source code for this package. 8 | git: 'https://github.com/okgrow/accounts-ui-react', 9 | // By default, Meteor will default to using README.md for documentation. 10 | // To avoid submitting documentation, set this field to null. 11 | documentation: 'README.md', 12 | }); 13 | 14 | Package.onUse(function (api) { 15 | api.versionsFrom('1.3'); 16 | api.use('ecmascript'); 17 | api.use('session'); 18 | api.use('blaze-html-templates'); 19 | api.imply('blaze-html-templates'); 20 | api.use('accounts-ui'); 21 | api.use('thereactivestack:blazetoreact@1.0.2'); 22 | api.addFiles('style.css'); 23 | api.mainModule('accounts-ui-react.js'); 24 | }); 25 | 26 | Package.onTest(function (api) { 27 | api.use('ecmascript'); 28 | api.use('tinytest'); 29 | api.use('okgrow:accounts-ui-react'); 30 | api.mainModule('accounts-ui-react-tests.js'); 31 | }); 32 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .accounts-dialog { 2 | border: 0; 3 | -webkit-box-shadow: none; 4 | box-shadow: none; 5 | } 6 | 7 | #login-dropdown-list { 8 | z-index: 1; 9 | } 10 | 11 | .accounts-dialog { 12 | padding: 15px; 13 | 14 | border: 1px solid #f1f1f1; 15 | border-radius: 2px; 16 | } 17 | 18 | .accounts-dialog .accounts-close { 19 | top: 0; 20 | right: 0; 21 | 22 | padding: 5px 10px 23 | } 24 | 25 | #login-buttons a, 26 | .accounts-dialog a { 27 | text-decoration: none; 28 | 29 | color: #666; 30 | 31 | font-family: sans-serif; 32 | font-size: 12px; 33 | } 34 | 35 | #login-buttons .login-button, 36 | .accounts-dialog .login-button { 37 | padding: 8px; 38 | 39 | border: 0; 40 | border-radius: 2px; 41 | background: #333; 42 | } 43 | #login-buttons .login-button:hover, 44 | .accounts-dialog .login-button:hover, 45 | #login-buttons .login-button:active, 46 | .accounts-dialog .login-button:active { 47 | background: #666; 48 | } 49 | 50 | #login-buttons input[type=text], 51 | .accounts-dialog input[type=text], 52 | #login-buttons input[type=email], 53 | .accounts-dialog input[type=email], 54 | #login-buttons input[type=password], 55 | .accounts-dialog input[type=password] { 56 | border-radius: 2px; 57 | } 58 | 59 | #login-buttons .login-image { 60 | top: 9px; 61 | left: 9px; 62 | } 63 | 64 | 65 | .visible .login-link-text, 66 | .visible .login-close-text { 67 | display: none; 68 | } 69 | 70 | /* HACK: Hide the close text and replace with cancel */ 71 | .changePassword #login-buttons .login-close-text { 72 | display: block; 73 | float: right; 74 | 75 | text-indent: -9999px; 76 | 77 | line-height: 0; /* Collapse the original line */ 78 | } 79 | 80 | .changePassword .login-close-text:after { 81 | display: block; 82 | 83 | content: 'Cancel'; 84 | text-indent: 0; 85 | 86 | line-height: initial; /* New content takes up original line height */ 87 | } 88 | 89 | .hideLinks .additional-link-container { 90 | display: none; 91 | } --------------------------------------------------------------------------------