@servicenow/ui-renderer-snabbdom
Version:
Snabbdom renderer for UI Framework on Next Experience
145 lines (121 loc) • 6.78 kB
JavaScript
/**
* Copyright (c) 2020 ServiceNow, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = onStateChange;
var _uiMetrics = require("@servicenow/ui-metrics");
var _uiInternal = require("@servicenow/ui-internal");
var _utils = require("./utils");
var _symbols = require("./symbols");
var _createElementFromNode = _interopRequireDefault(require("./createElementFromNode"));
var _log = _interopRequireDefault(require("./log"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
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; }
var noop = function noop() {
return null;
};
var helperNoop = Object.assign(noop, {
dispatch: noop,
updateState: noop,
updateProperties: noop
});
/**
* Renders a view using Snabbdom
* @method render
* @param {HTMLElement} element Element to append rendered view to
* @param {Function} handler Render function
* @param {Object} [props = {}] Optional properties object
* @param {Object } [helpers] Optional object containing helpful functions, such as dispatch, updateState, and updateProperties
* @param {Function} [helpers.dispatch] Optional function for dispatching actions
* @param {Function} [helpers.updateState] Optional function for updating component state
* @param {Function} [helpers.updateProperties] Optional function for updating component properties
* @param {String} [interactionId] Optional identifier used by ui-metrics for instrumentation
* @returns {VNode}
*/
function onStateChange(element, handler) {
var props = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var helpers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : helperNoop;
var interactionId = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : (0, _uiMetrics.createInteractionId)();
// The renderer is sometimes used to render DOM to native elements, typically in test fixtures
// or example code. Since we're not in a shadowRoot, we're not in a framework element, we
// shouldn't mark as context is not complete, e.g. componentId, componentName, etc are missing
// from `element.host`.
var isShadowRoot = element instanceof ShadowRoot;
try {
var result = handler(props, helpers);
var prev = element[_symbols.VNODE] || (0, _createElementFromNode["default"])(element);
var styles = [];
var children = prev.children;
var childrenCount = children.length;
for (var i = 0; i < childrenCount; i++) {
var child = children[i];
if (child && typeof child.sel === 'string' && (child.sel.startsWith('style') || child.sel.startsWith('link'))) styles.push(child);
}
var next = _objectSpread(_objectSpread({}, prev), {}, {
children: [].concat(result, styles)
});
var _element$host = element.host,
host = _element$host === void 0 ? {} : _element$host;
host[_symbols.INTERACTION_ID] = interactionId; // eslint-disable-line no-param-reassign
if (isShadowRoot) (0, _uiMetrics.mark)(host, interactionId, _uiMetrics.types.PATCH_START, {
location: _uiInternal.locations.VIEW
});
var vnode = (0, _utils.patch)(prev, next);
if (isShadowRoot) (0, _uiMetrics.mark)(host, interactionId, _uiMetrics.types.PATCH_END, {
location: _uiInternal.locations.VIEW
});
element[_symbols.VNODE] = vnode; // eslint-disable-line no-param-reassign
delete host[_symbols.INTERACTION_ID]; // eslint-disable-line no-param-reassign
return vnode;
} catch (e) {
var _element$host2 = element.host,
_host = _element$host2 === void 0 ? {} : _element$host2;
var metadata = (0, _uiMetrics.setInteractionId)({
internal: true
}, interactionId);
if (isShadowRoot) (0, _uiMetrics.mark)(_host, interactionId, _uiMetrics.types.ERROR, {
location: _uiInternal.locations.VIEW
});
helpers.dispatch(_uiInternal.errorTypes.COMPONENT_ERROR_THROWN, {
host: _host,
location: _uiInternal.locations.VIEW,
error: e,
details: {
boundaryError: true
}
}, metadata, true);
var tagName = (0, _uiInternal.toLower)(_host.tagName);
var componentId = _host.getAttribute('component-id');
(0, _log["default"])("An Error occurred in <".concat(tagName, " component-id=\"").concat(componentId, "\"/>. COMPONENT_ERROR_THROWN action type is dispatched with error details."), {
error: e,
level: _uiInternal.allLogTypes.ERROR,
host: _host,
origin: 'onStateChange'
});
return (0, _createElementFromNode["default"])(element);
}
}
//# sourceMappingURL=onStateChange.js.map