UNPKG

@telekom/scale-components

Version:

Scale is the digital design system for Telekom products and experiences.

113 lines (110 loc) 3.59 kB
'use strict'; /** * @license * Scale https://github.com/telekom/scale * * Copyright (c) 2021 Egor Kirpichev and contributors, Deutsche Telekom AG * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ const hasShadowDom = (el) => { return !!el.shadowRoot && !!el.attachShadow; }; // eg isPseudoClassSupported(':focus-visible') // true for chrome, false for safari const isPseudoClassSupported = (pseudoClass) => { // Get the document stylesheet1 let ss = document.styleSheets[0]; // Create a stylesheet if one doesn't exist if (!ss) { const el = document.createElement('style'); document.head.appendChild(el); ss = document.styleSheets[0]; document.head.removeChild(el); } // Test the pseudo-class by trying to style with it function testPseudo() { try { if (!/^:/.test(pseudoClass)) { pseudoClass = ':' + pseudoClass; } ss.insertRule('html' + pseudoClass + '{}', 0); ss.deleteRule(0); return true; } catch (e) { return false; } } // Run the test return testPseudo(); }; /** * Call `emit` on component events twice. * One for the legacy camel-cased event, one for the new kebab-cased. * e.g. for the event `scaleChange` it will do `instance.scaleChange.emit()` and `instance.scaleChangeLegacy.emit()`. * It expects both `scaleChange` and `scaleChangeLegacy` event-decorated properties to exist on the component. * * @param instance {ComponentInterface} - The component instance, aka `this` * @param eventKey {string} - The event property, e.g. `scaleChange` * @param detail {any} - The custom event `detail` * @returns {CustomEvent[]} - The events emitted */ function emitEvent(instance, eventKey, detail) { const legacyKey = eventKey + 'Legacy'; const emitted = []; if (typeof instance[legacyKey] !== 'undefined') { // Emit legacy camel case event, e.g. `scaleClose` emitted.push(instance[legacyKey].emit(detail)); } // Emit now-standard kebab-case event, e.g. `scale-close` emitted.push(instance[eventKey].emit(detail)); // Return both return emitted; } function isClickOutside(event, host) { let target = event.target; const hasShadow = target.shadowRoot != null; const composedPath = hasShadow ? event.composedPath() : []; do { if (target === host) { return false; } if (hasShadow) { // @ts-ignore target = composedPath.shift(); } else { target = target.parentNode; } } while (target); return true; } const isScaleIcon = (el) => { if (el == null || el.nodeType !== 1) { return false; } return el.nodeName.toUpperCase().substring(0, 10) === 'SCALE-ICON'; }; /** Creating global ids for different component helper-texts */ let id = 0; function generateUniqueId() { return id++; } /** * Useful for waiting for animations to finish before doing something. * * @param el {HTMLElement | ShadowRoot} - The element to call `getAnimations` on * @returns {Promise} - Resolves when all animations are finished */ const animationsFinished = (el) => { return Promise.all(el.getAnimations({ subtree: true }).map((x) => x.finished)); }; exports.animationsFinished = animationsFinished; exports.emitEvent = emitEvent; exports.generateUniqueId = generateUniqueId; exports.hasShadowDom = hasShadowDom; exports.isClickOutside = isClickOutside; exports.isPseudoClassSupported = isPseudoClassSupported; exports.isScaleIcon = isScaleIcon;