@roderickhsiao/react-i13n
Version:
[Experiment] React I13n provides a performant and scalable solution to application instrumentation.
241 lines (200 loc) • 8.19 kB
JavaScript
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
* Copyright 2015 - Present, Yahoo Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
import { IS_CLIENT, ENVIRONMENT } from '../utils/variables';
import EventsQueue from '../libs/EventsQueue';
import I13nNode from './I13nNode';
import warnAndPrintTrace from '../utils/warnAndPrintTrace';
var debugLib = require('debug');
var debug = debugLib('ReactI13n');
var DEFAULT_HANDLER_TIMEOUT = 1000; // export the debug lib in client side
if (IS_CLIENT) {
window.debugLib = debugLib;
}
var _reactI13nInstance = null;
/**
* ReactI13n Library to build a tree for instrumentation
* @class ReactI13n
* @param {Object} options options object
* @param {Boolean} options.isViewportEnabled if enable viewport checking
* @param {Object} options.rootModelData model data of root i13n node
* @param {Object} options.i13nNodeClass the i13nNode class, you can inherit it with your own functionalities
* @param {String} options.scrollableContainerId id of the scrollable element that your components
* reside within. Normally, you won't need to provide a value for this. This is only to
* support viewport checking when your components are contained within a scrollable element.
* Currently, only elements that fill the viewport are supported.
* @constructor
*/
class ReactI13n {
constructor() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_defineProperty(this, "execute", (eventName, payload, callback) => {
payload = Object.assign({}, payload);
payload.env = ENVIRONMENT;
payload.i13nNode = payload.i13nNode || this.getRootI13nNode();
var promiseHandlers = this.getEventHandlers(eventName, payload);
if (promiseHandlers && promiseHandlers.length > 0) {
var handlerTimeout;
promiseHandlers.push(new Promise(resolve => {
handlerTimeout = setTimeout(() => {
debug("handler timeout in ".concat(this._handlerTimeout, "ms."));
resolve();
}, this._handlerTimeout);
})); // promised execute all handlers if plugins and then call callback function
Promise.race(promiseHandlers).then(() => {
clearTimeout(handlerTimeout);
callback === null || callback === void 0 ? void 0 : callback();
}, e => {
clearTimeout(handlerTimeout);
debug('execute event failed', e);
callback === null || callback === void 0 ? void 0 : callback();
});
} else {
// if there's no handlers, execute callback directly
callback === null || callback === void 0 ? void 0 : callback();
}
});
_defineProperty(this, "getEventHandlers", (eventName, payload) => {
var promiseHandlers = [];
if (this._plugins) {
Object.entries(this._plugins).forEach((_ref) => {
var [pluginName, plugin] = _ref;
var eventsQueue = this._eventsQueues[pluginName];
var eventHandler = plugin && plugin.eventHandlers && plugin.eventHandlers[eventName];
if (eventHandler) {
promiseHandlers.push(new Promise((resolve, reject) => {
var _eventsQueue$executeE;
(_eventsQueue$executeE = eventsQueue.executeEvent) === null || _eventsQueue$executeE === void 0 ? void 0 : _eventsQueue$executeE.call(eventsQueue, eventName, payload, resolve, reject);
}));
}
});
}
return promiseHandlers;
});
debug('init', options);
this._eventsQueues = {};
this._plugins = {};
this._rootModelData = options.rootModelData || {};
this._handlerTimeout = options.handlerTimeout || DEFAULT_HANDLER_TIMEOUT;
this._i13nNodeClass = typeof options.i13nNodeClass === 'function' ? options.i13nNodeClass : I13nNode;
this._isViewportEnabled = options.isViewportEnabled || false;
this._scrollableContainerId = options.scrollableContainerId;
this._i13nInstance = null;
}
get i13nInstance() {
return this._i13nInstance;
}
set i13nInstance(instance) {
_reactI13nInstance = instance;
this._i13nInstance = instance;
}
/**
* Create root node and set to the global object
* @method createRootI13nNode
*/
createRootI13nNode() {
var I13nNodeClass = this.getI13nNodeClass();
this._rootI13nNode = new I13nNodeClass(null, this._rootModelData, false);
if (IS_CLIENT) {
this._rootI13nNode.setDOMNode(document.body);
}
return this._rootI13nNode;
}
/**
* Execute handlers asynchronously
* @method execute
* @param {String} eventName
* @param {Object} payload payload object
* @param {Function} callback callback function when all handlers are executed
* @async
*/
/**
* Setup plugins
* @method plug
* @param {Object} plugin the plugin object
*/
plug(plugin) {
if (!plugin) {
return;
}
debug('setup plugin', plugin);
this._plugins[plugin.name] = plugin;
this._eventsQueues[plugin.name] = new EventsQueue(plugin);
}
/**
* Get handlers from all plugin by event name
* @method getEventHandlers
* @param {String} eventName event name
* @param {Object} payload payload object
* @return {Array} the promise handlers
*/
/**
* Get I13n node class
* @method getI13nNodeClass
* @return {Object} I13nNode class
*/
getI13nNodeClass() {
return this._i13nNodeClass;
}
/**
* Get isViewportEnabled value
* @method isViewportEnabled
* @return {Object} isViewportEnabled value
*/
isViewportEnabled() {
return this._isViewportEnabled;
}
/**
* Get scrollableContainerId value
* @method getScrollableContainerId
* @return {String} scrollableContainerId value
*/
getScrollableContainerId() {
return this._scrollableContainerId;
}
/**
* Get scrollable container DOM node
* @method getScrollableContainerDOMNode
* @return {Object} scrollable container DOM node. This will be undefined if no
* scrollableContainerId was set, or null if the element was not found in the DOM.
*/
getScrollableContainerDOMNode() {
if (this._scrollableContainerId) {
var _document;
return (_document = document) === null || _document === void 0 ? void 0 : _document.getElementById(this._scrollableContainerId);
}
}
/**
* Get root i13n node
* @method getRootI13nNode
* @return {Object} root react i13n node
*/
getRootI13nNode() {
return this._rootI13nNode;
}
/**
* Update ReactI13n options
* @method updateOptions
* @param {Object} options
*/
updateOptions() {
var _options$isViewportEn, _options$rootModelDat, _options$handlerTimeo, _options$scrollableCo;
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
debug('updated', options);
this._i13nNodeClass = typeof options.i13nNodeClass === 'function' ? options.i13nNodeClass : this._i13nNodeClass;
this._isViewportEnabled = (_options$isViewportEn = options.isViewportEnabled) !== null && _options$isViewportEn !== void 0 ? _options$isViewportEn : this._isViewportEnabled;
this._rootModelData = (_options$rootModelDat = options.rootModelData) !== null && _options$rootModelDat !== void 0 ? _options$rootModelDat : this._rootModelData;
this._handlerTimeout = (_options$handlerTimeo = options.handlerTimeout) !== null && _options$handlerTimeo !== void 0 ? _options$handlerTimeo : this._handlerTimeout;
this._scrollableContainerId = (_options$scrollableCo = options.scrollableContainerId) !== null && _options$scrollableCo !== void 0 ? _options$scrollableCo : this._scrollableContainerId;
}
}
export var getInstance = () => {
if (IS_CLIENT) {
return _reactI13nInstance;
}
warnAndPrintTrace('ReactI13n instance is not avaialble on server side with getInstance, ' + 'please use this.props.i13n or React context to access ReactI13n utils');
return null;
};
export default ReactI13n;