(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.lumino_domutils = {}));
}(this, (function (exports) { 'use strict';

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2019, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * The namespace for clipboard related functionality.
     */
    exports.ClipboardExt = void 0;
    (function (ClipboardExt) {
        /**
         * Copy text to the system clipboard.
         *
         * @param text - The text to copy to the clipboard.
         */
        function copyText(text) {
            // Fetch the document body.
            var body = document.body;
            // Set up the clipboard event listener.
            var handler = function (event) {
                // Stop the event propagation.
                event.preventDefault();
                event.stopPropagation();
                // Set the clipboard data.
                event.clipboardData.setData('text', text);
                // Remove the event listener.
                body.removeEventListener('copy', handler, true);
            };
            // Add the event listener.
            body.addEventListener('copy', handler, true);
            // Trigger the event.
            document.execCommand('copy');
        }
        ClipboardExt.copyText = copyText;
    })(exports.ClipboardExt || (exports.ClipboardExt = {}));

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * The namespace for element related utilities.
     */
    exports.ElementExt = void 0;
    (function (ElementExt) {
        /**
         * Compute the box sizing for an element.
         *
         * @param element - The element of interest.
         *
         * @returns The box sizing data for the specified element.
         */
        function boxSizing(element) {
            var style = window.getComputedStyle(element);
            var bt = parseFloat(style.borderTopWidth) || 0;
            var bl = parseFloat(style.borderLeftWidth) || 0;
            var br = parseFloat(style.borderRightWidth) || 0;
            var bb = parseFloat(style.borderBottomWidth) || 0;
            var pt = parseFloat(style.paddingTop) || 0;
            var pl = parseFloat(style.paddingLeft) || 0;
            var pr = parseFloat(style.paddingRight) || 0;
            var pb = parseFloat(style.paddingBottom) || 0;
            var hs = bl + pl + pr + br;
            var vs = bt + pt + pb + bb;
            return {
                borderTop: bt,
                borderLeft: bl,
                borderRight: br,
                borderBottom: bb,
                paddingTop: pt,
                paddingLeft: pl,
                paddingRight: pr,
                paddingBottom: pb,
                horizontalSum: hs,
                verticalSum: vs
            };
        }
        ElementExt.boxSizing = boxSizing;
        /**
         * Compute the size limits for an element.
         *
         * @param element - The element of interest.
         *
         * @returns The size limit data for the specified element.
         */
        function sizeLimits(element) {
            var style = window.getComputedStyle(element);
            var minWidth = parseFloat(style.minWidth) || 0;
            var minHeight = parseFloat(style.minHeight) || 0;
            var maxWidth = parseFloat(style.maxWidth) || Infinity;
            var maxHeight = parseFloat(style.maxHeight) || Infinity;
            maxWidth = Math.max(minWidth, maxWidth);
            maxHeight = Math.max(minHeight, maxHeight);
            return { minWidth: minWidth, minHeight: minHeight, maxWidth: maxWidth, maxHeight: maxHeight };
        }
        ElementExt.sizeLimits = sizeLimits;
        /**
         * Test whether a client position lies within an element.
         *
         * @param element - The DOM element of interest.
         *
         * @param clientX - The client X coordinate of interest.
         *
         * @param clientY - The client Y coordinate of interest.
         *
         * @returns Whether the point is within the given element.
         */
        function hitTest(element, clientX, clientY) {
            var rect = element.getBoundingClientRect();
            return (clientX >= rect.left &&
                clientX < rect.right &&
                clientY >= rect.top &&
                clientY < rect.bottom);
        }
        ElementExt.hitTest = hitTest;
        /**
         * Vertically scroll an element into view if needed.
         *
         * @param area - The scroll area element.
         *
         * @param element - The element of interest.
         *
         * #### Notes
         * This follows the "nearest" behavior of the native `scrollIntoView`
         * method, which is not supported by all browsers.
         * https://drafts.csswg.org/cssom-view/#element-scrolling-members
         *
         * If the element fully covers the visible area or is fully contained
         * within the visible area, no scrolling will take place. Otherwise,
         * the nearest edges of the area and element are aligned.
         */
        function scrollIntoViewIfNeeded(area, element) {
            var ar = area.getBoundingClientRect();
            var er = element.getBoundingClientRect();
            if (er.top <= ar.top && er.bottom >= ar.bottom) {
                return;
            }
            if (er.top < ar.top && er.height <= ar.height) {
                area.scrollTop -= ar.top - er.top;
                return;
            }
            if (er.bottom > ar.bottom && er.height >= ar.height) {
                area.scrollTop -= ar.top - er.top;
                return;
            }
            if (er.top < ar.top && er.height > ar.height) {
                area.scrollTop -= ar.bottom - er.bottom;
                return;
            }
            if (er.bottom > ar.bottom && er.height < ar.height) {
                area.scrollTop -= ar.bottom - er.bottom;
                return;
            }
        }
        ElementExt.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded;
    })(exports.ElementExt || (exports.ElementExt = {}));

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * The namespace for platform related utilities.
     */
    exports.Platform = void 0;
    (function (Platform) {
        /**
         * A flag indicating whether the platform is Mac.
         */
        Platform.IS_MAC = !!navigator.platform.match(/Mac/i);
        /**
         * A flag indicating whether the platform is Windows.
         */
        Platform.IS_WIN = !!navigator.platform.match(/Win/i);
        /**
         * A flag indicating whether the browser is IE.
         */
        Platform.IS_IE = /Trident/.test(navigator.userAgent);
        /**
         * A flag indicating whether the browser is Edge.
         */
        Platform.IS_EDGE = /Edge/.test(navigator.userAgent);
        /**
         * Test whether the `accel` key is pressed.
         *
         * @param event - The keyboard or mouse event of interest.
         *
         * @returns Whether the `accel` key is pressed.
         *
         * #### Notes
         * On Mac the `accel` key is the command key. On all other
         * platforms the `accel` key is the control key.
         */
        function accelKey(event) {
            return Platform.IS_MAC ? event.metaKey : event.ctrlKey;
        }
        Platform.accelKey = accelKey;
    })(exports.Platform || (exports.Platform = {}));

    // Copyright (c) Jupyter Development Team.
    // Distributed under the terms of the Modified BSD License.
    /*-----------------------------------------------------------------------------
    | Copyright (c) 2014-2017, PhosphorJS Contributors
    |
    | Distributed under the terms of the BSD 3-Clause License.
    |
    | The full license is in the file LICENSE, distributed with this software.
    |----------------------------------------------------------------------------*/
    /**
     * The namespace for selector related utilities.
     */
    exports.Selector = void 0;
    (function (Selector) {
        /**
         * Calculate the specificity of a single CSS selector.
         *
         * @param selector - The CSS selector of interest.
         *
         * @returns The specificity of the selector.
         *
         * #### Undefined Behavior
         * The selector is invalid.
         *
         * #### Notes
         * This is based on https://www.w3.org/TR/css3-selectors/#specificity
         *
         * A larger number represents a more specific selector.
         *
         * The smallest possible specificity is `0`.
         *
         * The result is represented as a hex number `0x<aa><bb><cc>` where
         * each component is the count of the respective selector clause.
         *
         * If the selector contains commas, only the first clause is used.
         *
         * The computed result is cached, so subsequent calculations for the
         * same selector are extremely fast.
         */
        function calculateSpecificity(selector) {
            if (selector in Private.specificityCache) {
                return Private.specificityCache[selector];
            }
            var result = Private.calculateSingle(selector);
            return (Private.specificityCache[selector] = result);
        }
        Selector.calculateSpecificity = calculateSpecificity;
        /**
         * Test whether a selector is a valid CSS selector.
         *
         * @param selector - The CSS selector of interest.
         *
         * @returns `true` if the selector is valid, `false` otherwise.
         *
         * #### Notes
         * The computed result is cached, so subsequent tests for the same
         * selector are extremely fast.
         */
        function isValid(selector) {
            if (selector in Private.validityCache) {
                return Private.validityCache[selector];
            }
            var result = true;
            try {
                Private.testElem.querySelector(selector);
            }
            catch (err) {
                result = false;
            }
            return (Private.validityCache[selector] = result);
        }
        Selector.isValid = isValid;
        /**
         * Test whether an element matches a CSS selector.
         *
         * @param element - The element of interest.
         *
         * @param selector - The valid CSS selector of interest.
         *
         * @returns `true` if the element is a match, `false` otherwise.
         *
         * #### Notes
         * This function uses the builtin browser capabilities when possible,
         * falling back onto a document query otherwise.
         */
        function matches(element, selector) {
            return Private.protoMatchFunc.call(element, selector);
        }
        Selector.matches = matches;
    })(exports.Selector || (exports.Selector = {}));
    /**
     * The namespace for the module implementation details.
     */
    var Private;
    (function (Private) {
        /**
         * A cache of computed selector specificity values.
         */
        Private.specificityCache = Object.create(null);
        /**
         * A cache of computed selector validity.
         */
        Private.validityCache = Object.create(null);
        /**
         * An empty element for testing selector validity.
         */
        Private.testElem = document.createElement('div');
        /**
         * A cross-browser CSS selector matching prototype function.
         */
        Private.protoMatchFunc = (function () {
            var proto = Element.prototype;
            return (proto.matches ||
                proto.matchesSelector ||
                proto.mozMatchesSelector ||
                proto.msMatchesSelector ||
                proto.oMatchesSelector ||
                proto.webkitMatchesSelector ||
                function (selector) {
                    var elem = this;
                    var matches = elem.ownerDocument
                        ? elem.ownerDocument.querySelectorAll(selector)
                        : [];
                    return Array.prototype.indexOf.call(matches, elem) !== -1;
                });
        })();
        /**
         * Calculate the specificity of a single selector.
         *
         * The behavior is undefined if the selector is invalid.
         */
        function calculateSingle(selector) {
            // Ignore anything after the first comma.
            selector = selector.split(',', 1)[0];
            // Setup the aggregate counters.
            var a = 0;
            var b = 0;
            var c = 0;
            // Apply a regex to the front of the selector. If it succeeds, that
            // portion of the selector is removed. Returns a success/fail flag.
            function match(re) {
                var match = selector.match(re);
                if (match === null) {
                    return false;
                }
                selector = selector.slice(match[0].length);
                return true;
            }
            // Replace the negation pseudo-class (which is ignored),
            // but keep its inner content (which is not ignored).
            selector = selector.replace(NEGATION_RE, ' $1 ');
            // Continue matching until the selector is consumed.
            while (selector.length > 0) {
                // Match an ID selector.
                if (match(ID_RE)) {
                    a++;
                    continue;
                }
                // Match a class selector.
                if (match(CLASS_RE)) {
                    b++;
                    continue;
                }
                // Match an attribute selector.
                if (match(ATTR_RE)) {
                    b++;
                    continue;
                }
                // Match a pseudo-element selector. This is done before matching
                // a pseudo-class since this regex overlaps with that regex.
                if (match(PSEUDO_ELEM_RE)) {
                    c++;
                    continue;
                }
                // Match a pseudo-class selector.
                if (match(PSEDUO_CLASS_RE)) {
                    b++;
                    continue;
                }
                // Match a plain type selector.
                if (match(TYPE_RE)) {
                    c++;
                    continue;
                }
                // Finally, match any ignored characters.
                if (match(IGNORE_RE)) {
                    continue;
                }
                // At this point, the selector is assumed to be invalid.
                return 0;
            }
            // Clamp each component to a reasonable base.
            a = Math.min(a, 0xff);
            b = Math.min(b, 0xff);
            c = Math.min(c, 0xff);
            // Combine the components into a single result.
            return (a << 16) | (b << 8) | c;
        }
        Private.calculateSingle = calculateSingle;
        /**
         * A regex which matches an ID selector at string start.
         */
        var ID_RE = /^#[^\s\+>~#\.\[:]+/;
        /**
         * A regex which matches a class selector at string start.
         */
        var CLASS_RE = /^\.[^\s\+>~#\.\[:]+/;
        /**
         * A regex which matches an attribute selector at string start.
         */
        var ATTR_RE = /^\[[^\]]+\]/;
        /**
         * A regex which matches a type selector at string start.
         */
        var TYPE_RE = /^[^\s\+>~#\.\[:]+/;
        /**
         * A regex which matches a pseudo-element selector at string start.
         */
        var PSEUDO_ELEM_RE = /^(::[^\s\+>~#\.\[:]+|:first-line|:first-letter|:before|:after)/;
        /**
         * A regex which matches a pseudo-class selector at string start.
         */
        var PSEDUO_CLASS_RE = /^:[^\s\+>~#\.\[:]+/;
        /**
         * A regex which matches ignored characters at string start.
         */
        var IGNORE_RE = /^[\s\+>~\*]+/;
        /**
         * A regex which matches the negation pseudo-class globally.
         */
        var NEGATION_RE = /:not\(([^\)]+)\)/g;
    })(Private || (Private = {}));

    Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=index.js.map
