Skip to content

Commit

Permalink
feat(index.js): export ToastContainer and ToastMessage
Browse files Browse the repository at this point in the history
export ToastMessage for future subclassing

BREAKING CHANGE
  ToastContainer is put into exports and no longer a default export
  • Loading branch information
tomchentw committed Oct 12, 2014
1 parent 1d7950d commit ea3d2ea
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 156 deletions.
4 changes: 2 additions & 2 deletions client/scripts/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** @jsx React.DOM */
require("../styles/index.scss");
var React = require("react/addons");
var Container = require("../../src");
var {ToastContainer, ToastMessage} = require("../../src");

var Hello = React.createClass({
addAlert () {
Expand All @@ -10,7 +10,7 @@ var Hello = React.createClass({

render: function() {
return <div>
<Container ref="container" className="toast-top-right" />
<ToastContainer toastMessageClass={ToastMessage} ref="container" className="toast-top-right" />
<p onClick={this.addAlert}>Hello {this.props.name}</p>
</div>;
}
Expand Down
98 changes: 98 additions & 0 deletions src/ToastContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/** @jsx React.DOM */
var React = require("react/addons");
var {update} = React.addons;

var ToastMessage = require("./ToastMessage");

function noop () {}

module.exports = React.createClass({
displayName: "ToastContainer",

error (message, title, optionsOverride) {
this._notify(this.props.toastType.error, message, title, optionsOverride);
},

info (message, title, optionsOverride) {
this._notify(this.props.toastType.info, message, title, optionsOverride);
},

success (message, title, optionsOverride) {
this._notify(this.props.toastType.success, message, title, optionsOverride);
},

warning (message, title, optionsOverride) {
this._notify(this.props.toastType.warning, message, title, optionsOverride);
},

getDefaultProps () {
return {
toastType: {
error: "error",
info: "info",
success: "success",
warning: "warning"
},
id: "toast-container",
toastMessageClass: ToastMessage,
preventDuplicates: false,
newestOnTop: true,
onClick: noop
};
},

getInitialState () {
return {
toasts: [],
previousMessage: null
};
},

_notify (type, message, title, optionsOverride) {
var {props, state} = this;
if (props.preventDuplicates) {
if (state.previousMessage === message) {
return;
}
}
var newToast = update(optionsOverride || {}, {
$merge: {
type,
title,
message,
onClick: this._handleToastOnClick
}
});
var toastOperation = {};
toastOperation[(props.newestOnTop ? "$unshift" : "$push")] = [newToast];

var newState = update(state, {
previousMessage: { $set: message },
toasts: toastOperation
});
this.setState(newState);
},

_handleToastOnClick (event) {
this.props.onClick(event);
if (event.defaultPrevented) {
return;
}
event.preventDefault();
event.stopPropagation();
this._hideToast();
},

_hideToast: noop,//tapToDismiss

render () {
var {props, state} = this;
return this.transferPropsTo(
<div aria-live="polite" role="alert">
{state.toasts.map((toast) => {
return props.toastMessageClass(toast);
})}
</div>
);
}
});
63 changes: 63 additions & 0 deletions src/ToastMessage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/** @jsx React.DOM */
var React = require("react/addons");

module.exports = React.createClass({
displayName: "ToastMessage",

getDefaultProps () {
var iconClassNames = {
error: "toast-error",
info: "toast-info",
success: "toast-success",
warning: "toast-warning"
};

return {
className: "toast",
iconClassNames: iconClassNames,
titleClassName: "toast-title",
messageClassName: "toast-message",
closeButton: false
};
},

_render_close_button (props) {
return props.closeButton ? (
<button className="toast-close-button" role="button">&times;</button>
) : false;
},

_render_title_element (props) {
return props.title ? (
<div className={props.titleClassName}>
{props.title}
</div>
) : false;
},

_render_message_element (props) {
return props.message ? (
<div className={props.messageClassName}>
{props.message}
</div>
) : false;
},

render () {
var cx = React.addons.classSet;
var props = this.props;
var iconClassName = props.iconClassName || props.iconClassNames[props.type];

var toastClass = {};
toastClass[props.className] = true;
toastClass[iconClassName] = true;

return (
<div className={cx(toastClass)} onClick={props.onClick}>
{this._render_close_button(props)}
{this._render_title_element(props)}
{this._render_message_element(props)}
</div>
);
}
});
Empty file added src/ToastMessage/jQueryMixin.js
Empty file.
156 changes: 2 additions & 154 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,155 +1,3 @@
/** @jsx React.DOM */
var React = require("react/addons");
var {update} = React.addons;

function noop () {}

var AlertMessage = React.createClass({
displayName: "AlertMessage",

getDefaultProps () {
var iconClassNames = {
error: "toast-error",
info: "toast-info",
success: "toast-success",
warning: "toast-warning"
};

return {
className: "toast",
iconClassNames: iconClassNames,
titleClassName: "toast-title",
messageClassName: "toast-message",
closeButton: false
};
},

_render_close_button (props) {
return props.closeButton ? (
<button className="toast-close-button" role="button">&times;</button>
) : false;
},

_render_title_element (props) {
return props.title ? (
<div className={props.titleClassName}>
{props.title}
</div>
) : false;
},

_render_message_element (props) {
return props.message ? (
<div className={props.messageClassName}>
{props.message}
</div>
) : false;
},

render () {
var cx = React.addons.classSet;
var props = this.props;
var iconClassName = props.iconClassName || props.iconClassNames[props.type];

var toastClass = {};
toastClass[props.className] = true;
toastClass[iconClassName] = true;

return (
<div className={cx(toastClass)} onClick={props.onClick}>
{this._render_close_button(props)}
{this._render_title_element(props)}
{this._render_message_element(props)}
</div>
);
}
});

module.exports = React.createClass({
displayName: "Container",

error (message, title, optionsOverride) {
this._notify(this.props.toastType.error, message, title, optionsOverride);
},

info (message, title, optionsOverride) {
this._notify(this.props.toastType.info, message, title, optionsOverride);
},

success (message, title, optionsOverride) {
this._notify(this.props.toastType.success, message, title, optionsOverride);
},

warning (message, title, optionsOverride) {
this._notify(this.props.toastType.warning, message, title, optionsOverride);
},

getDefaultProps () {
return {
toastType: {
error: "error",
info: "info",
success: "success",
warning: "warning"
},
id: "toast-container",
preventDuplicates: false,
newestOnTop: true,
onClick: noop
};
},

getInitialState () {
return {
toasts: [],
previousMessage: null
};
},

_notify (type, message, title, optionsOverride) {
var {props, state} = this;
if (props.preventDuplicates) {
if (state.previousMessage === message) {
return;
}
}
var newToast = update(optionsOverride || {}, {
$merge: {
type,
title,
message,
onClick: this._handleToastOnClick
}
});
var toastOperation = {};
toastOperation[(props.newestOnTop ? "$unshift" : "$push")] = [newToast];

var newState = update(state, {
previousMessage: { $set: message },
toasts: toastOperation
});
this.setState(newState);
},

_handleToastOnClick (event) {
this.props.onClick(event);
if (event.defaultPrevented) {
return;
}
event.preventDefault();
event.stopPropagation();
this._hideToast();
},

_hideToast: noop,//tapToDismiss

render () {
return this.transferPropsTo(
<div aria-live="polite" role="alert">
{this.state.toasts.map((toast) => {
return AlertMessage(toast);
})}
</div>
);
}
});
exports.ToastContainer = require("./ToastContainer");
exports.ToastMessage = require("./ToastMessage");

0 comments on commit ea3d2ea

Please sign in to comment.