Skip to content

Commit 37bb8cf

Browse files
committed
Merge pull request #9 from georgeOsdDev/feature/react-0.14
Feature/react 0.14
2 parents 216e569 + 3ae3626 commit 37bb8cf

File tree

8 files changed

+277
-63
lines changed

8 files changed

+277
-63
lines changed

.babelrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"presets": [
3+
"es2015",
4+
"react"
5+
]
6+
}

example/app.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use strict';
22

3-
import React from 'react/addons';
4-
import Notification from '../components/Notification';
3+
import React from 'react';
4+
import ReactDom from 'react-dom';
5+
import Notification from '../src/components/Notification';
56

67
//allow react dev tools work
78
window.React = React;
@@ -102,4 +103,4 @@ class App extends React.Component {
102103
}
103104
};
104105

105-
React.render(<App/>, document.getElementById('out'));
106+
ReactDom.render(<App/>, document.getElementById('out'));

karma.conf.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,17 @@ module.exports = function(config) {
3434

3535
browserify: {
3636
debug: true,
37-
transform: [
38-
'babelify'
37+
'transform': [
38+
[
39+
'babelify',
40+
{
41+
'compact': false,
42+
'presets': [
43+
'react',
44+
'es2015'
45+
]
46+
}
47+
]
3948
]
4049
},
4150

lib/components/Notification.js

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
'use strict';
2+
3+
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
4+
5+
Object.defineProperty(exports, "__esModule", {
6+
value: true
7+
});
8+
9+
var _react = require('react');
10+
11+
var _react2 = _interopRequireDefault(_react);
12+
13+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14+
15+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16+
17+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
18+
19+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
20+
21+
var PERMISSION_GRANTED = 'granted';
22+
23+
var seqGen = function seqGen() {
24+
var i = 0;
25+
return function () {
26+
return i++;
27+
};
28+
};
29+
var seq = seqGen();
30+
31+
var Notification = (function (_React$Component) {
32+
_inherits(Notification, _React$Component);
33+
34+
function Notification(props) {
35+
_classCallCheck(this, Notification);
36+
37+
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Notification).call(this, props));
38+
39+
var supported = false;
40+
var granted = false;
41+
if ('Notification' in window && window.Notification) {
42+
supported = true;
43+
if (window.Notification.permission === PERMISSION_GRANTED) {
44+
granted = true;
45+
}
46+
} else {
47+
supported = false;
48+
}
49+
50+
_this.state = {
51+
supported: supported,
52+
granted: granted
53+
};
54+
// Do not save Notification instance in state
55+
_this.notifications = {};
56+
_this.windowFocus = true;
57+
_this.onWindowFocus = _this._onWindowFocus.bind(_this);
58+
_this.onWindowBlur = _this._onWindowBlur.bind(_this);
59+
return _this;
60+
}
61+
62+
_createClass(Notification, [{
63+
key: '_onWindowFocus',
64+
value: function _onWindowFocus() {
65+
this.windowFocus = true;
66+
}
67+
}, {
68+
key: '_onWindowBlur',
69+
value: function _onWindowBlur() {
70+
this.windowFocus = false;
71+
}
72+
}, {
73+
key: 'componentDidMount',
74+
value: function componentDidMount() {
75+
var _this2 = this;
76+
77+
if (this.props.disableActiveWindow) {
78+
if (window.addEventListener) {
79+
window.addEventListener('focus', this.onWindowFocus);
80+
window.addEventListener('blur', this.onWindowBlur);
81+
} else if (window.attachEvent) {
82+
window.attachEvent('focus', this.onWindowFocus);
83+
window.attachEvent('blur', this.onWindowBlur);
84+
}
85+
}
86+
87+
if (!this.state.supported) {
88+
this.props.notSupported();
89+
} else {
90+
if (this.state.granted) {
91+
this.props.onPermissionGranted();
92+
} else {
93+
window.Notification.requestPermission(function (permission) {
94+
var result = permission === PERMISSION_GRANTED;
95+
_this2.setState({
96+
granted: result
97+
}, function () {
98+
if (result) {
99+
_this2.props.onPermissionGranted();
100+
} else {
101+
_this2.props.onPermissionDenied();
102+
}
103+
});
104+
});
105+
}
106+
}
107+
}
108+
}, {
109+
key: 'componentWillUnmount',
110+
value: function componentWillUnmount() {
111+
if (this.props.disableActiveWindow) {
112+
if (window.removeEventListner) {
113+
window.removeEventListener('focus', this.onWindowFocus);
114+
window.removeEventListener('blur', this.onWindowBlur);
115+
} else if (window.detachEvent) {
116+
window.detachEvent('focus', this.onWindowFocus);
117+
window.detachEvent('blur', this.onWindowBlur);
118+
}
119+
}
120+
}
121+
}, {
122+
key: 'render',
123+
value: function render() {
124+
var _this3 = this;
125+
126+
var doNotShowOnActiveWindow = this.props.disableActiveWindow && this.windowFocus;
127+
if (!this.props.ignore && this.props.title && this.state.supported && this.state.granted && !doNotShowOnActiveWindow) {
128+
(function () {
129+
130+
var opt = _this3.props.options;
131+
if (typeof opt.tag !== 'string') {
132+
opt.tag = 'web-notification-' + seq();
133+
}
134+
135+
if (!_this3.notifications[opt.tag]) {
136+
var n = new window.Notification(_this3.props.title, opt);
137+
n.onshow = function (e) {
138+
_this3.props.onShow(e, opt.tag);
139+
setTimeout(function () {
140+
_this3.close(opt.tag);
141+
}, _this3.props.timeout);
142+
};
143+
n.onclick = function (e) {
144+
_this3.props.onClick(e, opt.tag);
145+
};
146+
n.onclose = function (e) {
147+
_this3.props.onClose(e, opt.tag);
148+
};
149+
n.onerror = function (e) {
150+
_this3.props.onError(e, opt.tag);
151+
};
152+
153+
_this3.notifications[opt.tag] = n;
154+
}
155+
})();
156+
}
157+
158+
// return null cause
159+
// Error: Invariant Violation: Notification.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
160+
return _react2.default.createElement('input', { type: 'hidden', name: 'dummy-for-react-web-notification', style: { display: 'none' } });
161+
}
162+
}, {
163+
key: 'close',
164+
value: function close(tag) {
165+
if (this.notifications[tag] && typeof this.notifications[tag].close === 'function') {
166+
this.notifications[tag].close();
167+
}
168+
}
169+
170+
// for debug
171+
172+
}, {
173+
key: '_getNotificationInstance',
174+
value: function _getNotificationInstance(tag) {
175+
return this.notifications[tag];
176+
}
177+
}]);
178+
179+
return Notification;
180+
})(_react2.default.Component);
181+
182+
Notification.propTypes = {
183+
ignore: _react2.default.PropTypes.bool,
184+
disableActiveWindow: _react2.default.PropTypes.bool,
185+
notSupported: _react2.default.PropTypes.func,
186+
onPermissionGranted: _react2.default.PropTypes.func,
187+
onPermissionDenied: _react2.default.PropTypes.func,
188+
onShow: _react2.default.PropTypes.func,
189+
onClick: _react2.default.PropTypes.func,
190+
onClose: _react2.default.PropTypes.func,
191+
onError: _react2.default.PropTypes.func,
192+
timeout: _react2.default.PropTypes.number,
193+
title: _react2.default.PropTypes.string.isRequired,
194+
options: _react2.default.PropTypes.object
195+
};
196+
197+
Notification.defaultProps = {
198+
ignore: false,
199+
disableActiveWindow: false,
200+
notSupported: function notSupported() {},
201+
onPermissionGranted: function onPermissionGranted() {},
202+
onPermissionDenied: function onPermissionDenied() {},
203+
onShow: function onShow() {},
204+
onClick: function onClick() {},
205+
onClose: function onClose() {},
206+
onError: function onError() {},
207+
timeout: 5000,
208+
options: {}
209+
};
210+
211+
exports.default = Notification;

