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

react-notification

Package Overview
Dependencies
Maintainers
2
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-notification - npm Package Compare versions

Comparing version 6.5.2 to 6.6.0

bin/test.sh

8

dist/notification.js

@@ -49,3 +49,3 @@ 'use strict';

value: function componentWillReceiveProps(nextProps) {
if (this.props.dismissAfter === false) return;
if (nextProps.dismissAfter === false) return;

@@ -57,4 +57,6 @@ // See http://eslint.org/docs/rules/no-prototype-builtins

if (nextProps.onDismiss && nextProps.isActive && !this.props.isActive) {
this.dismissTimeout = setTimeout(nextProps.onDismiss, nextProps.dismissAfter);
if (nextProps.onDismiss) {
if (nextProps.isActive && !this.props.isActive || nextProps.dismissAfter && this.props.dismissAfter === false) {
this.dismissTimeout = setTimeout(nextProps.onDismiss, nextProps.dismissAfter);
}
}

@@ -61,0 +63,0 @@ }

@@ -36,4 +36,14 @@ 'use strict';

var dismissNow = isLast || !props.dismissInOrder;
// Handle styles
var barStyle = props.barStyleFactory(index, notification.barStyle);
var activeBarStyle = props.activeBarStyleFactory(index, notification.activeBarStyle);
// Allow onClick from notification stack or individual notifications
var onClick = notification.onClick || props.onClick;
var onDismiss = props.onDismiss;
var dismissAfter = notification.dismissAfter;
if (dismissAfter !== false) {

@@ -43,4 +53,2 @@ if (dismissAfter == null) dismissAfter = props.dismissAfter;

}
var barStyle = props.barStyleFactory(index, notification.barStyle);
var activeBarStyle = props.activeBarStyleFactory(index, notification.activeBarStyle);

@@ -52,3 +60,4 @@ return _react2.default.createElement(_stackedNotification2.default, _extends({}, notification, {

dismissAfter: dismissAfter,
onDismiss: props.onDismiss.bind(undefined, notification),
onDismiss: onDismiss.bind(undefined, notification),
onClick: onClick.bind(undefined, notification),
activeBarStyle: activeBarStyle,

@@ -66,5 +75,7 @@ barStyle: barStyle

barStyleFactory: _react.PropTypes.func,
dismissInOrder: _react.PropTypes.bool.isRequired,
dismissInOrder: _react.PropTypes.bool,
notifications: _react.PropTypes.array.isRequired,
onDismiss: _react.PropTypes.func.isRequired
onDismiss: _react.PropTypes.func.isRequired,
onClick: _react.PropTypes.func,
action: _react.PropTypes.string
};

@@ -76,3 +87,4 @@

dismissInOrder: true,
dismissAfter: 1000
dismissAfter: 1000,
onClick: function onClick() {}
};

@@ -79,0 +91,0 @@

@@ -54,6 +54,9 @@ 'use strict';

if (this.props.dismissAfter) {
this.dismissTimeout = setTimeout(this.setState.bind(this, {
isActive: false
}), this.props.dismissAfter);
this.dismiss(this.props.dismissAfter);
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
if (nextProps.dismissAfter !== this.props.dismissAfter) {
this.dismiss(nextProps.dismissAfter);
}

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

}
}, {
key: 'dismiss',
value: function dismiss(dismissAfter) {
if (dismissAfter === false) return;
this.dismissTimeout = setTimeout(this.setState.bind(this, {
isActive: false
}), dismissAfter);
}
/*

@@ -70,0 +82,0 @@ * @function handleClick

{
"name": "react-notification",
"version": "6.5.2",
"description": "Snackbar style notification component for React.",
"version": "6.6.0",
"description": "Snackbar style notification component for React",
"main": "dist/index.js",
"scripts": {
"prepublish": "npm run build",
"precommit": "echo 'Running pre-commit hooks...' && npm test",
"prepublish": "npm run build",
"prebuild": "npm test",
"build": "`npm bin`/babel src -d dist",
"pretest": "npm run lint",
"test": "NODE_ENV=test `npm bin`/mocha --compilers js:babel-core/register --reporter spec --recursive --timeout 5000 test/setup.js test/**/*.js",
"test": "./bin/test.sh",
"lint": "`npm bin`/eslint src/**/*.js test/**/*.js",

@@ -31,2 +31,3 @@ "start": "node examples/server.js"

"notification",
"notification stack",
"snackbar"

@@ -33,0 +34,0 @@ ],

@@ -1,181 +0,22 @@

# react-notification
# React Notification
[![npm version](https://badge.fury.io/js/react-notification.svg)](http://badge.fury.io/js/react-notification) [![Build Status](https://travis-ci.org/pburtchaell/react-notification.svg)](https://travis-ci.org/pburtchaell/react-notification) [![npm downloads](https://img.shields.io/npm/dm/react-notification.svg?style=flat)](http://badge.fury.io/js/react-notification)
[![npm version](https://badge.fury.io/js/react-notification.svg)](http://badge.fury.io/js/react-notification) [![Build Status](https://travis-ci.org/pburtchaell/react-notification.svg)](https://travis-ci.org/pburtchaell/react-notification) [![npm downloads](https://img.shields.io/npm/dm/react-notification.svg?style=flat)](http://badge.fury.io/js/react-notification)
## Overview
![](https://raw.githubusercontent.com/pburtchaell/react-notification/master/docs/example-b.gif)
![](https://raw.githubusercontent.com/pburtchaell/react-notification/master/examples/example.gif)
![](https://raw.githubusercontent.com/pburtchaell/react-notification/master/examples/stack.gif)
React Notification is a component designed to provide snackbar notification messages and notification stacks. The default visual style and interaction follows [Material Design guidelines for snackbards](http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-usage), but it can be fully customized.
This is a component designed to provide "[snackbar](http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-usage)" notification messages and notification stacks (similar to how notifications stack on OS X). I would suggest reading the usage guidelines for [snackbars](http://www.google.com/design/spec/components/snackbars-toasts.html#).
## Docs and Help
## Getting Started
- [Guides](/docs/guides/)
- [Introduction](/docs/introduction.md)
- [Examples](/examples)
- [Releases](https://github.com/pburtchaell/react-notification/releases)
- [Upgrading versions](/UPGRADING.md)
Install the component via npm: `npm install react-notification`.
## Sponsor
If you are using the React 0.13.x or lower, you can install the previously compatible version of this component with `npm i react-notification@2.3.0 -S`. The current version only works with React 0.14.x.
To help cover the cost of my time spent maintaining open source software (OSS) projects, **I'm looking for a small sponsor.** If your company is interested, [send me an email](mailto:patrick@pburtchaell.com) and we can chat! If you like my code and you're interested in buying me a drink, I have a [Gratipay](https://gratipay.com/~pburtchaell/). Thanks! I greatly appreciate your support and I'm grateful to be a part of the OSS and GitHub community.
Please read the [contributing guide](/CONTRUBUTING.md) if you are interested in contributing. If you are coming from version 1.0.0, there is an [upgrade guide](/UPGRADING.md) to help you make the switch. If you have questions, please feel free to create an issue on GitHub.
Note the component uses `Object.assign`. If you are compiling with Babel, you should include the Babel Polyfill in your build to ensure the method works.
## Usage
Single notification:
```js
import { Notification } from 'react-notification';
<Notification
isActive={boolean}
message={string}
action={string}
onClick={myClickHander}
/>
```
Notification stack:
```js
import { NotificationStack } from 'react-notification';
import { OrderedSet } from 'immutable';
constructor () {
super();
this.state = {
notifications: OrderedSet()
};
}
addNotification () {
const newCount = count + 1;
return this.setState({
notifications: this.state.notifications.add({
message: `Notification ipsum...`,
key: 'some UID',
action: 'Dismiss',
onClick: (deactivate) => {
deactivate();
setTimeout(() => this.removeNotification('some UID'), 400);
},
})
});
}
removeNotification (count) {
this.setState({
notifications: this.state.notifications.filter(n => n.key !== count)
})
}
render () {
return (
<NotificationStack
notifications={this.state.notifications.toArray()}
onDismiss={notification => this.setState({
notifications: this.state.notifications.delete(notification)
})}
/>
);
}
```
See the [examples](examples/notification-tree) for more context on how to use a notification stack.
### Props
For Notification component:
| Name | Type | Description | Required | Default |
|-----------------|-------------------------|-------------------------------------------------------------|-----------|----------------------------|
| isActive | boolean | If true, the notification is visible | true | `false` |
| message | string or React element | The message or component for the notification | true | |
| title | string | The title for the notification | | |
| action | string | The name of the action, e.g., "close" or "undo" | | |
| style | boolean | Setting this prop to `false` will disable all inline styles | | |
| barStyle | object | Custom snackbar styles | | |
| activeBarStyle | object | Custom snackbar styles when the bar is active | | |
| actionStyle | object | Custom action styles | | |
| className | string | Custom class to apply to the top-level component | | |
| activeClassName | string | Custom class to apply to the top-level component when active| | `'notification-bar-active'`|
| dismissAfter | number or false | Timeout for onDismiss event | | `2000` |
The `style` prop useful if you are not using React inline styles and would like to use CSS instead. See [styles](#styles) for more.
For NotificationStack component:
| Name | Type | Description | Required | Default |
|-----------------------|-------|----------------------------------------------------------|---------- |----------|
| notifications | array | Array of notifications to render | true | |
| dismissInOrder | bool | If false, notification dismiss timers start immediately | false | true |
| barStyleFactory | func | create the style of the notification | false | fn |
| activeBarStyleFactory | func | create the style of the active notification | false | fn |
**Update** `v5.0.3`: Now notifications used in a stack _can_ have all properties included in the regular notification component.
## Events
For Notification component:
| Event | Description |
|-----------|------------------------------------------------------------|
| onClick | Callback function to run when the action is clicked |
| onDismiss | Callback function to run when dismissAfter timer runs out |
onClick is called with parameter *deactivate*, which is a function and can be called to set the notification to inactive. Used to activate notification exit animation on click.
For NotificationStack component:
| Event | Description | Arguments |
|-----------|------------------------------------------------------------------------------|-----------------------------------------------------------|
| onDismiss | Callback function to run when dismissAfter timer runs out for a notification | The object for the notification currently being dismissed |
## Styles
This component does use basic inline CSS to style the position and visibility of the notification. You have two options for adding additional styles:
1. Remove all inline styles and use only CSS.
2. Add additional inline styles via the style prop.
The DOM tree of the component for reference:
```html
<div class="notification-bar">
<div class="notification-bar-wrapper" onClick={this.props.onClick}>
<span class="notification-bar-message">{this.props.message}</span>
<span class="notification-bar-action">{this.props.action}</span>
</div>
</div>
```
To use additional inline styles, return two objects. The `bar` object applies styles to the entire notification "snackbar" and the `action` object applies styles to the action message. Under the hood, this uses `Object.assign` to handle properly combining styles.
I would highly suggest using this method since the styles included in the component by default handle the visibility of the notification. If you remove these styles, the component won't actually show or hide itself.
### barStyleFactory and activeBarStyleFactory NotificationStack props
These two function have the following signature:
```js
(index: Number, style: Object|Void) => Object
```
Where `index` is the index of the notification in the notifications array and
`style` is the style property of the individual notification.
This function is used to dynamically set the style of each notification in the
stack. The default function adds the `bottom` style property to correctly
position of the notification in a stack.
```js
function defaultStyleFactory(index, style) {
return Object.assign(
{},
style,
{ bottom: `${2 + index * 4}rem` }
);
}
```
---
Copyright (c) 2015 Patrick Burtchaell. [Licensed with The MIT License (MIT)](https://raw.githubusercontent.com/pburtchaell/react-notification/master/LICENSE). [Gratipay](https://gratipay.com/~pburtchaell/).

@@ -53,4 +53,4 @@ import React from 'react';

done();
} catch (e) {
done(e);
} catch (error) {
throw error;
}

@@ -61,25 +61,2 @@ // Add time due to each StackedNotification transition time ( > 300 )

it('onDismiss fires after `dismissAfter` value + transition time', (done) => {
const handleDismiss = spy();
const wrapper = mount(
<NotificationStack
notifications={notifications}
onDismiss={handleDismiss}
/>
);
wrapper.update();
setTimeout(() => {
try {
expect(handleDismiss.calledOnce).to.equal(true);
done();
} catch (e) {
done(e);
}
// Add time due to each StackedNotification transition time ( > 300 )
}, mockNotification.dismissAfter + 340);
});
it('should not dismiss when `dismissAfter` is `false`', (done) => {

@@ -101,4 +78,4 @@ const handleDismiss = spy();

done();
} catch (e) {
done(e);
} catch (error) {
throw error;
}

@@ -109,36 +86,37 @@ // Add time due to each StackedNotification transition time ( > 300 )

it('onDismiss fires on each Notification in the stack', (done) => {
it('should dismiss when `dismissAfter` is updated to a number after it was `false`', (done) => {
const handleDismiss = spy();
let dismissAfter = 0;
const wrapper = mount(
<NotificationStack
notifications={notifications}
dismissInOrder={false}
notifications={[{ ...mockNotification, dismissAfter: false }]}
onDismiss={handleDismiss}
/>
);
wrapper.update();
setTimeout(() => {
try {
expect(handleDismiss.callCount).to.equal(notifications.length);
done();
} catch (e) {
done(e);
}
// Add transition time + 1000ms per each Notification
}, mockNotification.dismissAfter + 1340);
});
it('onDismiss does not fire until `dismissAfter` value times out', () => {
const handleDismiss = spy();
const isDismissed = (called, callback) => {
setTimeout(() => {
try {
expect(handleDismiss.called).to.equal(called);
callback();
} catch (err) {
callback(err);
}
// Add time due to each StackedNotification transition time ( > 300 )
}, dismissAfter + 440);
};
// eslint-disable-next-line
const wrapper = shallow(
<NotificationStack
notifications={[mockNotification]}
onDismiss={handleDismiss}
/>
);
expect(handleDismiss.calledOnce).to.equal(false);
isDismissed(false, (err) => {
if (err) return done(err);
dismissAfter = 110;
wrapper.setProps({
notifications: [{ ...mockNotification, dismissAfter }]
}, () => {
isDismissed(true, done);
});
});
});

@@ -152,2 +130,3 @@

);
const stack = mount(

@@ -160,3 +139,5 @@ <NotificationStack

);
const notification = stack.find(Notification);
expect(notification.prop('barStyle').bottom).to.equal('0px');

@@ -171,2 +152,3 @@ });

);
const stack = mount(

@@ -179,3 +161,5 @@ <NotificationStack

);
const notification = stack.find(Notification);
expect(notification.prop('barStyle').background).to.equal('rgb(2, 2, 2)');

@@ -190,2 +174,3 @@ });

);
const stack = mount(

@@ -198,3 +183,5 @@ <NotificationStack

);
const notification = stack.find(Notification);
expect(notification.prop('activeBarStyle').bottom).to.equal('2px');

@@ -209,2 +196,3 @@ });

);
const stack = mount(

@@ -217,5 +205,146 @@ <NotificationStack

);
const notification = stack.find(Notification);
expect(notification.prop('activeBarStyle').left).to.equal('4rem');
});
/**
* Test: Global handling of onClick:
*
* If a child notification in the stack does not have an onClick property,
* then fire onClick at the parent (<NotificationStack />) level.
*
* Because the mockNotification we used for other tests includes an
* onClick property, we need use a different mock notification.
*/
it('onClick fires globally when notification action is clicked', () => {
const handleClickGlobal = spy();
// Render a notification stack with one notification child
const wrapper = mount(
<NotificationStack
notifications={[{
key: '0',
message: 'Foo',
action: 'Dismiss',
dismissAfter: 100,
title: 'Title'
// No onClick property on the notification child
// onClick: () => {}
}]}
// Instead, it is handled globally
onClick={handleClickGlobal}
onDismiss={() => {}}
/>
);
// Simulate a click on the notification in the stack
const notification = wrapper.find('.notification-bar-action');
notification.simulate('click');
// Expect handleClick to be caled once
expect(handleClickGlobal).to.have.property('callCount', 1);
});
/**
* Test: Local handling of onClick:
*
* If a child notification in the stack has an onClick property,
* then fire onClick on the child.
*/
it('onClick fires locally when notification action is clicked', () => {
const handleClickLocal = spy();
const handleClickGlobal = spy();
// Render a notification stack with one notification child
const wrapper = mount(
<NotificationStack
notifications={[{
key: mockNotification.key,
message: mockNotification.message,
action: mockNotification.action,
dismissAfter: mockNotification.dismissAfter,
title: mockNotification.title,
onClick: handleClickLocal
}]}
// Instead, it is handled globally
onClick={handleClickGlobal}
onDismiss={() => {}}
/>
);
// Simulate a click on the notification in the stack
const notification = wrapper.find('.notification-bar-action');
notification.simulate('click');
// Expect local to be called once and global to be called 0
expect(handleClickLocal).to.have.property('callCount', 1);
expect(handleClickGlobal).to.have.property('callCount', 0);
});
it('onDismiss fires for notification', (done) => {
const handleDismiss = spy();
const wrapper = mount(
<NotificationStack
notifications={notifications}
onDismiss={handleDismiss}
/>
);
wrapper.update();
setTimeout(() => {
try {
expect(handleDismiss.callCount).to.equal(notifications.length);
done();
} catch (error) {
throw error;
}
// Add transition time + 1000ms per each Notification
}, mockNotification.dismissAfter + 1340);
});
it('onDismiss does not fire until `dismissAfter` value times out', () => {
const handleDismiss = spy();
// eslint-disable-next-line
const wrapper = shallow(
<NotificationStack
notifications={[mockNotification]}
onDismiss={handleDismiss}
/>
);
expect(handleDismiss.calledOnce).to.equal(false);
});
it('onDismiss fires after `dismissAfter` value', (done) => {
const handleDismiss = spy();
const wrapper = mount(
<NotificationStack
notifications={notifications}
onDismiss={handleDismiss}
/>
);
wrapper.update();
setTimeout(() => {
try {
expect(handleDismiss.calledOnce).to.equal(true);
done();
} catch (error) {
throw error;
}
// Add time due to each StackedNotification transition time ( > 300 )
}, mockNotification.dismissAfter + 340);
});
});

@@ -21,3 +21,1 @@ # 1.0.0 to 2.0.0

```
If you have questions, please feel free to create an issue on GitHub or message me (@pburtchaell) on the [Reactiflux Slack community](http://www.reactiflux.com/).
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