React
by samur3
HTML
<body>
<div id="notification-box"></div>
<div id="content"></div>
</body>
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.done {
color: rgba(0, 0, 0, 0.3);
text-decoration: line-through;
}
input {
margin-right: 5px;
}
React
define([
"react",
"react-dom",
"prop-types"
], function(
React,
ReactDOM,
PropTypes
) {
"use strict";
const { PureComponent } = React;
const ATTRIBUTE_MAP = Object.freeze({
acceptCharset: "accept-charset",
httpEquiv: "http-equiv"
});
const getAttrName = attr => ATTRIBUTE_MAP[attr] || attr;
const store = {};
const getOrCreateMountNode = (uid, type = "div") => {
if (!store[uid]) {
const mountNode = document.createElement(type);
store[uid] = {
mountNode,
inUse: true
};
} else {
store[uid].inUse = true;
if (store[uid].mountNode.nodeName.toLowerCase() !== type) {
const newNode = document.createElement(type);
ReactDOM.unmountComponentAtNode(store[uid].mountNode);
store[uid].mountNode = newNode;
}
}
return store[uid].mountNode;
};
const calculateChangeSet = (prev = {}, next = {}) => {
const set = [];
const del = Object.entries(prev).reduce((acc, [name, value]) => {
const nextValue = next[name];
if (nextValue === undefined || nextValue === null || nextValue === "") {
return acc.concat(name);
} else if (value !== nextValue) {
set.push([name, value]);
}
return acc;
}, []);
Object.entries(next).forEach(entry => {
const [name, value] = entry;
if (prev.hasOwnProperty(name) || value === undefined || value === null || value === "") {
// Already handled or invalid
return;
}
set.push(entry);
});
return {
del,
set
};
};
const updateNodeStyle = (
node,
prevClassName,
nextClassName,
prevStyle,
nextStyle,
...