Skip to content

Instantly share code, notes, and snippets.

@matthewrobb
Last active December 18, 2015 15:50
Show Gist options
  • Save matthewrobb/7b24f9d4affb04be7e9c to your computer and use it in GitHub Desktop.
Save matthewrobb/7b24f9d4affb04be7e9c to your computer and use it in GitHub Desktop.
const Shade = Shades;
const { Content, Slot } = Shades;
function PageFooter(props) {
return (
<footer>
{props.children}
</footer>
);
}
function PageHeader(props) {
return (
<Shade lightTree={props.children}>
<header>
<Slot name="title">
<h1 className="header"></h1>
</Slot>
<Slot name="subtitle">
<span className="subtitle"></span>
</Slot>
</header>
</Shade>
);
}
function PageBody(props) {
return (
<div className="body">
{props.children}
</div>
);
}
function Page({ children }) {
return (
<Shade lightTree={children}>
<div className="page">
<Slot name="header">
<PageHeader />
</Slot>
<Slot name="body">
<PageBody />
</Slot>
<Slot name="footer">
<PageFooter />
</Slot>
</div>
</Shade>
);
}
function ThingList(props) {
return (
<Shade lightTree={props.children}>
<Slot name="thing">
<ul>
<li></li>
</ul>
</Slot>
</Shade>
);
}
function MyPage() {
var things = [
{ label: 'cup' },
{ label: 'lamp' },
{ label: 'shotgun' }
];
return (
<Page className="my-page">
<Content slot="header">
<Content slot="title">My Page</Content>
<Content slot="subtitle">The coolest</Content>
</Content>
<Content slot="body">
<ThingList>
{things.map(thing => (
<Content slot="thing">
{thing.label}
</Content>
))}
</ThingList>
</Content>
<Content slot="footer">
Footies!
</Content>
</Page>
);
}
React.render(<MyPage/>, document.getElementById('root'));
/*
*
* ReactShades
*
*/
var Shades = (function(){
"use strict";
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
var PureRenderMixin = React.addons.PureRenderMixin;
function Slot(props, context) {
var contents = context.lightTree[props.name];
if (!contents) return React.createElement("span", null);
var root = React.Children.only(props.children || React.createElement("span", null));
var inner = root && root.props.children;
var children = [];
var rootProps = {};
contents.forEach(function (content) {
var _content$props = content.props;
var lightTree = _content$props.children;
var slot = _content$props.slot;
var props = _objectWithoutProperties(_content$props, ["children", "slot"]);
var child = lightTree || React.createElement("span", null);
if (inner) {
child = React.cloneElement(inner, props, lightTree);
} else {
rootProps = props;
}
children.push(child);
});
return React.cloneElement(root, rootProps, children);
}
Slot.contextTypes = {
lightTree: React.PropTypes.object
};
function Content(props) {
return React.createElement(
"div",
null,
props.children
);
}
var Shade = React.createClass({
displayName: "Shade",
mixins: [PureRenderMixin],
statics: {
Content: Content,
Slot: Slot,
visit: function visit(nodes, visitor) {
React.Children.forEach(nodes, function (node, idx) {
if (visitor(node) !== false) {
Shade.visit(node.props.children, visitor);
}
});
}
},
childContextTypes: {
lightTree: React.PropTypes.object
},
getChildContext: function getChildContext() {
var slots = {};
Shade.visit(this.props.lightTree, function (child) {
if (child.type === Shade || child.type === Slot) {
return false;
} else if (!child.props.slot) {
return;
}
(slots[child.props.slot] || (slots[child.props.slot] = [])).push(child);
return false;
});
return {
lightTree: slots
};
},
render: function render() {
return React.Children.only(this.props.children);
}
});
return Shade;
})(React);
/*
*
* ReactShades
*
*/
var Shade = (function(React){
const {PureRenderMixin} = React.addons;
function Slot(props, context) {
const contents = context.lightTree[props.name];
if (!contents) return <span></span>;
const root = React.Children.only(props.children || <span></span>);
const inner = root && root.props.children;
var children = [];
var rootProps = {};
contents.forEach(content => {
const { children: lightTree, slot, ...props } = content.props;
var child = lightTree || <span></span>;
if (inner) {
child = React.cloneElement(inner, props, lightTree);
} else {
rootProps = props;
}
children.push(child);
});
return React.cloneElement(root, rootProps, children);
}
Slot.contextTypes = {
lightTree: React.PropTypes.object
};
function Content(props) {
return <div>{props.children}</div>;
}
const Shade = React.createClass({
mixins: [ PureRenderMixin ],
statics: {
Content,
Slot,
visit(nodes, visitor) {
React.Children.forEach(nodes, function(node, idx) {
if(visitor(node) !== false) {
Shade.visit(node.props.children, visitor);
}
});
}
},
childContextTypes: {
lightTree: React.PropTypes.object
},
getChildContext() {
var slots = {};
Shade.visit(this.props.lightTree, (child)=> {
if (child.type === Shade || child.type === Slot) {
return false;
} else if (!child.props.slot) {
return;
}
(slots[child.props.slot] || (slots[child.props.slot] = [])).push(child);
return false;
});
return {
lightTree: slots
};
},
render() {
return React.Children.only(this.props.children);
}
});
return Shade;
})(React);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment