Notifications
by evgkch
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.9/react-with-addons.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.9/react-dom.js"></script>
<div id="app"></div>
SCSS
$green-color: rgb(29, 182, 119);
body {
font-family: Arial;
background-color: #2F2F30;
}
.container {
clear: both;
width: 100%;
padding-top: 20px;
transition: all 300ms ease-out;
}
.nt-container {
transition: all 300ms ease-out;
position: absolute;
perspective: 150px;
perspective-origin: bottom center;
.nt-box {
position: relative;
matgin-top: 0;
top: 0;
transition: all 100ms ease-out;
.nt-close-button {
position: absolute;
cursor: pointer;
user-select: none;
z-index: 9999;
transition: all 100ms ease-out;
&:hover {
transform: scale(1.5);
}
&:active {
transform: scale(1);
}
}
}
.nt-theme-white {
background-color: white;
.nt-close-button {
color: #363436;
}
}
.nt-theme-grey {
background-color: #dbdbe3;
.nt-close-button {
color: white;
}
}
.nt-theme-green {
background-color: $green-color;
.nt-close-button {
color: #363436;
}
}
.nt-animate-slide-left {
transform: translateX(-150%);
opacity: 0;
}
.nt-animate-slide-right {
transform: translateX(150%);
opacity: 0;
}
.nt-animate-slide-top {
transform: translateY(-150%);
opacity: 0;
}
.nt-animate-slide-bottom {
transform: translateY(150%);
opacity: 0;
}
.nt-animate-scale {
transform: scale(0);
}
.nt-animate-hidden {
opacity: 0;
}
.nt-animate-3d {
transform: rotateX(90deg);
transform-style: preserve-3d;
}
}
.nt-body-content {
margin-top: 15px;
}
.nt-body-incident, .nt-body-task {
display: flex;
flex-direction: column;
color: #232224;
}
.nt-body-incident-dscr {
display: flex;
align-items: center;
margin-bottom: 5px;
.nt-body-incident-dscr-icon {
width: 30px;
height: 30px;
margin-right: 5px;
background-color: whitesmoke;
border-radius: 100%;
}
}
Babel + JSX
// Local store
class Store {
constructor(name, initialState = {}) {
this.name = name;
this.subscribers = [];
this.state = initialState;
}
subscribe(subscriber) {
this.subscribers.push(subscriber);
}
unsubscribe(subscriber) {
this.subscribers = this.subscribers.filter(item => item !== subscriber);
}
update(state) {
this.state = { ...this.state, ...state };
console.log(this.state);
this.subscribers.map(component => component.setState(this.state));
}
}
// Subscribe component to store with controller
const connect = (component, controller, store) =>
class Container extends React.Component {
constructor() {
super();
if (store) store.subscribe(this);
this.ctrl = controller(
(state) => store
? store.update(state)
: this.setState(state),
() => this.state
);
}
componentDidMount() {
if (store) this.setState(store.state);
}
componentWillUnmount() {
if (store) store.unsubscribe(this);
}
render() {
return React.createElement(component, {...this.state, ...this.props, ctrl: this.ctrl })
}
}
// For changes without React
const Model = (controller, store) =>
controller(
store.update.bind(store),
() => store.state
);
const createMessage = (message, type = 'default') => ({
id: Math.random(),
type: type,
message: `<div>${message}</div>`,
})
const data = Array.from({ length: 5 }, (v, k) => createMessage('message', 'default'))
class NotificationsBox extends React.Component {
constructor(props) {
super(props);
this.CLOSE_BUTTON = '✖';
}
animate(flag) {
const { effect = 'hidden' } = this.props;
return flag
? `nt-animate-${effect}`
: '';
}
render() {
const {
body,
notifications = [],
theme = 'white',
style = {},
onOpen = () => {},
ctrl,
} = this.props;
const {
padding = '10px',
margin = '5px',
width = '300px',
minHeight =...