├── .babelrc
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── README.md
├── build
├── webpack.config.js
└── webpack
│ ├── base.js
│ ├── development.js
│ └── production.js
├── config
└── index.js
├── development
├── App.js
├── client.js
├── containers
│ └── DevTools.js
├── index.less
├── largetext.js
├── reducer.js
└── store.js
├── package.json
└── src
├── Modal.js
├── ReduxModal.js
├── emitter.js
├── index.js
├── less
└── index.less
├── redux.js
└── utils.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "syntax-class-properties",
4 | "transform-class-properties",
5 | "transform-decorators-legacy",
6 | "transform-es2015-arrow-functions",
7 | "transform-es2015-block-scoping",
8 | ["transform-es2015-classes", {"loose": true}],
9 | "transform-proto-to-assign"
10 | ],
11 | "presets": ["stage-0", "react", "es2015"]
12 | }
13 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | lib
2 | node_modules
3 | demo
4 | .DS_Store
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "env": {
4 | "browser": true,
5 | "node": true
6 | },
7 | "ecmaFeatures": {
8 | "jsx": true
9 | },
10 | "plugins": [
11 | "react"
12 | ],
13 | "rules": {
14 | "comma-dangle": [2, "never"],
15 | "no-cond-assign": 2,
16 | "no-constant-condition": 2,
17 | "no-control-regex": 2,
18 | "no-debugger": 2,
19 | "no-dupe-keys": 2,
20 | "no-empty": 2,
21 | "no-empty-character-class": 2,
22 | "no-ex-assign": 2,
23 | "no-extra-boolean-cast": 2,
24 | "no-extra-parens": 0,
25 | "no-extra-semi": 2,
26 | "no-func-assign": 2,
27 | "no-inner-declarations": 2,
28 | "no-invalid-regexp": 2,
29 | "no-irregular-whitespace": 2,
30 | "no-negated-in-lhs": 2,
31 | "no-obj-calls": 2,
32 | "no-regex-spaces": 2,
33 | "no-reserved-keys": 0,
34 | "no-sparse-arrays": 2,
35 | "no-unreachable": 2,
36 | "strict": [2, "global"],
37 | "no-catch-shadow": 2,
38 | "no-delete-var": 2,
39 | "no-label-var": 2,
40 | "no-shadow": 2,
41 | "no-shadow-restricted-names": 2,
42 | "no-undef": 2,
43 | "no-undef-init": 2,
44 | "no-undefined": 2,
45 | "no-unused-vars": 2,
46 | "no-use-before-define": 2,
47 | "indent": [2, 2, {
48 | "SwitchCase": 1
49 | }],
50 | "brace-style": 2,
51 | "camelcase": 0,
52 | "comma-spacing": 2,
53 | "comma-style": 2,
54 | "consistent-this": 0,
55 | "eol-last": 2,
56 | "func-names": 0,
57 | "func-style": 0,
58 | "key-spacing": [2, {
59 | "beforeColon": false,
60 | "afterColon": true
61 | }],
62 | "max-nested-callbacks": 0,
63 | "new-cap": 2,
64 | "new-parens": 2,
65 | "no-array-constructor": 2,
66 | "no-inline-comments": 0,
67 | "no-lonely-if": 2,
68 | "no-mixed-spaces-and-tabs": 2,
69 | "no-nested-ternary": 2,
70 | "no-new-object": 2,
71 | "semi-spacing": [2, {
72 | "before": false,
73 | "after": true
74 | }],
75 | "no-spaced-func": 2,
76 | "no-ternary": 0,
77 | "no-trailing-spaces": 2,
78 | "no-multiple-empty-lines": 2,
79 | "no-underscore-dangle": 0,
80 | "one-var": 0,
81 | "operator-assignment": [2, "always"],
82 | "padded-blocks": 0,
83 | "quotes": [2, "single"],
84 | "quote-props": [2, "as-needed"],
85 | "semi": [2, "always"],
86 | "sort-vars": [2, {"ignoreCase": true}],
87 | "space-after-keywords": 2,
88 | "space-before-blocks": 2,
89 | "object-curly-spacing": [2, "never"],
90 | "array-bracket-spacing": [2, "never"],
91 | "space-in-parens": 2,
92 | "space-infix-ops": 2,
93 | "space-return-throw-case": 2,
94 | "space-unary-ops": 2,
95 | "spaced-comment": 2,
96 | "wrap-regex": 0,
97 | "use-isnan": 2,
98 | "valid-jsdoc": 0,
99 | "valid-typeof": 2,
100 | "react/display-name": 1,
101 | "react/jsx-no-undef": 1,
102 | "react/jsx-uses-react": 1,
103 | "react/jsx-uses-vars": 1
104 | }
105 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | 0.*
4 | 1.*
5 | lib
6 | fonts/
7 | dist
8 | typings/
9 | tsconfig.json
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .*.swp
2 | ._*
3 | .DS_Store
4 | .git
5 | .hg
6 | .npmrc
7 | .lock-wscript
8 | .svn
9 | .wafpickle-*
10 | config.gypi
11 | CVS
12 | npm-debug.log
13 | src
14 | CHANGELOG.md
15 | build/
16 | config/
17 | node_modules
18 | .babelrc
19 | .eslintrc
20 | .tsconfig.json
21 | .gitignore
22 | .eslintigore
23 | dist/
24 | typings/
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoddox/react-redux-modal/d0301457df2c31e0476935f8511c0869760a1180/CHANGELOG.md
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NOT MAINTAINED
2 |
3 | ##`react-redux-modal` [demo](http://diegoddox.github.io/react-redux-modal/)
4 |
5 | ## Implementation Guide
6 |
7 | ##### 1. Installation
8 |
9 | `npm install --save react-redux-modal`
10 |
11 | ##### 2. Add the `react-redux-modal` css link to your app
12 | ```
13 |
14 | ```
15 | ##### 3. The third thing you need to do is to add the `react-redux-modal` `reducer` to Redux.
16 |
17 | ```
18 | import {createStore, combineReducers} from 'redux'
19 | import {reducer as modalReducer} from 'react-redux-modal'
20 | const reducers = {
21 | // ... other reducers ...
22 | modals: modalReducer // <- Mounted at modals.
23 | }
24 | const reducer = combineReducers(reducers)
25 | const store = createStore(reducer)
26 | ```
27 |
28 | ##### NOTE: The default mount point for `react-redux-modal` is `modals`.
29 |
30 | ##### 4. Add the `react-redux-modal` React component to the root of your app
31 | ```
32 | import {Provider} from 'react-redux'
33 | import ReduxModal from 'react-redux-modal'
34 |
35 |
36 |
37 | ... other things like router ...
38 |
39 |
40 |
41 | ```
42 |
43 | ##### 5. Add the `react-redux-modal` `modal` emitter
44 | The `modal` method use [eventemitter3](https://github.com/primus/eventemitter3) to dispatch the actions
45 |
46 | ```
47 | import React, {Component} from 'react'
48 | import {modal} from 'react-redux-modal' // The modal emitter
49 | ```
50 |
51 | Create a `component` that will be injected in the modal
52 | ```
53 | class myModalComopnent extends Component {
54 | constructor(props) {
55 | super(props);
56 | console.log('## MODAL DATA AND PROPS:', this.props);
57 | }
58 |
59 | removeThisModal() {
60 | this.props.removeModal();
61 | }
62 |
63 | render() {
64 | return (
65 |
66 |
this is my modal
67 |
72 |
73 | );
74 | }
75 | }
76 | ```
77 | ```
78 | export class YourComponent extends Component {
79 | constructor(props) {
80 | super(props);
81 | }
82 |
83 | addModal() {
84 | modal.add(myModalComopnent, {
85 | title: 'This is my modal',
86 | size: 'medium', // large, medium or small,
87 | closeOnOutsideClick: false // (optional) Switch to true if you want to close the modal by clicking outside of it,
88 | hideTitleBar: false // (optional) Switch to true if do not want the default title bar and close button,
89 | hideCloseButton: false // (optional) if you don't wanna show the top right close button
90 | //.. all what you put in here you will get access in the modal props ;)
91 | });
92 | }
93 |
94 | render() {
95 | return ;
96 | }
97 | }
98 | ```
99 |
100 | The `modal` `add` method takes two arguments, first a `react` `component` and a `object` that will specify the modal `title`, `size` and `data`
101 |
102 | # Run a local demo
103 | ```
104 | git clone https://github.com/diegoddox/react-redux-modal.git
105 | cd react-redux-modal
106 | npm install
107 | npm start
108 | ```
109 | open your browser at `http://localhost:3001`
110 |
111 | # TODO
112 | create test.
--------------------------------------------------------------------------------
/build/webpack.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = require('./webpack/' + require('../config').env);
4 |
--------------------------------------------------------------------------------
/build/webpack/base.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var webpack = require('webpack');
4 | var path = require('path');
5 | var HtmlWebpackPlugin = require('html-webpack-plugin');
6 | var config = require('../../config');
7 |
8 | // const baseSrcPath = path.join(config.path_base, '/' + config.dir_client);
9 |
10 | module.exports = {
11 | target: 'web',
12 | entry: {
13 | app: path.join(config.path_base, '/' + config.dir_client + '/client.js')
14 | },
15 | output: {
16 | path: path.join(config.path_base + '/dist'),
17 | filename: 'bundle.js',
18 | publicPath: ''
19 | },
20 | module: {
21 | preLoaders: [
22 | {
23 | test: /\.jsx?$/,
24 | loaders: ['eslint'],
25 | exclude: /node_modules/
26 | }
27 | ],
28 | loaders: [
29 | {
30 | test: /\.js?$/,
31 | exclude: /node_modules/,
32 | loaders: ['react-hot', 'babel']
33 | }, {
34 | test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
35 | exclude: /node_modules/,
36 | loader: 'url-loader'
37 | }, {
38 | test: /\.less$/,
39 | exclude: /node_modules/,
40 | loader: 'style!css!less'
41 | }, {
42 | test: /\.css$/,
43 | loader: 'style-loader!css-loader'
44 | }, {
45 | test: /\.jpg$/,
46 | exclude: /node_modules/,
47 | loader: 'file-loader'
48 | }
49 | ]
50 | },
51 | plugins: [
52 | new webpack.DefinePlugin({
53 | 'process.env': {
54 | NODE_ENV: '"' + process.env.NODE_ENV + '"'
55 | }
56 | }),
57 | new HtmlWebpackPlugin({
58 | templateContent: ''
59 | + ''
60 | + ''
61 | + ' '
62 | + ' '
63 | + ' React Redux Modal'
64 | + ' '
65 | + ' '
66 | + ' '
67 | + ' '
68 | + ' '
69 | + ' '
70 | + ' '
71 | + '',
72 | inject: 'body'
73 | })
74 | ]
75 | };
76 |
--------------------------------------------------------------------------------
/build/webpack/development.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var config = require('../../config');
5 | var baseConfig = require('./base');
6 |
7 | baseConfig.entry.app = [
8 | 'webpack-dev-server/client?http://localhost:' + config.server_port,
9 | 'webpack/hot/only-dev-server',
10 | config.path_base + '/' + config.dir_client + '/client.js'
11 | ];
12 |
13 | baseConfig.devtool = 'inline-source-map';
14 |
15 | baseConfig.devServer = {
16 | headers: {
17 | 'Access-Control-Allow-Origin': '*',
18 | 'Access-Control-Allow-Credentials': true,
19 | 'Access-Control-Max-Age': 1
20 | },
21 | contentBase: path.join(config.path_base, '/' + config.dir_client),
22 | noInfo: false,
23 | port: config.server_port,
24 | hot: true,
25 | stats: {
26 | colors: true
27 | },
28 | historyApiFallback: true
29 | };
30 |
31 | module.exports = baseConfig;
32 |
--------------------------------------------------------------------------------
/build/webpack/production.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var webpack = require('webpack');
4 | var webpackBase = require('./base');
5 |
6 | webpackBase.plugins.push(
7 | new webpack.optimize.UglifyJsPlugin({
8 | compress: {
9 | warnings: false
10 | }
11 | })
12 | );
13 |
14 | module.exports = webpackBase;
15 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 |
5 | module.exports = {
6 | env: process.env.NODE_ENV,
7 | path_base: path.resolve(__dirname, '../'),
8 | dir_client: 'development',
9 | server_port: process.env.NODE_PORT || 3000
10 | };
11 |
--------------------------------------------------------------------------------
/development/App.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import './index.less';
4 | import './../src/less/index.less';
5 | import React, {Component, PropTypes} from 'react';
6 | import {Provider} from 'react-redux';
7 | import ReduxModal, {modal} from './../src/';
8 | import DevTools from './containers/DevTools';
9 | import largeText from './largetext';
10 | import config from './../config';
11 |
12 | import loremIpsum from 'lorem-ipsum';
13 |
14 | class myLargeModalComponent extends Component {
15 | static displayName = 'MySUperModal';
16 |
17 | constructor(props) {
18 | super(props);
19 | console.log('##myLargeModalComponent props##', this.props);
20 | }
21 |
22 | render() {
23 | return (
24 |
25 |
{loremIpsum({count: 1})}
26 |
29 |
30 | );
31 | }
32 | }
33 |
34 | class modalComponentWithButton extends Component {
35 | static displayName = 'MySUperModal';
36 |
37 | render() {
38 | return (
39 |
40 |
{loremIpsum({count: 1})}
41 |
44 |
45 | );
46 | }
47 | }
48 |
49 | class modalComponent extends Component {
50 | static displayName = 'MySUperModal';
51 |
52 | render() {
53 | return {largeText}
;
54 | }
55 | }
56 |
57 | class myModalComponent extends Component {
58 | static displayName = 'MySUperModal';
59 |
60 | render() {
61 | return :D {largeText}
;
62 | }
63 | }
64 |
65 | export default class App extends Component {
66 | static displayName = 'ReduxModalDev';
67 |
68 | static propTypes = {
69 | store: PropTypes.object.isRequired
70 | };
71 |
72 | constructor(props) {
73 | super(props);
74 | this.renderDev = this.renderDev.bind(this);
75 | }
76 |
77 | addModalLarge() {
78 | modal.add(myLargeModalComponent, {
79 | title: 'This one there is no close botton.',
80 | size: 'large',
81 | hideCloseButton: true
82 | });
83 | }
84 |
85 | addModalMedium() {
86 | modal.add(myModalComponent, {
87 | title: 'Time to get some food',
88 | size: 'medium'
89 | });
90 | }
91 |
92 | addModalSmall() {
93 | modal.add(modalComponent, {
94 | title: 'You got it',
95 | size: 'small'
96 | });
97 | }
98 |
99 | addOutsideClickCloseModal() {
100 | modal.add(modalComponent, {
101 | title: 'You got it',
102 | size: 'small',
103 | closeOnOutsideClick: true
104 | });
105 | }
106 | addModalWithoutTitle() {
107 | modal.add(modalComponentWithButton, {
108 | title: null,
109 | hideTitleBar: true,
110 | size: 'small'
111 | });
112 | }
113 |
114 | renderDev() {
115 | if (config.env !== 'production') {
116 | return ;
117 | }
118 | }
119 |
120 | render() {
121 | return (
122 |
123 |
124 |
125 |
128 |
131 |
132 |
135 |
138 |
141 |
142 |
143 | {this.renderDev()}
144 |
145 |
146 | );
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/development/client.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | import React from 'react';
3 | import {render} from 'react-dom';
4 | import createStore from './store';
5 | import App from './App';
6 |
7 | const store = createStore();
8 | const target = document.getElementById('app');
9 |
10 | render(, target);
11 |
--------------------------------------------------------------------------------
/development/containers/DevTools.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import {createDevTools} from 'redux-devtools';
5 | import LogMonitor from 'redux-devtools-log-monitor';
6 | import DockMonitor from 'redux-devtools-dock-monitor';
7 |
8 | export default createDevTools(
9 |
12 |
13 |
14 | );
15 |
--------------------------------------------------------------------------------
/development/index.less:
--------------------------------------------------------------------------------
1 | .wrapper {
2 | width: 70%;
3 | margin: 100px auto;
4 |
5 | .content {
6 | width: 100%;
7 | text-align: center;
8 | button {
9 | margin: 20px;
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/development/largetext.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | const text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vitae aliquam lacus. Donec a egestas mauris. Quisque et luctus nisi, vel placerat est. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus tincidunt ullamcorper eros, nec tincidunt sapien ultrices in. Vestibulum sed blandit mi. Pellentesque augue tellus, bibendum id nulla vitae, consequat bibendum purus. Cras varius tellus a convallis finibus. Praesent sem risus, tristique at suscipit a, mattis id orci. Vestibulum interdum ligula sit amet ex lobortis, ac maximus ipsum vestibulum. Donec suscipit viverra nisl placerat imperdiet. Aliquam pulvinar ut orci id pharetra. Quisque tristique augue a dui efficitur ornare. Aenean tincidunt eget sem ut pulvinar. Quisque at ligula rhoncus, congue justo et, sagittis ex. Pellentesque sapien magna, porta ut pulvinar a, venenatis at turpis.Aenean ut mi a odio hendrerit laoreet. Morbi convallis, massa et tristique tempus, risus eros rhoncus turpis, vel accumsan velit purus nec urna. Curabitur varius molestie orci nec cursus. Curabitur pretium erat feugiat tortor imperdiet hendrerit. Curabitur condimentum cursus dui sit amet vestibulum. Nunc pretium iaculis est vel dignissim. Fusce et enim tempor, laoreet lacus in, hendrerit lectus. Sed sagittis sollicitudin condimentum. Curabitur fermentum dui at congue vehicula. Fusce vel risus sed lectus egestas ullamcorper. Morbi vel mauris erat.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vitae aliquam lacus. Donec a egestas mauris. Quisque et luctus nisi, vel placerat est. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus tincidunt ullamcorper eros, nec tincidunt sapien ultrices in. Vestibulum sed blandit mi. Pellentesque augue tellus, bibendum id nulla vitae, consequat bibendum purus. Cras varius tellus a convallis finibus. Praesent sem risus, tristique at suscipit a, mattis id orci. Vestibulum interdum ligula sit amet ex lobortis, ac maximus ipsum vestibulum. Donec suscipit viverra nisl placerat imperdiet. Aliquam pulvinar ut orci id pharetra. Quisque tristique augue a dui efficitur ornare. Aenean tincidunt eget sem ut pulvinar. Quisque at ligula rhoncus, congue justo et, sagittis ex. Pellentesque sapien magna, porta ut pulvinar a, venenatis at turpis.Aenean ut mi a odio hendrerit laoreet. Morbi convallis, massa et tristique tempus, risus eros rhoncus turpis, vel accumsan velit purus nec urna. Curabitur varius molestie orci nec cursus. Curabitur pretium erat feugiat tortor imperdiet hendrerit. Curabitur condimentum cursus dui sit amet vestibulum. Nunc pretium iaculis est vel dignissim. Fusce et enim tempor, laoreet lacus in, hendrerit lectus. Sed sagittis sollicitudin condimentum. Curabitur fermentum dui at congue vehicula. Fusce vel risus sed lectus egestas ullamcorper. Morbi vel mauris erat';
5 |
6 | export default text;
7 |
--------------------------------------------------------------------------------
/development/reducer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | import {combineReducers} from 'redux';
3 | import {reducer as modalReducer} from './../src/';
4 | export default combineReducers({
5 | modals: modalReducer
6 | });
7 |
--------------------------------------------------------------------------------
/development/store.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react'; // eslint-disable-line no-unused-vars
4 | import {createStore, compose} from 'redux';
5 | import DevTools from './containers/DevTools';
6 | import rootReducers from './reducer';
7 |
8 | export default function configStore(initialState) {
9 | let createStoreWithMiddleware;
10 | createStoreWithMiddleware = compose(DevTools.instrument());
11 |
12 | const store = createStoreWithMiddleware(createStore)(rootReducers, initialState);
13 |
14 | // This we only use in development.
15 | if (module.hot) {
16 | module.hot.accept('./reducer', () => {
17 | const nextRootReducers = require('./reducer');
18 | store.replaceReducer(nextRootReducers);
19 | });
20 | }
21 |
22 | return store;
23 | }
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-redux-modal",
3 | "version": "0.5.2",
4 | "description": "react-redux-modal is a React modal implemented with Redux",
5 | "main": "lib/index.js",
6 | "jsnext:main": "./src/index.js",
7 | "scripts": {
8 | "start": "better-npm-run dev-server",
9 | "build:w": "better-npm-run build:w",
10 | "build": "better-npm-run build && npm run less && npm run less:m",
11 | "less": "node_modules/.bin/lessc src/less/index.less --autoprefix=\"last 2 versions\" lib/css/react-redux-modal.css",
12 | "less:m": "node_modules/.bin/lessc src/less/index.less --autoprefix=\"last 2 versions\" --clean-css lib/css/react-redux-modal.min.css",
13 | "clean": "better-npm-run clean",
14 | "lint": "better-npm-run lint",
15 | "build_app": "concurrent --kill-others & npm run clean & npm run lint & npm run build & npm run less & npm run less:m",
16 | "buildc": "better-npm-run build_client"
17 | },
18 | "eslintConfig": {
19 | "root": true
20 | },
21 | "betterScripts": {
22 | "dev-server": {
23 | "command": "./node_modules/.bin/webpack-dev-server --hot --inline --config build/webpack.config.js",
24 | "env": {
25 | "NODE_ENV": "development",
26 | "NODE_PORT": 3001
27 | }
28 | },
29 | "build_client": {
30 | "command": "./node_modules/.bin/webpack --progress --config build/webpack.config.js",
31 | "env": {
32 | "NODE_ENV": "production"
33 | }
34 | },
35 | "build": {
36 | "command": "node_modules/.bin/babel src/ --out-dir lib"
37 | },
38 | "build:w": {
39 | "command": "node_modules/.bin/babel -w src/ --out-dir lib"
40 | },
41 | "lint": {
42 | "command": "node_modules/.bin/eslint . --ext .js --ext .jsx || true"
43 | },
44 | "clean": {
45 | "command": "node_modules/.bin/rimraf dist lib"
46 | }
47 | },
48 | "author": "Diego Oliveira",
49 | "license": "MIT",
50 | "repository": {
51 | "type": "git",
52 | "url": "https://github.com/diegoddox/react-redux-modal"
53 | },
54 | "bugs": {
55 | "url": "https://github.com/diegoddox/react-redux-modal/issues"
56 | },
57 | "files": [
58 | "lib/",
59 | "src/",
60 | "CHANGELOG.md",
61 | "README.md"
62 | ],
63 | "keywords": [
64 | "React.js",
65 | "React",
66 | "Redux",
67 | "react",
68 | "redux modal",
69 | "react-redux-modal",
70 | "react-component",
71 | "modal",
72 | "react modal",
73 | "react redux modal",
74 | "react modal redux"
75 | ],
76 | "devDependencies": {
77 | "babel-cli": "^6.6.5",
78 | "babel-core": "^6.2.1",
79 | "babel-eslint": "^4.1.6",
80 | "babel-loader": "^6.2.0",
81 | "babel-plugin-syntax-class-properties": "^6.1.18",
82 | "babel-plugin-transform-class-properties": "^6.2.2",
83 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
84 | "babel-plugin-transform-es2015-arrow-functions": "^6.1.18",
85 | "babel-plugin-transform-es2015-block-scoping": "^6.1.18",
86 | "babel-plugin-transform-proto-to-assign": "^6.6.5",
87 | "babel-preset-es2015": "^6.1.18",
88 | "babel-preset-react": "^6.1.18",
89 | "babel-preset-stage-0": "^6.1.18",
90 | "better-npm-run": "0.0.4",
91 | "chance": "^0.8.0",
92 | "concurrently": "^1.0.0",
93 | "core-js": "^2.0.2",
94 | "css-loader": "^0.23.1",
95 | "eslint": "^1.10.1",
96 | "eslint-loader": "^1.1.1",
97 | "eslint-plugin-react": "^3.16.1",
98 | "html-webpack-plugin": "^1.6.2",
99 | "jasmine": "^2.3.2",
100 | "jshint": "^2.9.1-rc1",
101 | "jshint-loader": "^0.8.3",
102 | "karma": "^0.13.15",
103 | "karma-jasmine": "^0.3.6",
104 | "karma-phantomjs-launcher": "^0.2.1",
105 | "karma-webpack": "^1.7.0",
106 | "less": "^2.5.3",
107 | "less-loader": "^2.2.1",
108 | "less-plugin-autoprefix": "^1.5.1",
109 | "less-plugin-clean-css": "^1.5.1",
110 | "lorem-ipsum": "^1.0.3",
111 | "phantomjs": "^1.9.19",
112 | "phantomjs-polyfill": "0.0.1",
113 | "react": "^0.14.7",
114 | "react-dom": "^0.14.7",
115 | "react-hot-loader": "^1.3.0",
116 | "react-redux": "^4.4.0",
117 | "redux": "^3.3.1",
118 | "redux-devtools": "^3.1.1",
119 | "redux-devtools-dock-monitor": "^1.1.0",
120 | "redux-devtools-log-monitor": "^1.0.5",
121 | "redux-logger": "^2.0.4",
122 | "rimraf": "^2.4.4",
123 | "style-loader": "^0.13.0",
124 | "url-loader": "^0.5.7",
125 | "webpack": "^1.12.4",
126 | "webpack-dev-server": "^1.14.0"
127 | },
128 | "dependencies": {
129 | "classnames": "^2.2.3",
130 | "eventemitter3": "^1.1.1",
131 | "uuid": "^2.0.1"
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/Modal.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, {Component, PropTypes} from 'react';
4 | import classnames from 'classnames';
5 |
6 | class Modal extends Component {
7 | constructor(props) {
8 | super(props);
9 | }
10 |
11 | handleOnOutsideClick(e) {
12 | if (this.props.options.closeOnOutsideClick && !this.isChildOf(e.target, this.refs.modalContent) || false) {
13 | this.props.removeModal(this.props.id);
14 | }
15 | }
16 |
17 | isChildOf(child, parent) {
18 | if (child.parentNode === parent) {
19 | return true;
20 | } else if (child.parentNode === null) {
21 | return false;
22 | } else {
23 | return this.isChildOf(child.parentNode, parent);
24 | }
25 | }
26 |
27 | render() {
28 | return (
29 |
30 |
31 |
32 |
33 | {this.props.options.hideTitleBar ? null :
34 |
35 |
{this.props.options.title}
36 |
37 | {this.props.options.hideCloseButton ? null :
38 |
42 | }
43 |
44 |
45 | }
46 |
47 |
48 | this.props.removeModal(this.props.id)}/>
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | );
57 | }
58 | }
59 |
60 | Modal.displayName = 'rrModal';
61 |
62 | Modal.propTypes = {
63 | id: PropTypes.string,
64 | index: PropTypes.number,
65 | removeModal: PropTypes.func.isRequired,
66 | options: PropTypes.shape({
67 | size: PropTypes.string,
68 | title: PropTypes.string,
69 | hideCloseButton: PropTypes.bool,
70 | hideTitleBar: PropTypes.bool,
71 | closeOnOutsideClick: PropTypes.bool
72 | }).isRequired
73 | };
74 |
75 | export default Modal;
76 |
--------------------------------------------------------------------------------
/src/ReduxModal.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | import React, {Component, PropTypes} from 'react';
3 | import {connect} from 'react-redux';
4 | import {EE} from './emitter';
5 | import * as actions from './redux';
6 | import Modal from './Modal';
7 |
8 | @connect(state => ({modals: state.modals.modals}), actions)
9 | class ReduxModal extends Component {
10 | constructor(props) {
11 | super(props);
12 | }
13 |
14 | componentDidMount() {
15 | EE.on('add/modal', obj => this.props.addModal(obj));
16 | EE.on('clear/all', this.props.clearAll);
17 | }
18 |
19 | componentWillUnmount() {
20 | EE.off('add/modal');
21 | EE.off('clear/all');
22 | }
23 |
24 | render() {
25 | return (
26 |
27 |
28 | {this.props.modals.map((modal, i) => {
29 | return (
30 |
35 | );
36 | })}
37 |
38 |
39 | );
40 | }
41 | }
42 |
43 | ReduxModal.displayName = 'ReduxModal';
44 |
45 | ReduxModal.propTypes = {
46 | modals: PropTypes.array
47 | };
48 |
49 | export default ReduxModal;
50 |
--------------------------------------------------------------------------------
/src/emitter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | import EventEmitter from 'eventemitter3';
3 | const emitter = new EventEmitter();
4 |
5 | export const EE = emitter;
6 | export const modalEmitter = {
7 | add: (component, options) => emitter.emit('add/modal', {component, options}),
8 | remove: id => emitter.emit('remove/modal', id),
9 | clear: () => emitter.emit('clear/all')
10 | };
11 |
12 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import ReduxModal from './ReduxModal';
4 | import reduxDuck from './redux';
5 | import {modalEmitter} from './emitter';
6 | import * as modalActions from './redux';
7 |
8 | export default ReduxModal;
9 | export const reducer = reduxDuck;
10 | export const actions = modalActions;
11 | export const modal = modalEmitter;
12 |
--------------------------------------------------------------------------------
/src/less/index.less:
--------------------------------------------------------------------------------
1 | .react-redux-modal {
2 | font-family: "Arial";
3 | box-sizing: content-box;
4 |
5 | button {
6 | &:focus {
7 | outline: 0;
8 | }
9 | }
10 |
11 | .rrm-holder {
12 | width: 100%;
13 | height: 100%;
14 | position: fixed;
15 | top: 0;
16 | left: 0;
17 |
18 | .scroll {
19 | width: 100%;
20 | height: 100%;
21 | position: relative;
22 | overflow-y: auto;
23 | z-index: 1;
24 |
25 | .rrm-content {
26 | z-index: 1;
27 | background-color: #fcfcfc;
28 | position: relative;
29 | border-radius: 4px;
30 | box-shadow: 0px 0px 20px #333;
31 | margin: 80px auto;
32 | overflow: hidden;
33 |
34 | &.m-small {
35 | width: 300px;
36 |
37 | .rrm-title {
38 | h2 {
39 | width: 140px;
40 | }
41 | }
42 | }
43 |
44 | &.m-medium {
45 | width: 500px;
46 | .rrm-title {
47 | h2 {
48 | width: 340px;
49 | }
50 | }
51 | }
52 |
53 | &.m-large {
54 | width: 800px;
55 | .rrm-title {
56 | h2 {
57 | width: 640px;
58 | }
59 | }
60 | }
61 |
62 | .rrm-title {
63 | width: 100%;
64 | height: 60px;
65 | border-bottom: 1px solid #dbdbdb;
66 | position: relative;
67 | color: #444;
68 | box-sizing: content-box;
69 |
70 | h2 {
71 | height: 60px;
72 | padding: 0px 20px;
73 | white-space: nowrap;
74 | overflow: hidden;
75 | text-overflow: ellipsis;
76 | font-size: 1.4em;
77 | margin: 0;
78 | line-height: 60px;
79 | float: left;
80 | box-sizing: content-box;
81 | }
82 |
83 | .rr-title-actions {
84 | width: 120px;
85 | height: 100%;
86 | text-align: center;
87 | float: left;
88 |
89 | button {
90 | width: 40px;
91 | height: 40px;
92 | margin: 10px 8px;
93 | line-height: 40px;
94 | position: relative;
95 | border: 1px solid transparent;
96 | float: right;
97 | background-color: transparent;
98 | text-align: center;
99 | padding: 0;
100 | color: #666;
101 | font-size: 1.2em;
102 | border-radius: 50%;
103 |
104 | &:hover {
105 | color: #4186bf;
106 | cursor: pointer;
107 | background-color: rgba(65, 134, 191, .1);
108 | border-color: rgba(65, 134, 191, .2);
109 | box-shadow: 2px 2px 3px #f0f0f0;
110 | }
111 | }
112 | }
113 | }
114 |
115 | .rrm-body {
116 | width: 100%;
117 | padding: 20px;
118 | }
119 | }
120 | }
121 |
122 | .rrm-shadow {
123 | width: 100%;
124 | height: 100%;
125 | background-color: rgba(50,58,68, .8);
126 | position: absolute;
127 | top: 0;
128 | left: 0;
129 | z-index: 0;
130 | }
131 | }
132 | }
--------------------------------------------------------------------------------
/src/redux.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import uiid from 'uuid';
4 | import {createReducer} from './utils.js';
5 |
6 | export const ADD_MODAL = '@react-redux-modal.ADD_MODAL';
7 | export const REMOVE_MODAL = '@react-redux-modal.REMOVE_MODAL';
8 | export const CLEAR_ALL = '@react-redux-modal.CLEAR_ALL';
9 |
10 | const initialSate = {
11 | modals: []
12 | };
13 |
14 | export default createReducer(initialSate, {
15 | [ADD_MODAL]: (state, payload) => {
16 | return {
17 | ...state,
18 | modals: [
19 | ...state.modals,
20 | {
21 | id: uiid.v1(),
22 | ...payload
23 | }
24 | ]
25 | };
26 | },
27 | [REMOVE_MODAL]: (state, id) => {
28 | return {
29 | ...state,
30 | modals: state.modals.filter(modal => modal.id !== id)
31 | };
32 | },
33 | [CLEAR_ALL]: () => {
34 | return {
35 | modals: []
36 | };
37 | }
38 | });
39 |
40 | export function addModal(payload) {
41 | return {
42 | type: ADD_MODAL,
43 | payload: payload
44 | };
45 | }
46 |
47 | export function removeModal(id) {
48 | return {
49 | type: REMOVE_MODAL,
50 | payload: id
51 | };
52 | }
53 |
54 | export function clearAll() {
55 | return {
56 | type: CLEAR_ALL
57 | };
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | export function createReducer(initialState, fnMap) {
4 | return (state = initialState, {type, payload}) => {
5 | const handle = fnMap[type];
6 | return handle ? handle(state, payload) : state;
7 | };
8 | }
9 |
--------------------------------------------------------------------------------