UNPKG

@servicenow/ui-renderer-snabbdom

Version:

Snabbdom renderer for UI Framework on Next Experience

145 lines (121 loc) 6.78 kB
/** * 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. */ "use strict"; 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