package.json

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
{
22
"name": "react-web-notification",
3-
"version": "0.1.1",
3+
"version": "0.1.2",
44
"description": "React component with HTML5 Web Notification API",
5-
"main": "./dist/ReactWebNotification.js",
5+
"main": "./lib/components/ReactWebNotification.js",
66
"scripts": {
77
"browser": "browser-sync start --files example/* --server example",
88
"watch:example": "watchify example/app.js -dv -o example/bundle.js",
99
"start:example": "npm run watch:example & npm run browser",
1010
"test:local": "karma start",
1111
"test": "./node_modules/.bin/karma start --browsers Firefox --single-run",
12-
"clean": "rimraf dist",
13-
"build": "npm run clean & webpack"
12+
"clean": "rimraf lib",
13+
"build": "babel src --out-dir lib"
1414
},
1515
"repository": {
1616
"type": "git",
@@ -29,39 +29,50 @@
2929
},
3030
"homepage": "https://github.com/georgeosddev/react-web-notification",
3131
"devDependencies": {
32-
"babel-eslint": "^3.1.9",
33-
"babelify": "^6.1.2",
34-
"browser-sync": "^2.7.6",
35-
"browserify": "^10.2.1",
36-
"chai": "^2.3.0",
37-
"eslint": "^0.21.2",
38-
"eslint-plugin-react": "^2.3.0",
39-
"karma": "^0.12.35",
40-
"karma-browserify": "^4.2.1",
32+
"babel-cli": "^6.3.17",
33+
"babel-core": "^6.3.21",
34+
"babel-eslint": "^5.0.0-beta6",
35+
"babel-loader": "^6.2.0",
36+
"babel-preset-es2015": "^6.3.13",
37+
"babel-preset-react": "^6.3.13",
38+
"babelify": "^7.2.0",
39+
"browser-sync": "^2.10.1",
40+
"browserify": "^12.0.1",
41+
"chai": "^3.4.1",
42+
"eslint": "^1.10.3",
43+
"eslint-plugin-react": "^3.12.0",
44+
"karma": "^0.13.15",
45+
"karma-browserify": "^4.4.2",
4146
"karma-chai": "^0.1.0",
42-
"karma-chrome-launcher": "^0.1.12",
43-
"karma-cli": "0.0.4",
44-
"karma-firefox-launcher": "^0.1.6",
45-
"karma-mocha": "^0.1.10",
47+
"karma-chrome-launcher": "^0.2.2",
48+
"karma-cli": "0.1.1",
49+
"karma-firefox-launcher": "^0.1.7",
50+
"karma-mocha": "^0.2.1",
4651
"karma-safari-launcher": "^0.1.1",
47-
"karma-spec-reporter": "0.0.19",
48-
"mocha": "^2.2.5",
49-
"sinon": "^1.14.1",
50-
"watchify": "^3.2.1",
51-
"webpack": "^1.12.0",
52-
"babel-core": "^5.8.23",
53-
"babel-loader": "^5.3.2",
54-
"rimraf": "^2.4.3"
52+
"karma-spec-reporter": "0.0.23",
53+
"mocha": "^2.3.4",
54+
"react-addons-test-utils": "^0.14.3",
55+
"react-dom": "^0.14.3",
56+
"rimraf": "^2.4.4",
57+
"sinon": "^1.17.2",
58+
"watchify": "^3.6.1"
5559
},
5660
"dependencies": {
57-
"react": "^0.13.3"
61+
"react": "^0.14.3"
62+
},
63+
"peerDependencies": {
64+
"react": "^0.14.3"
5865
},
5966
"browserify": {
6067
"transform": [
6168
[
6269
"babelify",
6370
{
64-
"compact": false
71+
"compact": false,
72+
"presets": [
73+
"es2015",
74+
"react"
75+
]
6576
}
6677
]
6778
]
File renamed without changes.

test/components/Notification_spec.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
'use strict';
2-
import React from 'react/addons';
2+
3+
import React from 'react';
4+
import ReactDom from 'react-dom';
5+
import TestUtils from 'react-addons-test-utils';
6+
37
import chai from 'chai';
48
import sinon from 'sinon';
59
let expect = chai.expect;
610
import events from 'events'
711
let EventEmitter = events.EventEmitter;
8-
import Notification from '../../components/Notification';
9-
const {TestUtils} = React.addons;
12+
import Notification from '../../src/components/Notification';
1013

1114
const PERMISSION_GRANTED = 'granted';
1215
const PERMISSION_DENIED = 'denied';
@@ -38,7 +41,7 @@ describe('Test of Notification', () => {
3841
component = TestUtils.renderIntoDocument(<Notification title='test'/>);
3942
const el = TestUtils.scryRenderedDOMComponentsWithTag(component, 'input');
4043
expect(el.length).to.be.eql(1);
41-
expect(React.findDOMNode(el[0]).type).to.be.eql('hidden');
44+
expect(ReactDom.findDOMNode(el[0]).type).to.be.eql('hidden');
4245
});
4346
});
4447

0 commit comments

Comments
 (0)