Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

redal

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redal - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

.eslintrc.js

40

demo/index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Redal from './dist';
//import Redal from '../src';
//import Redal from '../dist';
import Redal from '../src';
import './index.scss';

@@ -13,15 +13,33 @@ const REDAL_REF = Symbol('redal');

}
render() {
return (
<div className='wrapper'>
<button onClick={() => this.refs[REDAL_REF].toggle(false)}> open redal </button>
<button onClick={() => this.setState({ scoped: !this.state.scoped })}> scoped: {this.state.scoped ? 'true' : 'false'}</button>
<button onClick={() => this.setState({ maskToggle: !this.state.maskToggle })}> maskToggle: {this.state.maskToggle ? 'true' : 'false'}</button>
<button onClick={() => this.refs[REDAL_REF].toggle(false)}>Open Redal</button>
<button onClick={() => this.setState({ scoped: !this.state.scoped })}>
scoped: {this.state.scoped ? 'true' : 'false'}
</button>
<button onClick={() => this.setState({ maskToggle: !this.state.maskToggle })}>
maskToggle: {this.state.maskToggle ? 'true' : 'false'}
</button>
<div className='scope'>
<Redal handleMaskClick={() => !confirm('close?')} ref={REDAL_REF} scoped={this.state.scoped} enterDuration={800} maskToggle={this.state.maskToggle} beforeEnter={() => this.setState({msg: ''})} didEnter={() => this.setState({msg: 'did enter'})} didLeave={() => this.setState({ msg: 'did leave' })}>
<h1>
some content
</h1>
<Redal.X component='h3' beforeLeave={() => confirm('confirm leave?')} > close redal </Redal.X>
<Redal
ref={REDAL_REF}
scoped={this.state.scoped}
enterTimeout={800}
handleMaskClick={() => confirm('close on mask clicked?')}
maskToggle={this.state.maskToggle}
beforeEnter={() => this.setState({msg: ''})}
didEnter={() => {
this.setState({msg: 'did enter'});
alert('did enter');
}}
didLeave={() => {
this.setState({ msg: 'did leave' });
alert('did leave');
}}
>
<div className='inner'>
<h1>some content</h1>
<Redal.X component='h3' beforeLeave={() => confirm('confirm leave?')} > close redal </Redal.X>
</div>
</Redal>

@@ -28,0 +46,0 @@ </div>

@@ -7,5 +7,2 @@ import gulp from 'gulp';

import WebpackDevServer from 'webpack-dev-server';
import {

@@ -37,3 +34,3 @@ build,

gulp.task('wp:dev', (cb) => {
let webpackDevServer = new WebpackDevServer(webpack(demo), devServerConf);
const webpackDevServer = new WebpackDevServer(webpack(demo), devServerConf);
webpackDevServer.listen(WEBPACK_PORT, WEBPACK_HOST, (err, result) => {

@@ -46,3 +43,3 @@ console.log(err || 'Listening at %s:%s', WEBPACK_HOST, WEBPACK_PORT);

gulp.task('dev', cb => {
run('clean', 'statics', 'watch', 'wp:dev');
run('statics', 'watch', 'wp:dev');
});
{
"name": "redal",
"version": "0.0.2",
"version": "0.0.3",
"description": "react modal",

@@ -29,14 +29,11 @@ "scripts": {

"autoprefixer-loader": "^3.1.0",
"babel-core": "^5.8.25",
"babel-eslint": "^4.1.3",
"babel-loader": "^5.3.2",
"babel-plugin-syntax-class-properties": "^6.1.18",
"babel-plugin-syntax-decorators": "^6.1.18",
"babel-plugin-syntax-function-bind": "^6.1.18",
"babel-plugin-syntax-object-rest-spread": "^6.1.18",
"babel-plugin-transform-object-assign": "^6.1.18",
"babel-preset-es2015": "^6.1.18",
"babel-preset-react": "^6.1.18",
"babel-preset-stage-0": "^6.1.18",
"babel-preset-stage-2": "^6.1.18",
"babel-eslint": "^6.0.4",
"babel-loader": "^6.2.4",
"babel-plugin-transform-runtime": "^6.9.0",
"babel-polyfill": "^6.9.1",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"babel-register": "^6.9.0",
"babel-runtime": "^6.9.2",
"blueimp-tmpl": "^2.5.6",

@@ -43,0 +40,0 @@ "css-loader": "^0.20.2",

@@ -6,2 +6,3 @@ #### Usage:

```js
import React, { Component } from 'react';
import Redal from 'redal';

@@ -14,2 +15,3 @@

super(props, context);
this.state = { maskToggle: false };
}

@@ -19,27 +21,27 @@ toggle(hidden) {

}
canBeClosed() {
// return `false` to stop the modal from closing
// return a `Promise` to defer the closing when resolved
// otherwise close the modal immediately
}
afterModalClosed(modalDom) {
}
render() {
return (
<div>
<Redal ref={REDAL_REF} enterDuration={800} leaveDuration={800} didLeave={::this.afterModalClosed}>
{/* click to close the modal*/}
<Redal.X> x </Redal.X>
<div className='redal-header'></div>
<div className='redal-body'></div>
<div className='redal-footer'>
{/* click to close the modal if beforeClose() !== false */}
<Redal.X beforeLeave={::this.canBeClosed}> confirm </Redal.X>
<Redal.X> cancel </Redal.X>
</div>
</Redal>
</div>
<div className='wrapper'>
<button onClick={() => this.toggle(false)}>Open Redal</button>
<button onClick={() => this.setState({ maskToggle: !this.state.maskToggle })}>
maskToggle: {this.state.maskToggle ? 'true' : 'false'}
</button>
<Redal
ref={REDAL_REF}
enterTimeout={800}
handleMaskClick={() => confirm('close on mask clicked?')}
maskToggle={this.state.maskToggle}
didEnter={() => {
alert('did enter');
}}
didLeave={() => {
alert('did leave');
}}
>
<div className='inner'>
<h1>some content</h1>
<Redal.X component='h3' beforeLeave={() => confirm('confirm leave?')}>Close redal</Redal.X>
</div>
</Redal>
</div>
);

@@ -55,12 +57,25 @@ }

<Redal
scoped // boolean, default to `false`, which will append the modal dom to body (portal pattern);
// set as `true` to leave the actually modal dom where <Redal> is used, which is useful when you don't want the modal to be full screen, in which case
// you also need to set a `transform` css property rather than `none` on any closest ancestor you want the modal to be scoped to, then the modal will be
variant // {string?}
scoped // {boolean? := `false`}
// default to append the modal dom to body (portal pattern);
// set as `true` to leave the actually modal dom where <Redal> is used,
// which is useful when you don't want the modal to be full screen, in which case
// you also need to set a `transform` css property rather than `none` on
// any closest ancestor you want the modal to be scoped to, then the modal will be
// just the full size of that ancestor
enterDuration, leaveDuration, // same as your animation-duration for css animation
enterTimeout, leaveTimeout // {number} same as your animation-duration for css animation
willEnter, didEnter, willLeave, didLeave // callback for modal lifecycles
maskToggle // boolean, default to `false`, should close the modal or not when you click on the mask
handleMaskClick // optional, (event, innerDOM), if `!handleMaskClick(e,innerDOM)` then will close, vice versa. If this function is set, will ignore `maskToggle`
hidden //
>
maskToggle // {boolean? := `false`} should close the modal or not when you click on the mask
handleMaskClick // {function?} (event, innerDOM)
// if `!handleMaskClick(e,innerDOM)` then will close, vice versa.
// If this function is set, will ignore `maskToggle`
hidden // { boolean := `false`}
>
<Redal.X> x </Redal.X>
<div className='redal-header'></div>
<div className='redal-body'></div>
<div className='redal-footer'>
<Redal.X beforeLeave={}> confirm </Redal.X>
<Redal.X> cancel </Redal.X>
</div>
</Redal>

@@ -113,3 +128,2 @@ ```

gulp dev
```
/**
* <Redal scoped={false} enterDuration leaveDuration ref='redal' willEnter={} didEnter={} willLeave={} didLeave={} maskToggle={false} handleMaskClick hidden={true}>
* <Redal
* variant // {string?}
* scoped // {boolean? := `false`}
// default to append the modal dom to body (portal pattern);
// set as `true` to leave the actually modal dom where <Redal> is used,
// which is useful when you don't want the modal to be full screen, in which case
// you also need to set a `transform` css property rather than `none` on
// any closest ancestor you want the modal to be scoped to, then the modal will be
// just the full size of that ancestor
* enterTimeout, leaveTimeout // {number} same as your animation-duration for css animation
* willEnter, didEnter, willLeave, didLeave // callback for modal lifecycles
* maskToggle // {boolean? := `false`} should close the modal or not when you click on the mask
* handleMaskClick // {function?} (event, innerDOM)
* // if `!handleMaskClick(e,innerDOM)` then will close, vice versa.
* // If this function is set, will ignore `maskToggle`
* hidden // { boolean := `false`}
* >
* <Redal.X> x </Redal.X>

@@ -24,3 +40,3 @@ * <div className='redal-header'></div>

const DEFAULT_DURATION = 0;
const DEFAULT_TIMEOUT = 0;

@@ -30,3 +46,3 @@ const STATUS_SHOWN = 1;

const WRAPPER_KEY = 'redalwrapper';
const DEFAULT_VARIANT = 'redal';

@@ -38,3 +54,3 @@ function replaceRedalX(children, replace) {

} else if (child && child.props && typeof child.props.children === 'object') {
return React.cloneElement(child, child.props, replaceRedalX(child.props.children, replace));
return React.cloneElement(child, undefined, replaceRedalX(child.props.children, replace));
}

@@ -47,13 +63,16 @@ return child;

static defaultProps = {
hidden: true
hidden: true,
variant: DEFAULT_VARIANT
};
constructor(props, context) {
const { hidden = true } = props;
super(props, context);
this.state = { hidden };
this.state = { hidden: props.hidden };
this.close = ::this.close;
this.delegateRedalX = ::this.delegateRedalX;
}
componentWillReceiveProps(nextProps) {
const hidden = nextProps.hidden !== this.props.hidden ? nextProps.hidden : this.state.hidden;
if (hidden !== this.state.hidden) this.setState({ hidden });
if (nextProps.scoped !== true) {
const hidden = nextProps.hidden !== this.props.hidden ? nextProps.hidden : this.state.hidden;
this.toggle(hidden, nextProps);

@@ -63,6 +82,6 @@ }

componentDidMount() {
const { scoped, ...props } = this.props;
if (scoped === true) return;
const props = this.props;
if (props.scoped === true) return;
this.node = document.createElement('div');
this.node.className = 'ReactModalPortal';
this.node.className = `${props.variant}-portal`;
document.body.appendChild(this.node);

@@ -83,5 +102,5 @@ this.toggle(props.hidden, props);

}
toggle(hidden = !this.state.hidden, { scoped, ...props } = this.props) {
toggle(hidden = !this.state.hidden, { ...props } = this.props) {
this.setState({ hidden });
if (scoped !== true) {
if (props.scoped !== true) {
props.hidden = hidden;

@@ -92,3 +111,3 @@ this.renderPortal(props);

delegateRedalX(redalX) {
return React.cloneElement(redalX, Object.assign({}, redalX.props, { onClick: this.createLeaveHandler(redalX.props.beforeLeave) }));
return React.cloneElement(redalX, { variant: this.props.variant, onClick: this.createLeaveHandler(redalX.props.beforeLeave) });
}

@@ -101,16 +120,17 @@ createLeaveHandler(beforeLeave) {

if (!shouldLeave || typeof shouldLeave.then !== 'function') return this.close();
shouldLeave.then(::this.close);
} : ::this.close;
shouldLeave.then(this.close);
} : this.close;
return handler;
}
renderPortal(props) {
this.portal = renderSubtreeIntoContainer(this, this.build(props), this.node);
}
build(pristineProps) {
const { enterDuration = DEFAULT_DURATION, leaveDuration = enterDuration, children, hidden, ...props } = pristineProps;
const { component = 'div', rootClassName, enterTimeout = DEFAULT_TIMEOUT, leaveTimeout = enterTimeout, children, hidden, ...props } = pristineProps;
const content = hidden ? null : (
<RedalWrapper key={WRAPPER_KEY} {...props} enterDuration={enterDuration} leaveDuration={leaveDuration} close={::this.close}>
{replaceRedalX(children, ::this.delegateRedalX)}
<RedalWrapper
{...props}
key={`${props.variant}wrapper`}
enterTimeout={enterTimeout}
leaveTimeout={leaveTimeout}
close={this.close}>
{replaceRedalX(children, this.delegateRedalX)}
</RedalWrapper>

@@ -120,4 +140,6 @@ );

return (
<ReactTransitionGroup component='div' transitionEnterTimeout={enterDuration} transitionLeaveTimeout={leaveDuration}>
{content}
<ReactTransitionGroup
component={component}
className={rootClassName}>
{content}
</ReactTransitionGroup>

@@ -127,5 +149,11 @@ );

renderPortal(props) {
this.portal = renderSubtreeIntoContainer(this, this.build(props), this.node);
}
render() {
const { scoped, ...props } = this.props;
return scoped !== true ? React.DOM.noscript() : props.hidden = this.state.hidden, this.build(props);
if (scoped !== true) return null;
props.hidden = this.state.hidden;
return this.build(props);
}

@@ -132,0 +160,0 @@ }

@@ -1,9 +0,13 @@

import React, { Component, PropTypes } from 'react';
import cns from 'classnames';
import domContains from './utils/dom-contains';
import React, { Component, Children, createElement, cloneElement } from 'react';
import ReactDOM from 'react-dom';
import cx from 'classnames';
import domContains from './utils/domContains';
import linkFuncs from './utils/linkFuncs';
const STATUS_WILL_ENTER = 1;
const STATUS_DID_ENTER = 2;
const STATUS_WILL_LEAVE = 3;
const STATUS_DID_LEAVE = 4;
const STATUS_WILL_APPEAR = 1;
const STATUS_DID_APPEAR = 2;
const STATUS_WILL_ENTER = 3;
const STATUS_DID_ENTER = 4;
const STATUS_WILL_LEAVE = 5;
const STATUS_DID_LEAVE = 6;

@@ -16,21 +20,22 @@ const INNER_REF = Symbol('inner');

this.state = { status: STATUS_WILL_ENTER };
this.handleMaskClick = ::this.handleMaskClick;
}
componentWillAppear(cb) {
console.log('redal will appear');
this.setState({ status: STATUS_WILL_ENTER });
cb();
const { willAppear, appearTimeout = 0 } = this.props;
this.setState({ status: STATUS_WILL_APPEAR });
setTimeout(cb, appearTimeout);
typeof willAppear === 'function' && setTimeout(() => willAppear(this.refs.inner), 0);
}
componentDidAppear() {
console.log('redal did appear');
this.setState({ status: STATUS_DID_ENTER });
const { didAppear } = this.props;
this.setState({ status: STATUS_DID_APPEAR });
typeof didAppear === 'function' && setTimeout(() => didAppear(this.refs.inner), 0);
}
componentWillEnter(cb) {
console.log('redal will enter');
const { willEnter, enterDuration = 0 } = this.props;
const { willEnter, enterTimeout = 0 } = this.props;
this.setState({ status: STATUS_WILL_ENTER });
setTimeout(cb, enterDuration);
setTimeout(cb, enterTimeout);
typeof willEnter === 'function' && setTimeout(() => willEnter(this.refs.inner), 0);
}
componentDidEnter() {
console.log('redal did enter');
const { didEnter } = this.props;

@@ -41,10 +46,8 @@ this.setState({ status: STATUS_DID_ENTER });

componentWillLeave(cb) {
console.log('redal will leave');
const { willLeave, leaveDuration = 0 } = this.props;
const { willLeave, leaveTimeout = 0 } = this.props;
this.setState({ status: STATUS_WILL_LEAVE });
setTimeout(cb, leaveDuration);
setTimeout(cb, leaveTimeout);
typeof willLeave === 'function' && setTimeout(() => willLeave(this.refs.inner), 0);
}
componentDidLeave() {
console.log('redal did leave');
const { didLeave } = this.props;

@@ -54,20 +57,31 @@ this.setState({ status: STATUS_DID_LEAVE });

}
handleClick(e) {
const { maskToggle, handleMaskClick, close } = this.props;
const inner = this.refs[INNER_REF];
const willLeave = typeof handleMaskClick === 'function' ? !handleMaskClick(e, inner) : maskToggle && !domContains(inner, e.target);
handleMaskClick(e) {
const { maskToggle = true, handleMaskClick: handler, close } = this.props;
const inner = ReactDOM.findDOMNode(this.refs[INNER_REF]);
const isMaskClicked = !domContains(inner, e.target);
if (!isMaskClicked) return;
const willLeave = typeof handler === 'function' ? handler(e, inner) : maskToggle;
if (willLeave) close();
}
render() {
const { className, children, ...props } = this.props;
const { className, variant, children, ...props } = this.props;
const { status } = this.state;
const cn = cns({
'redal--entering': status === STATUS_WILL_ENTER,
'redal--entered': status === STATUS_DID_ENTER,
'redal--leaving': status === STATUS_WILL_LEAVE,
'redal--left': status === STATUS_DID_LEAVE
}, 'redal', className);
const cn = cx({
[`${variant}--appearing`]: status === STATUS_WILL_APPEAR,
[`${variant}--appeared`]: status === STATUS_DID_APPEAR,
[`${variant}--entering`]: status === STATUS_WILL_ENTER,
[`${variant}--entered`]: status === STATUS_DID_ENTER,
[`${variant}--leaving`]: status === STATUS_WILL_LEAVE,
[`${variant}--left`]: status === STATUS_DID_LEAVE
}, variant, className);
const child = Children.count(children) === 1 ? children[0] : null;
const inner = child ?
cloneElement(child, { className: cx(child.props.className, `${variant}-inner`), ref: INNER_REF }) :
createElement('div', { className: cx(className, `${variant}-inner`), ref: INNER_REF }, children);
props.onClick = linkFuncs(props.onClick, this.handleMaskClick);
return (
<div className={cn} {...props} onClick={::this.handleClick}>
<div className={cns('redal-inner', className)} ref={INNER_REF}>{children}</div>
<div className={cn} {...props}>
{inner}
</div>

@@ -74,0 +88,0 @@ );

import React, { Component } from 'react';
import cns from 'classnames';
import cx from 'classnames';
class ReactX extends Component {
render() {
const { children, className, component = 'span', ...props } = this.props;
props.className = cns(className, 'redal-x');
const { children, variant, className, component = 'span', ...props } = this.props;
props.className = cx(className, variant && `${variant}-x`);
return React.createElement(component, props, children);

@@ -9,0 +9,0 @@ }

@@ -5,2 +5,4 @@ import webpack from 'webpack';

const WEBPACK_HOST = process.env.HOST || 'localhost'
const WEBPACK_PORT = process.env.PORT || 3006;
const PATHS = {

@@ -13,14 +15,12 @@ SRC: path.resolve(__dirname, 'src'),

};
const WEBPACK_HOST = process.env.HOST || 'localhost'
const WEBPACK_PORT = process.env.PORT || 3005;
let AUTOPREFIXER_CONF = [
const AUTOPREFIXER_CONF = [
'{browsers:["last 5 version"]}'
].join('&');
let resolve = {
const resolve = {
extensions: ['', '.js', '.jsx']
}
let externals = {
const externals = {
'react': {

@@ -49,5 +49,9 @@ root: 'React',

let build = {
const demo = {
entry: {
src: './src/index.js'
demo: [
'webpack-dev-server/client?http://' + WEBPACK_HOST + ':' + WEBPACK_PORT,
'webpack/hot/only-dev-server',
'./demo/index.js'
]
},

@@ -60,3 +64,2 @@ resolve: resolve,

sourceMapFilename: 'index.map.json',
library: 'ReactRedal',
libraryTarget: 'umd'

@@ -67,3 +70,4 @@ },

test: /\.jsx?$/,
loader: 'babel'
loaders: ['react-hot', `babel`],
include: [PATHS.SRC, PATHS.DEMO, PATHS.DIST]
}, {

@@ -74,13 +78,17 @@ test: /\.(css|scss)$/,

},
devtool: 'sourcemap',
externals: externals,
};
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
inject: 'body',
hash: true,
template: './demo/index.html',
title: 'Demo',
filename: 'index.html'
})
]
}
let demo = {
const build = {
entry: {
demo: [
'webpack-dev-server/client?http://' + WEBPACK_HOST + ':' + WEBPACK_PORT,
'webpack/hot/only-dev-server',
'./demo/index.js'
]
src: './src/index.js'
},

@@ -93,2 +101,3 @@ resolve: resolve,

sourceMapFilename: 'index.map.json',
library: 'ReactRedal',
libraryTarget: 'umd'

@@ -99,4 +108,4 @@ },

test: /\.jsx?$/,
loaders: ['react-hot', `babel`],
include: [PATHS.SRC, PATHS.DEMO]
loader: 'babel',
include: [PATHS.SRC, PATHS.DEMO, PATHS.DIST]
}, {

@@ -107,15 +116,6 @@ test: /\.(css|scss)$/,

},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
inject: 'body',
hash: true,
template: './demo/index.html',
title: 'Demo',
filename: 'index.html'
})
]
}
devtool: 'sourcemap',
externals: externals,
};
const devServerConf = {

@@ -131,8 +131,6 @@ contentBase: PATHS.DIST,

export default {
export {
WEBPACK_HOST, WEBPACK_PORT,
demo, devServerConf,
build,
demo,
devServerConf,
WEBPACK_HOST,
WEBPACK_PORT
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc