react-transclusion
Version:
Render arbitrary components into outlets for use in dynamic layouts.
95 lines (76 loc) • 2.56 kB
JavaScript
;
var invariant = require('invariant');
/**
* This is the underlying module that allows you to register elements for
* [[Outlet | outlets]] and define them.
*/
module.exports = function OutletManager() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var exports = {};
var outlets = {};
var strict = config.strict !== false;
/**
* Define a new outlet in the layout. An outlet must be defined through this
* API before attempting to inject into it or even render it.
*
* @param {String} name
* The outlet name.
*
* @throws {InvariantError}
* If a similar outlet with this name had already been defined.
*/
exports.define = function (name) {
invariant(!getOutletByName(name), 'Outlet ' + name + ' has already been defined.');
if (process.env.NODE_ENV !== 'production' && config.verbose) {
console.log('Outlet defined: "%s"', name);
}
outlets[name] = [];
};
/**
* Register an element to be rendered inside an [Outlet outlet]().
*
* @param {String} name
* The outlet ID.
*
* @param {Object} element
* A description of the element.
*
* @param {String} element.key
* **REQUIRED** - a unique identifier for the component (within that
* outlet.)
*
* @param {React.Class} element.component
* **REQUIRED** - the component to render inside the outlet.
*/
exports.add = function (name, element) {
var outlet = getOutletByName(name);
if (!outlet) {
if (strict) {
invariant(false, 'Unknown outlet "' + name + '".');
}
exports.define(name);
return exports.add(name, element);
}
var key = element.key || element.component && (element.component.displayName || element.component.constructor.name);
invariant(typeof key === 'string', 'Missing @key for outlet occupant of "' + name + '"');
invariant(typeof element.component === 'function', "You must specify a React.Class as @component for the outlet component.");
outlet.push(Object.assign({}, element, { key: key }));
};
exports.getElements = function (name) {
return getOutletByName(name) || [];
};
exports.isDefined = function (name) {
return !!getOutletByName(name);
};
exports.reset = function (name) {
if (name) {
outlets[name] = null;
} else {
Object.keys(outlets).forEach(exports.reset);
}
};
return exports;
function getOutletByName(name) {
return outlets[name];
}
};