[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/dist/ -> dom.js (source)

   1  /******/ (() => { // webpackBootstrap
   2  /******/     "use strict";
   3  /******/     // The require scope
   4  /******/     var __webpack_require__ = {};
   5  /******/     
   6  /************************************************************************/
   7  /******/     /* webpack/runtime/compat get default export */
   8  /******/     (() => {
   9  /******/         // getDefaultExport function for compatibility with non-harmony modules
  10  /******/         __webpack_require__.n = (module) => {
  11  /******/             var getter = module && module.__esModule ?
  12  /******/                 () => (module['default']) :
  13  /******/                 () => (module);
  14  /******/             __webpack_require__.d(getter, { a: getter });
  15  /******/             return getter;
  16  /******/         };
  17  /******/     })();
  18  /******/     
  19  /******/     /* webpack/runtime/define property getters */
  20  /******/     (() => {
  21  /******/         // define getter functions for harmony exports
  22  /******/         __webpack_require__.d = (exports, definition) => {
  23  /******/             for(var key in definition) {
  24  /******/                 if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  25  /******/                     Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  26  /******/                 }
  27  /******/             }
  28  /******/         };
  29  /******/     })();
  30  /******/     
  31  /******/     /* webpack/runtime/hasOwnProperty shorthand */
  32  /******/     (() => {
  33  /******/         __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  34  /******/     })();
  35  /******/     
  36  /******/     /* webpack/runtime/make namespace object */
  37  /******/     (() => {
  38  /******/         // define __esModule on exports
  39  /******/         __webpack_require__.r = (exports) => {
  40  /******/             if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  41  /******/                 Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  42  /******/             }
  43  /******/             Object.defineProperty(exports, '__esModule', { value: true });
  44  /******/         };
  45  /******/     })();
  46  /******/     
  47  /************************************************************************/
  48  var __webpack_exports__ = {};
  49  // ESM COMPAT FLAG
  50  __webpack_require__.r(__webpack_exports__);
  51  
  52  // EXPORTS
  53  __webpack_require__.d(__webpack_exports__, {
  54    __unstableStripHTML: () => (/* reexport */ stripHTML),
  55    computeCaretRect: () => (/* reexport */ computeCaretRect),
  56    documentHasSelection: () => (/* reexport */ documentHasSelection),
  57    documentHasTextSelection: () => (/* reexport */ documentHasTextSelection),
  58    documentHasUncollapsedSelection: () => (/* reexport */ documentHasUncollapsedSelection),
  59    focus: () => (/* binding */ build_module_focus),
  60    getFilesFromDataTransfer: () => (/* reexport */ getFilesFromDataTransfer),
  61    getOffsetParent: () => (/* reexport */ getOffsetParent),
  62    getPhrasingContentSchema: () => (/* reexport */ getPhrasingContentSchema),
  63    getRectangleFromRange: () => (/* reexport */ getRectangleFromRange),
  64    getScrollContainer: () => (/* reexport */ getScrollContainer),
  65    insertAfter: () => (/* reexport */ insertAfter),
  66    isEmpty: () => (/* reexport */ isEmpty),
  67    isEntirelySelected: () => (/* reexport */ isEntirelySelected),
  68    isFormElement: () => (/* reexport */ isFormElement),
  69    isHorizontalEdge: () => (/* reexport */ isHorizontalEdge),
  70    isNumberInput: () => (/* reexport */ isNumberInput),
  71    isPhrasingContent: () => (/* reexport */ isPhrasingContent),
  72    isRTL: () => (/* reexport */ isRTL),
  73    isTextContent: () => (/* reexport */ isTextContent),
  74    isTextField: () => (/* reexport */ isTextField),
  75    isVerticalEdge: () => (/* reexport */ isVerticalEdge),
  76    placeCaretAtHorizontalEdge: () => (/* reexport */ placeCaretAtHorizontalEdge),
  77    placeCaretAtVerticalEdge: () => (/* reexport */ placeCaretAtVerticalEdge),
  78    remove: () => (/* reexport */ remove),
  79    removeInvalidHTML: () => (/* reexport */ removeInvalidHTML),
  80    replace: () => (/* reexport */ replace),
  81    replaceTag: () => (/* reexport */ replaceTag),
  82    safeHTML: () => (/* reexport */ safeHTML),
  83    unwrap: () => (/* reexport */ unwrap),
  84    wrap: () => (/* reexport */ wrap)
  85  });
  86  
  87  // NAMESPACE OBJECT: ./node_modules/@wordpress/dom/build-module/focusable.js
  88  var focusable_namespaceObject = {};
  89  __webpack_require__.r(focusable_namespaceObject);
  90  __webpack_require__.d(focusable_namespaceObject, {
  91    find: () => (find)
  92  });
  93  
  94  // NAMESPACE OBJECT: ./node_modules/@wordpress/dom/build-module/tabbable.js
  95  var tabbable_namespaceObject = {};
  96  __webpack_require__.r(tabbable_namespaceObject);
  97  __webpack_require__.d(tabbable_namespaceObject, {
  98    find: () => (tabbable_find),
  99    findNext: () => (findNext),
 100    findPrevious: () => (findPrevious),
 101    isTabbableIndex: () => (isTabbableIndex)
 102  });
 103  
 104  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/focusable.js
 105  /**
 106   * References:
 107   *
 108   * Focusable:
 109   *  - https://www.w3.org/TR/html5/editing.html#focus-management
 110   *
 111   * Sequential focus navigation:
 112   *  - https://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute
 113   *
 114   * Disabled elements:
 115   *  - https://www.w3.org/TR/html5/disabled-elements.html#disabled-elements
 116   *
 117   * getClientRects algorithm (requiring layout box):
 118   *  - https://www.w3.org/TR/cssom-view-1/#extension-to-the-element-interface
 119   *
 120   * AREA elements associated with an IMG:
 121   *  - https://w3c.github.io/html/editing.html#data-model
 122   */
 123  
 124  /**
 125   * Returns a CSS selector used to query for focusable elements.
 126   *
 127   * @param {boolean} sequential If set, only query elements that are sequentially
 128   *                             focusable. Non-interactive elements with a
 129   *                             negative `tabindex` are focusable but not
 130   *                             sequentially focusable.
 131   *                             https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute
 132   *
 133   * @return {string} CSS selector.
 134   */
 135  function buildSelector(sequential) {
 136    return [sequential ? '[tabindex]:not([tabindex^="-"])' : '[tabindex]', 'a[href]', 'button:not([disabled])', 'input:not([type="hidden"]):not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'iframe:not([tabindex^="-"])', 'object', 'embed', 'area[href]', '[contenteditable]:not([contenteditable=false])'].join(',');
 137  }
 138  
 139  /**
 140   * Returns true if the specified element is visible (i.e. neither display: none
 141   * nor visibility: hidden).
 142   *
 143   * @param {HTMLElement} element DOM element to test.
 144   *
 145   * @return {boolean} Whether element is visible.
 146   */
 147  function isVisible(element) {
 148    return element.offsetWidth > 0 || element.offsetHeight > 0 || element.getClientRects().length > 0;
 149  }
 150  
 151  /**
 152   * Returns true if the specified area element is a valid focusable element, or
 153   * false otherwise. Area is only focusable if within a map where a named map
 154   * referenced by an image somewhere in the document.
 155   *
 156   * @param {HTMLAreaElement} element DOM area element to test.
 157   *
 158   * @return {boolean} Whether area element is valid for focus.
 159   */
 160  function isValidFocusableArea(element) {
 161    /** @type {HTMLMapElement | null} */
 162    const map = element.closest('map[name]');
 163    if (!map) {
 164      return false;
 165    }
 166  
 167    /** @type {HTMLImageElement | null} */
 168    const img = element.ownerDocument.querySelector('img[usemap="#' + map.name + '"]');
 169    return !!img && isVisible(img);
 170  }
 171  
 172  /**
 173   * Returns all focusable elements within a given context.
 174   *
 175   * @param {Element} context              Element in which to search.
 176   * @param {Object}  options
 177   * @param {boolean} [options.sequential] If set, only return elements that are
 178   *                                       sequentially focusable.
 179   *                                       Non-interactive elements with a
 180   *                                       negative `tabindex` are focusable but
 181   *                                       not sequentially focusable.
 182   *                                       https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute
 183   *
 184   * @return {HTMLElement[]} Focusable elements.
 185   */
 186  function find(context, {
 187    sequential = false
 188  } = {}) {
 189    /* eslint-disable jsdoc/no-undefined-types */
 190    /** @type {NodeListOf<HTMLElement>} */
 191    /* eslint-enable jsdoc/no-undefined-types */
 192    const elements = context.querySelectorAll(buildSelector(sequential));
 193    return Array.from(elements).filter(element => {
 194      if (!isVisible(element)) {
 195        return false;
 196      }
 197      const {
 198        nodeName
 199      } = element;
 200      if ('AREA' === nodeName) {
 201        return isValidFocusableArea( /** @type {HTMLAreaElement} */element);
 202      }
 203      return true;
 204    });
 205  }
 206  
 207  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/tabbable.js
 208  /**
 209   * Internal dependencies
 210   */
 211  
 212  
 213  /**
 214   * Returns the tab index of the given element. In contrast with the tabIndex
 215   * property, this normalizes the default (0) to avoid browser inconsistencies,
 216   * operating under the assumption that this function is only ever called with a
 217   * focusable node.
 218   *
 219   * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1190261
 220   *
 221   * @param {Element} element Element from which to retrieve.
 222   *
 223   * @return {number} Tab index of element (default 0).
 224   */
 225  function getTabIndex(element) {
 226    const tabIndex = element.getAttribute('tabindex');
 227    return tabIndex === null ? 0 : parseInt(tabIndex, 10);
 228  }
 229  
 230  /**
 231   * Returns true if the specified element is tabbable, or false otherwise.
 232   *
 233   * @param {Element} element Element to test.
 234   *
 235   * @return {boolean} Whether element is tabbable.
 236   */
 237  function isTabbableIndex(element) {
 238    return getTabIndex(element) !== -1;
 239  }
 240  
 241  /** @typedef {Element & { type?: string, checked?: boolean, name?: string }} MaybeHTMLInputElement */
 242  
 243  /**
 244   * Returns a stateful reducer function which constructs a filtered array of
 245   * tabbable elements, where at most one radio input is selected for a given
 246   * name, giving priority to checked input, falling back to the first
 247   * encountered.
 248   *
 249   * @return {(acc: MaybeHTMLInputElement[], el: MaybeHTMLInputElement) => MaybeHTMLInputElement[]} Radio group collapse reducer.
 250   */
 251  function createStatefulCollapseRadioGroup() {
 252    /** @type {Record<string, MaybeHTMLInputElement>} */
 253    const CHOSEN_RADIO_BY_NAME = {};
 254    return function collapseRadioGroup( /** @type {MaybeHTMLInputElement[]} */result, /** @type {MaybeHTMLInputElement} */element) {
 255      const {
 256        nodeName,
 257        type,
 258        checked,
 259        name
 260      } = element;
 261  
 262      // For all non-radio tabbables, construct to array by concatenating.
 263      if (nodeName !== 'INPUT' || type !== 'radio' || !name) {
 264        return result.concat(element);
 265      }
 266      const hasChosen = CHOSEN_RADIO_BY_NAME.hasOwnProperty(name);
 267  
 268      // Omit by skipping concatenation if the radio element is not chosen.
 269      const isChosen = checked || !hasChosen;
 270      if (!isChosen) {
 271        return result;
 272      }
 273  
 274      // At this point, if there had been a chosen element, the current
 275      // element is checked and should take priority. Retroactively remove
 276      // the element which had previously been considered the chosen one.
 277      if (hasChosen) {
 278        const hadChosenElement = CHOSEN_RADIO_BY_NAME[name];
 279        result = result.filter(e => e !== hadChosenElement);
 280      }
 281      CHOSEN_RADIO_BY_NAME[name] = element;
 282      return result.concat(element);
 283    };
 284  }
 285  
 286  /**
 287   * An array map callback, returning an object with the element value and its
 288   * array index location as properties. This is used to emulate a proper stable
 289   * sort where equal tabIndex should be left in order of their occurrence in the
 290   * document.
 291   *
 292   * @param {Element} element Element.
 293   * @param {number}  index   Array index of element.
 294   *
 295   * @return {{ element: Element, index: number }} Mapped object with element, index.
 296   */
 297  function mapElementToObjectTabbable(element, index) {
 298    return {
 299      element,
 300      index
 301    };
 302  }
 303  
 304  /**
 305   * An array map callback, returning an element of the given mapped object's
 306   * element value.
 307   *
 308   * @param {{ element: Element }} object Mapped object with element.
 309   *
 310   * @return {Element} Mapped object element.
 311   */
 312  function mapObjectTabbableToElement(object) {
 313    return object.element;
 314  }
 315  
 316  /**
 317   * A sort comparator function used in comparing two objects of mapped elements.
 318   *
 319   * @see mapElementToObjectTabbable
 320   *
 321   * @param {{ element: Element, index: number }} a First object to compare.
 322   * @param {{ element: Element, index: number }} b Second object to compare.
 323   *
 324   * @return {number} Comparator result.
 325   */
 326  function compareObjectTabbables(a, b) {
 327    const aTabIndex = getTabIndex(a.element);
 328    const bTabIndex = getTabIndex(b.element);
 329    if (aTabIndex === bTabIndex) {
 330      return a.index - b.index;
 331    }
 332    return aTabIndex - bTabIndex;
 333  }
 334  
 335  /**
 336   * Givin focusable elements, filters out tabbable element.
 337   *
 338   * @param {Element[]} focusables Focusable elements to filter.
 339   *
 340   * @return {Element[]} Tabbable elements.
 341   */
 342  function filterTabbable(focusables) {
 343    return focusables.filter(isTabbableIndex).map(mapElementToObjectTabbable).sort(compareObjectTabbables).map(mapObjectTabbableToElement).reduce(createStatefulCollapseRadioGroup(), []);
 344  }
 345  
 346  /**
 347   * @param {Element} context
 348   * @return {Element[]} Tabbable elements within the context.
 349   */
 350  function tabbable_find(context) {
 351    return filterTabbable(find(context));
 352  }
 353  
 354  /**
 355   * Given a focusable element, find the preceding tabbable element.
 356   *
 357   * @param {Element} element The focusable element before which to look. Defaults
 358   *                          to the active element.
 359   *
 360   * @return {Element|undefined} Preceding tabbable element.
 361   */
 362  function findPrevious(element) {
 363    return filterTabbable(find(element.ownerDocument.body)).reverse().find(focusable => {
 364      return (
 365        // eslint-disable-next-line no-bitwise
 366        element.compareDocumentPosition(focusable) & element.DOCUMENT_POSITION_PRECEDING
 367      );
 368    });
 369  }
 370  
 371  /**
 372   * Given a focusable element, find the next tabbable element.
 373   *
 374   * @param {Element} element The focusable element after which to look. Defaults
 375   *                          to the active element.
 376   *
 377   * @return {Element|undefined} Next tabbable element.
 378   */
 379  function findNext(element) {
 380    return filterTabbable(find(element.ownerDocument.body)).find(focusable => {
 381      return (
 382        // eslint-disable-next-line no-bitwise
 383        element.compareDocumentPosition(focusable) & element.DOCUMENT_POSITION_FOLLOWING
 384      );
 385    });
 386  }
 387  
 388  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/utils/assert-is-defined.js
 389  function assertIsDefined(val, name) {
 390    if (false) {}
 391  }
 392  
 393  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-rectangle-from-range.js
 394  /**
 395   * Internal dependencies
 396   */
 397  
 398  
 399  /**
 400   * Get the rectangle of a given Range. Returns `null` if no suitable rectangle
 401   * can be found.
 402   *
 403   * @param {Range} range The range.
 404   *
 405   * @return {DOMRect?} The rectangle.
 406   */
 407  function getRectangleFromRange(range) {
 408    // For uncollapsed ranges, get the rectangle that bounds the contents of the
 409    // range; this a rectangle enclosing the union of the bounding rectangles
 410    // for all the elements in the range.
 411    if (!range.collapsed) {
 412      const rects = Array.from(range.getClientRects());
 413  
 414      // If there's just a single rect, return it.
 415      if (rects.length === 1) {
 416        return rects[0];
 417      }
 418  
 419      // Ignore tiny selection at the edge of a range.
 420      const filteredRects = rects.filter(({
 421        width
 422      }) => width > 1);
 423  
 424      // If it's full of tiny selections, return browser default.
 425      if (filteredRects.length === 0) {
 426        return range.getBoundingClientRect();
 427      }
 428      if (filteredRects.length === 1) {
 429        return filteredRects[0];
 430      }
 431      let {
 432        top: furthestTop,
 433        bottom: furthestBottom,
 434        left: furthestLeft,
 435        right: furthestRight
 436      } = filteredRects[0];
 437      for (const {
 438        top,
 439        bottom,
 440        left,
 441        right
 442      } of filteredRects) {
 443        if (top < furthestTop) furthestTop = top;
 444        if (bottom > furthestBottom) furthestBottom = bottom;
 445        if (left < furthestLeft) furthestLeft = left;
 446        if (right > furthestRight) furthestRight = right;
 447      }
 448      return new window.DOMRect(furthestLeft, furthestTop, furthestRight - furthestLeft, furthestBottom - furthestTop);
 449    }
 450    const {
 451      startContainer
 452    } = range;
 453    const {
 454      ownerDocument
 455    } = startContainer;
 456  
 457    // Correct invalid "BR" ranges. The cannot contain any children.
 458    if (startContainer.nodeName === 'BR') {
 459      const {
 460        parentNode
 461      } = startContainer;
 462      assertIsDefined(parentNode, 'parentNode');
 463      const index = /** @type {Node[]} */Array.from(parentNode.childNodes).indexOf(startContainer);
 464      assertIsDefined(ownerDocument, 'ownerDocument');
 465      range = ownerDocument.createRange();
 466      range.setStart(parentNode, index);
 467      range.setEnd(parentNode, index);
 468    }
 469    const rects = range.getClientRects();
 470  
 471    // If we have multiple rectangles for a collapsed range, there's no way to
 472    // know which it is, so don't return anything.
 473    if (rects.length > 1) {
 474      return null;
 475    }
 476    let rect = rects[0];
 477  
 478    // If the collapsed range starts (and therefore ends) at an element node,
 479    // `getClientRects` can be empty in some browsers. This can be resolved
 480    // by adding a temporary text node with zero-width space to the range.
 481    //
 482    // See: https://stackoverflow.com/a/6847328/995445
 483    if (!rect || rect.height === 0) {
 484      assertIsDefined(ownerDocument, 'ownerDocument');
 485      const padNode = ownerDocument.createTextNode('\u200b');
 486      // Do not modify the live range.
 487      range = range.cloneRange();
 488      range.insertNode(padNode);
 489      rect = range.getClientRects()[0];
 490      assertIsDefined(padNode.parentNode, 'padNode.parentNode');
 491      padNode.parentNode.removeChild(padNode);
 492    }
 493    return rect;
 494  }
 495  
 496  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/compute-caret-rect.js
 497  /**
 498   * Internal dependencies
 499   */
 500  
 501  
 502  
 503  /**
 504   * Get the rectangle for the selection in a container.
 505   *
 506   * @param {Window} win The window of the selection.
 507   *
 508   * @return {DOMRect | null} The rectangle.
 509   */
 510  function computeCaretRect(win) {
 511    const selection = win.getSelection();
 512    assertIsDefined(selection, 'selection');
 513    const range = selection.rangeCount ? selection.getRangeAt(0) : null;
 514    if (!range) {
 515      return null;
 516    }
 517    return getRectangleFromRange(range);
 518  }
 519  
 520  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-text-selection.js
 521  /**
 522   * Internal dependencies
 523   */
 524  
 525  
 526  /**
 527   * Check whether the current document has selected text. This applies to ranges
 528   * of text in the document, and not selection inside `<input>` and `<textarea>`
 529   * elements.
 530   *
 531   * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection#Related_objects.
 532   *
 533   * @param {Document} doc The document to check.
 534   *
 535   * @return {boolean} True if there is selection, false if not.
 536   */
 537  function documentHasTextSelection(doc) {
 538    assertIsDefined(doc.defaultView, 'doc.defaultView');
 539    const selection = doc.defaultView.getSelection();
 540    assertIsDefined(selection, 'selection');
 541    const range = selection.rangeCount ? selection.getRangeAt(0) : null;
 542    return !!range && !range.collapsed;
 543  }
 544  
 545  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-html-input-element.js
 546  /* eslint-disable jsdoc/valid-types */
 547  /**
 548   * @param {Node} node
 549   * @return {node is HTMLInputElement} Whether the node is an HTMLInputElement.
 550   */
 551  function isHTMLInputElement(node) {
 552    /* eslint-enable jsdoc/valid-types */
 553    return node?.nodeName === 'INPUT';
 554  }
 555  
 556  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-text-field.js
 557  /**
 558   * Internal dependencies
 559   */
 560  
 561  
 562  /* eslint-disable jsdoc/valid-types */
 563  /**
 564   * Check whether the given element is a text field, where text field is defined
 565   * by the ability to select within the input, or that it is contenteditable.
 566   *
 567   * See: https://html.spec.whatwg.org/#textFieldSelection
 568   *
 569   * @param {Node} node The HTML element.
 570   * @return {node is HTMLElement} True if the element is an text field, false if not.
 571   */
 572  function isTextField(node) {
 573    /* eslint-enable jsdoc/valid-types */
 574    const nonTextInputs = ['button', 'checkbox', 'hidden', 'file', 'radio', 'image', 'range', 'reset', 'submit', 'number', 'email', 'time'];
 575    return isHTMLInputElement(node) && node.type && !nonTextInputs.includes(node.type) || node.nodeName === 'TEXTAREA' || /** @type {HTMLElement} */node.contentEditable === 'true';
 576  }
 577  
 578  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/input-field-has-uncollapsed-selection.js
 579  /**
 580   * Internal dependencies
 581   */
 582  
 583  
 584  
 585  /**
 586   * Check whether the given input field or textarea contains a (uncollapsed)
 587   * selection of text.
 588   *
 589   * CAVEAT: Only specific text-based HTML inputs support the selection APIs
 590   * needed to determine whether they have a collapsed or uncollapsed selection.
 591   * This function defaults to returning `true` when the selection cannot be
 592   * inspected, such as with `<input type="time">`. The rationale is that this
 593   * should cause the block editor to defer to the browser's native selection
 594   * handling (e.g. copying and pasting), thereby reducing friction for the user.
 595   *
 596   * See: https://html.spec.whatwg.org/multipage/input.html#do-not-apply
 597   *
 598   * @param {Element} element The HTML element.
 599   *
 600   * @return {boolean} Whether the input/textareaa element has some "selection".
 601   */
 602  function inputFieldHasUncollapsedSelection(element) {
 603    if (!isHTMLInputElement(element) && !isTextField(element)) {
 604      return false;
 605    }
 606  
 607    // Safari throws a type error when trying to get `selectionStart` and
 608    // `selectionEnd` on non-text <input> elements, so a try/catch construct is
 609    // necessary.
 610    try {
 611      const {
 612        selectionStart,
 613        selectionEnd
 614      } = /** @type {HTMLInputElement | HTMLTextAreaElement} */element;
 615      return (
 616        // `null` means the input type doesn't implement selection, thus we
 617        // cannot determine whether the selection is collapsed, so we
 618        // default to true.
 619        selectionStart === null ||
 620        // when not null, compare the two points
 621        selectionStart !== selectionEnd
 622      );
 623    } catch (error) {
 624      // This is Safari's way of saying that the input type doesn't implement
 625      // selection, so we default to true.
 626      return true;
 627    }
 628  }
 629  
 630  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-uncollapsed-selection.js
 631  /**
 632   * Internal dependencies
 633   */
 634  
 635  
 636  
 637  /**
 638   * Check whether the current document has any sort of (uncollapsed) selection.
 639   * This includes ranges of text across elements and any selection inside
 640   * textual `<input>` and `<textarea>` elements.
 641   *
 642   * @param {Document} doc The document to check.
 643   *
 644   * @return {boolean} Whether there is any recognizable text selection in the document.
 645   */
 646  function documentHasUncollapsedSelection(doc) {
 647    return documentHasTextSelection(doc) || !!doc.activeElement && inputFieldHasUncollapsedSelection(doc.activeElement);
 648  }
 649  
 650  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-selection.js
 651  /**
 652   * Internal dependencies
 653   */
 654  
 655  
 656  
 657  
 658  /**
 659   * Check whether the current document has a selection. This includes focus in
 660   * input fields, textareas, and general rich-text selection.
 661   *
 662   * @param {Document} doc The document to check.
 663   *
 664   * @return {boolean} True if there is selection, false if not.
 665   */
 666  function documentHasSelection(doc) {
 667    return !!doc.activeElement && (isHTMLInputElement(doc.activeElement) || isTextField(doc.activeElement) || documentHasTextSelection(doc));
 668  }
 669  
 670  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-computed-style.js
 671  /**
 672   * Internal dependencies
 673   */
 674  
 675  
 676  /* eslint-disable jsdoc/valid-types */
 677  /**
 678   * @param {Element} element
 679   * @return {ReturnType<Window['getComputedStyle']>} The computed style for the element.
 680   */
 681  function getComputedStyle(element) {
 682    /* eslint-enable jsdoc/valid-types */
 683    assertIsDefined(element.ownerDocument.defaultView, 'element.ownerDocument.defaultView');
 684    return element.ownerDocument.defaultView.getComputedStyle(element);
 685  }
 686  
 687  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-scroll-container.js
 688  /**
 689   * Internal dependencies
 690   */
 691  
 692  
 693  /**
 694   * Given a DOM node, finds the closest scrollable container node or the node
 695   * itself, if scrollable.
 696   *
 697   * @param {Element | null} node      Node from which to start.
 698   * @param {?string}        direction Direction of scrollable container to search for ('vertical', 'horizontal', 'all').
 699   *                                   Defaults to 'vertical'.
 700   * @return {Element | undefined} Scrollable container node, if found.
 701   */
 702  function getScrollContainer(node, direction = 'vertical') {
 703    if (!node) {
 704      return undefined;
 705    }
 706    if (direction === 'vertical' || direction === 'all') {
 707      // Scrollable if scrollable height exceeds displayed...
 708      if (node.scrollHeight > node.clientHeight) {
 709        // ...except when overflow is defined to be hidden or visible
 710        const {
 711          overflowY
 712        } = getComputedStyle(node);
 713        if (/(auto|scroll)/.test(overflowY)) {
 714          return node;
 715        }
 716      }
 717    }
 718    if (direction === 'horizontal' || direction === 'all') {
 719      // Scrollable if scrollable width exceeds displayed...
 720      if (node.scrollWidth > node.clientWidth) {
 721        // ...except when overflow is defined to be hidden or visible
 722        const {
 723          overflowX
 724        } = getComputedStyle(node);
 725        if (/(auto|scroll)/.test(overflowX)) {
 726          return node;
 727        }
 728      }
 729    }
 730    if (node.ownerDocument === node.parentNode) {
 731      return node;
 732    }
 733  
 734    // Continue traversing.
 735    return getScrollContainer( /** @type {Element} */node.parentNode, direction);
 736  }
 737  
 738  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-offset-parent.js
 739  /**
 740   * Internal dependencies
 741   */
 742  
 743  
 744  /**
 745   * Returns the closest positioned element, or null under any of the conditions
 746   * of the offsetParent specification. Unlike offsetParent, this function is not
 747   * limited to HTMLElement and accepts any Node (e.g. Node.TEXT_NODE).
 748   *
 749   * @see https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent
 750   *
 751   * @param {Node} node Node from which to find offset parent.
 752   *
 753   * @return {Node | null} Offset parent.
 754   */
 755  function getOffsetParent(node) {
 756    // Cannot retrieve computed style or offset parent only anything other than
 757    // an element node, so find the closest element node.
 758    let closestElement;
 759    while (closestElement = /** @type {Node} */node.parentNode) {
 760      if (closestElement.nodeType === closestElement.ELEMENT_NODE) {
 761        break;
 762      }
 763    }
 764    if (!closestElement) {
 765      return null;
 766    }
 767  
 768    // If the closest element is already positioned, return it, as offsetParent
 769    // does not otherwise consider the node itself.
 770    if (getComputedStyle( /** @type {Element} */closestElement).position !== 'static') {
 771      return closestElement;
 772    }
 773  
 774    // offsetParent is undocumented/draft.
 775    return /** @type {Node & { offsetParent: Node }} */closestElement.offsetParent;
 776  }
 777  
 778  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-input-or-text-area.js
 779  /* eslint-disable jsdoc/valid-types */
 780  /**
 781   * @param {Element} element
 782   * @return {element is HTMLInputElement | HTMLTextAreaElement} Whether the element is an input or textarea
 783   */
 784  function isInputOrTextArea(element) {
 785    /* eslint-enable jsdoc/valid-types */
 786    return element.tagName === 'INPUT' || element.tagName === 'TEXTAREA';
 787  }
 788  
 789  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-entirely-selected.js
 790  /**
 791   * Internal dependencies
 792   */
 793  
 794  
 795  
 796  /**
 797   * Check whether the contents of the element have been entirely selected.
 798   * Returns true if there is no possibility of selection.
 799   *
 800   * @param {HTMLElement} element The element to check.
 801   *
 802   * @return {boolean} True if entirely selected, false if not.
 803   */
 804  function isEntirelySelected(element) {
 805    if (isInputOrTextArea(element)) {
 806      return element.selectionStart === 0 && element.value.length === element.selectionEnd;
 807    }
 808    if (!element.isContentEditable) {
 809      return true;
 810    }
 811    const {
 812      ownerDocument
 813    } = element;
 814    const {
 815      defaultView
 816    } = ownerDocument;
 817    assertIsDefined(defaultView, 'defaultView');
 818    const selection = defaultView.getSelection();
 819    assertIsDefined(selection, 'selection');
 820    const range = selection.rangeCount ? selection.getRangeAt(0) : null;
 821    if (!range) {
 822      return true;
 823    }
 824    const {
 825      startContainer,
 826      endContainer,
 827      startOffset,
 828      endOffset
 829    } = range;
 830    if (startContainer === element && endContainer === element && startOffset === 0 && endOffset === element.childNodes.length) {
 831      return true;
 832    }
 833    const lastChild = element.lastChild;
 834    assertIsDefined(lastChild, 'lastChild');
 835    const endContainerContentLength = endContainer.nodeType === endContainer.TEXT_NODE ? /** @type {Text} */endContainer.data.length : endContainer.childNodes.length;
 836    return isDeepChild(startContainer, element, 'firstChild') && isDeepChild(endContainer, element, 'lastChild') && startOffset === 0 && endOffset === endContainerContentLength;
 837  }
 838  
 839  /**
 840   * Check whether the contents of the element have been entirely selected.
 841   * Returns true if there is no possibility of selection.
 842   *
 843   * @param {HTMLElement|Node}         query     The element to check.
 844   * @param {HTMLElement}              container The container that we suspect "query" may be a first or last child of.
 845   * @param {"firstChild"|"lastChild"} propName  "firstChild" or "lastChild"
 846   *
 847   * @return {boolean} True if query is a deep first/last child of container, false otherwise.
 848   */
 849  function isDeepChild(query, container, propName) {
 850    /** @type {HTMLElement | ChildNode | null} */
 851    let candidate = container;
 852    do {
 853      if (query === candidate) {
 854        return true;
 855      }
 856      candidate = candidate[propName];
 857    } while (candidate);
 858    return false;
 859  }
 860  
 861  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-form-element.js
 862  /**
 863   * Internal dependencies
 864   */
 865  
 866  
 867  /**
 868   *
 869   * Detects if element is a form element.
 870   *
 871   * @param {Element} element The element to check.
 872   *
 873   * @return {boolean} True if form element and false otherwise.
 874   */
 875  function isFormElement(element) {
 876    if (!element) {
 877      return false;
 878    }
 879    const {
 880      tagName
 881    } = element;
 882    const checkForInputTextarea = isInputOrTextArea(element);
 883    return checkForInputTextarea || tagName === 'BUTTON' || tagName === 'SELECT';
 884  }
 885  
 886  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-rtl.js
 887  /**
 888   * Internal dependencies
 889   */
 890  
 891  
 892  /**
 893   * Whether the element's text direction is right-to-left.
 894   *
 895   * @param {Element} element The element to check.
 896   *
 897   * @return {boolean} True if rtl, false if ltr.
 898   */
 899  function isRTL(element) {
 900    return getComputedStyle(element).direction === 'rtl';
 901  }
 902  
 903  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-range-height.js
 904  /**
 905   * Gets the height of the range without ignoring zero width rectangles, which
 906   * some browsers ignore when creating a union.
 907   *
 908   * @param {Range} range The range to check.
 909   * @return {number | undefined} Height of the range or undefined if the range has no client rectangles.
 910   */
 911  function getRangeHeight(range) {
 912    const rects = Array.from(range.getClientRects());
 913    if (!rects.length) {
 914      return;
 915    }
 916    const highestTop = Math.min(...rects.map(({
 917      top
 918    }) => top));
 919    const lowestBottom = Math.max(...rects.map(({
 920      bottom
 921    }) => bottom));
 922    return lowestBottom - highestTop;
 923  }
 924  
 925  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-selection-forward.js
 926  /**
 927   * Internal dependencies
 928   */
 929  
 930  
 931  /**
 932   * Returns true if the given selection object is in the forward direction, or
 933   * false otherwise.
 934   *
 935   * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
 936   *
 937   * @param {Selection} selection Selection object to check.
 938   *
 939   * @return {boolean} Whether the selection is forward.
 940   */
 941  function isSelectionForward(selection) {
 942    const {
 943      anchorNode,
 944      focusNode,
 945      anchorOffset,
 946      focusOffset
 947    } = selection;
 948    assertIsDefined(anchorNode, 'anchorNode');
 949    assertIsDefined(focusNode, 'focusNode');
 950    const position = anchorNode.compareDocumentPosition(focusNode);
 951  
 952    // Disable reason: `Node#compareDocumentPosition` returns a bitmask value,
 953    // so bitwise operators are intended.
 954    /* eslint-disable no-bitwise */
 955    // Compare whether anchor node precedes focus node. If focus node (where
 956    // end of selection occurs) is after the anchor node, it is forward.
 957    if (position & anchorNode.DOCUMENT_POSITION_PRECEDING) {
 958      return false;
 959    }
 960    if (position & anchorNode.DOCUMENT_POSITION_FOLLOWING) {
 961      return true;
 962    }
 963    /* eslint-enable no-bitwise */
 964  
 965    // `compareDocumentPosition` returns 0 when passed the same node, in which
 966    // case compare offsets.
 967    if (position === 0) {
 968      return anchorOffset <= focusOffset;
 969    }
 970  
 971    // This should never be reached, but return true as default case.
 972    return true;
 973  }
 974  
 975  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/caret-range-from-point.js
 976  /**
 977   * Polyfill.
 978   * Get a collapsed range for a given point.
 979   *
 980   * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint
 981   *
 982   * @param {DocumentMaybeWithCaretPositionFromPoint} doc The document of the range.
 983   * @param {number}                                  x   Horizontal position within the current viewport.
 984   * @param {number}                                  y   Vertical position within the current viewport.
 985   *
 986   * @return {Range | null} The best range for the given point.
 987   */
 988  function caretRangeFromPoint(doc, x, y) {
 989    if (doc.caretRangeFromPoint) {
 990      return doc.caretRangeFromPoint(x, y);
 991    }
 992    if (!doc.caretPositionFromPoint) {
 993      return null;
 994    }
 995    const point = doc.caretPositionFromPoint(x, y);
 996  
 997    // If x or y are negative, outside viewport, or there is no text entry node.
 998    // https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint
 999    if (!point) {
1000      return null;
1001    }
1002    const range = doc.createRange();
1003    range.setStart(point.offsetNode, point.offset);
1004    range.collapse(true);
1005    return range;
1006  }
1007  
1008  /**
1009   * @typedef {{caretPositionFromPoint?: (x: number, y: number)=> CaretPosition | null} & Document } DocumentMaybeWithCaretPositionFromPoint
1010   * @typedef {{ readonly offset: number; readonly offsetNode: Node; getClientRect(): DOMRect | null; }} CaretPosition
1011   */
1012  
1013  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/hidden-caret-range-from-point.js
1014  /**
1015   * Internal dependencies
1016   */
1017  
1018  
1019  
1020  /**
1021   * Get a collapsed range for a given point.
1022   * Gives the container a temporary high z-index (above any UI).
1023   * This is preferred over getting the UI nodes and set styles there.
1024   *
1025   * @param {Document}    doc       The document of the range.
1026   * @param {number}      x         Horizontal position within the current viewport.
1027   * @param {number}      y         Vertical position within the current viewport.
1028   * @param {HTMLElement} container Container in which the range is expected to be found.
1029   *
1030   * @return {?Range} The best range for the given point.
1031   */
1032  function hiddenCaretRangeFromPoint(doc, x, y, container) {
1033    const originalZIndex = container.style.zIndex;
1034    const originalPosition = container.style.position;
1035    const {
1036      position = 'static'
1037    } = getComputedStyle(container);
1038  
1039    // A z-index only works if the element position is not static.
1040    if (position === 'static') {
1041      container.style.position = 'relative';
1042    }
1043    container.style.zIndex = '10000';
1044    const range = caretRangeFromPoint(doc, x, y);
1045    container.style.zIndex = originalZIndex;
1046    container.style.position = originalPosition;
1047    return range;
1048  }
1049  
1050  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/scroll-if-no-range.js
1051  /**
1052   * If no range range can be created or it is outside the container, the element
1053   * may be out of view, so scroll it into view and try again.
1054   *
1055   * @param {HTMLElement} container  The container to scroll.
1056   * @param {boolean}     alignToTop True to align to top, false to bottom.
1057   * @param {Function}    callback   The callback to create the range.
1058   *
1059   * @return {?Range} The range returned by the callback.
1060   */
1061  function scrollIfNoRange(container, alignToTop, callback) {
1062    let range = callback();
1063  
1064    // If no range range can be created or it is outside the container, the
1065    // element may be out of view.
1066    if (!range || !range.startContainer || !container.contains(range.startContainer)) {
1067      container.scrollIntoView(alignToTop);
1068      range = callback();
1069      if (!range || !range.startContainer || !container.contains(range.startContainer)) {
1070        return null;
1071      }
1072    }
1073    return range;
1074  }
1075  
1076  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-edge.js
1077  /**
1078   * Internal dependencies
1079   */
1080  
1081  
1082  
1083  
1084  
1085  
1086  
1087  
1088  
1089  /**
1090   * Check whether the selection is at the edge of the container. Checks for
1091   * horizontal position by default. Set `onlyVertical` to true to check only
1092   * vertically.
1093   *
1094   * @param {HTMLElement} container            Focusable element.
1095   * @param {boolean}     isReverse            Set to true to check left, false to check right.
1096   * @param {boolean}     [onlyVertical=false] Set to true to check only vertical position.
1097   *
1098   * @return {boolean} True if at the edge, false if not.
1099   */
1100  function isEdge(container, isReverse, onlyVertical = false) {
1101    if (isInputOrTextArea(container) && typeof container.selectionStart === 'number') {
1102      if (container.selectionStart !== container.selectionEnd) {
1103        return false;
1104      }
1105      if (isReverse) {
1106        return container.selectionStart === 0;
1107      }
1108      return container.value.length === container.selectionStart;
1109    }
1110    if (!( /** @type {HTMLElement} */container.isContentEditable)) {
1111      return true;
1112    }
1113    const {
1114      ownerDocument
1115    } = container;
1116    const {
1117      defaultView
1118    } = ownerDocument;
1119    assertIsDefined(defaultView, 'defaultView');
1120    const selection = defaultView.getSelection();
1121    if (!selection || !selection.rangeCount) {
1122      return false;
1123    }
1124    const range = selection.getRangeAt(0);
1125    const collapsedRange = range.cloneRange();
1126    const isForward = isSelectionForward(selection);
1127    const isCollapsed = selection.isCollapsed;
1128  
1129    // Collapse in direction of selection.
1130    if (!isCollapsed) {
1131      collapsedRange.collapse(!isForward);
1132    }
1133    const collapsedRangeRect = getRectangleFromRange(collapsedRange);
1134    const rangeRect = getRectangleFromRange(range);
1135    if (!collapsedRangeRect || !rangeRect) {
1136      return false;
1137    }
1138  
1139    // Only consider the multiline selection at the edge if the direction is
1140    // towards the edge. The selection is multiline if it is taller than the
1141    // collapsed  selection.
1142    const rangeHeight = getRangeHeight(range);
1143    if (!isCollapsed && rangeHeight && rangeHeight > collapsedRangeRect.height && isForward === isReverse) {
1144      return false;
1145    }
1146  
1147    // In the case of RTL scripts, the horizontal edge is at the opposite side.
1148    const isReverseDir = isRTL(container) ? !isReverse : isReverse;
1149    const containerRect = container.getBoundingClientRect();
1150  
1151    // To check if a selection is at the edge, we insert a test selection at the
1152    // edge of the container and check if the selections have the same vertical
1153    // or horizontal position. If they do, the selection is at the edge.
1154    // This method proves to be better than a DOM-based calculation for the
1155    // horizontal edge, since it ignores empty textnodes and a trailing line
1156    // break element. In other words, we need to check visual positioning, not
1157    // DOM positioning.
1158    // It also proves better than using the computed style for the vertical
1159    // edge, because we cannot know the padding and line height reliably in
1160    // pixels. `getComputedStyle` may return a value with different units.
1161    const x = isReverseDir ? containerRect.left + 1 : containerRect.right - 1;
1162    const y = isReverse ? containerRect.top + 1 : containerRect.bottom - 1;
1163    const testRange = scrollIfNoRange(container, isReverse, () => hiddenCaretRangeFromPoint(ownerDocument, x, y, container));
1164    if (!testRange) {
1165      return false;
1166    }
1167    const testRect = getRectangleFromRange(testRange);
1168    if (!testRect) {
1169      return false;
1170    }
1171    const verticalSide = isReverse ? 'top' : 'bottom';
1172    const horizontalSide = isReverseDir ? 'left' : 'right';
1173    const verticalDiff = testRect[verticalSide] - rangeRect[verticalSide];
1174    const horizontalDiff = testRect[horizontalSide] - collapsedRangeRect[horizontalSide];
1175  
1176    // Allow the position to be 1px off.
1177    const hasVerticalDiff = Math.abs(verticalDiff) <= 1;
1178    const hasHorizontalDiff = Math.abs(horizontalDiff) <= 1;
1179    return onlyVertical ? hasVerticalDiff : hasVerticalDiff && hasHorizontalDiff;
1180  }
1181  
1182  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-horizontal-edge.js
1183  /**
1184   * Internal dependencies
1185   */
1186  
1187  
1188  /**
1189   * Check whether the selection is horizontally at the edge of the container.
1190   *
1191   * @param {HTMLElement} container Focusable element.
1192   * @param {boolean}     isReverse Set to true to check left, false for right.
1193   *
1194   * @return {boolean} True if at the horizontal edge, false if not.
1195   */
1196  function isHorizontalEdge(container, isReverse) {
1197    return isEdge(container, isReverse);
1198  }
1199  
1200  ;// CONCATENATED MODULE: external ["wp","deprecated"]
1201  const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
1202  var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
1203  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-number-input.js
1204  /**
1205   * WordPress dependencies
1206   */
1207  
1208  
1209  /**
1210   * Internal dependencies
1211   */
1212  
1213  
1214  /* eslint-disable jsdoc/valid-types */
1215  /**
1216   * Check whether the given element is an input field of type number.
1217   *
1218   * @param {Node} node The HTML node.
1219   *
1220   * @return {node is HTMLInputElement} True if the node is number input.
1221   */
1222  function isNumberInput(node) {
1223    external_wp_deprecated_default()('wp.dom.isNumberInput', {
1224      since: '6.1',
1225      version: '6.5'
1226    });
1227    /* eslint-enable jsdoc/valid-types */
1228    return isHTMLInputElement(node) && node.type === 'number' && !isNaN(node.valueAsNumber);
1229  }
1230  
1231  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-vertical-edge.js
1232  /**
1233   * Internal dependencies
1234   */
1235  
1236  
1237  /**
1238   * Check whether the selection is vertically at the edge of the container.
1239   *
1240   * @param {HTMLElement} container Focusable element.
1241   * @param {boolean}     isReverse Set to true to check top, false for bottom.
1242   *
1243   * @return {boolean} True if at the vertical edge, false if not.
1244   */
1245  function isVerticalEdge(container, isReverse) {
1246    return isEdge(container, isReverse, true);
1247  }
1248  
1249  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/place-caret-at-edge.js
1250  /**
1251   * Internal dependencies
1252   */
1253  
1254  
1255  
1256  
1257  
1258  
1259  /**
1260   * Gets the range to place.
1261   *
1262   * @param {HTMLElement}      container Focusable element.
1263   * @param {boolean}          isReverse True for end, false for start.
1264   * @param {number|undefined} x         X coordinate to vertically position.
1265   *
1266   * @return {Range|null} The range to place.
1267   */
1268  function getRange(container, isReverse, x) {
1269    const {
1270      ownerDocument
1271    } = container;
1272    // In the case of RTL scripts, the horizontal edge is at the opposite side.
1273    const isReverseDir = isRTL(container) ? !isReverse : isReverse;
1274    const containerRect = container.getBoundingClientRect();
1275    // When placing at the end (isReverse), find the closest range to the bottom
1276    // right corner. When placing at the start, to the top left corner.
1277    // Ensure x is defined and within the container's boundaries. When it's
1278    // exactly at the boundary, it's not considered within the boundaries.
1279    if (x === undefined) {
1280      x = isReverse ? containerRect.right - 1 : containerRect.left + 1;
1281    } else if (x <= containerRect.left) {
1282      x = containerRect.left + 1;
1283    } else if (x >= containerRect.right) {
1284      x = containerRect.right - 1;
1285    }
1286    const y = isReverseDir ? containerRect.bottom - 1 : containerRect.top + 1;
1287    return hiddenCaretRangeFromPoint(ownerDocument, x, y, container);
1288  }
1289  
1290  /**
1291   * Places the caret at start or end of a given element.
1292   *
1293   * @param {HTMLElement}      container Focusable element.
1294   * @param {boolean}          isReverse True for end, false for start.
1295   * @param {number|undefined} x         X coordinate to vertically position.
1296   */
1297  function placeCaretAtEdge(container, isReverse, x) {
1298    if (!container) {
1299      return;
1300    }
1301    container.focus();
1302    if (isInputOrTextArea(container)) {
1303      // The element may not support selection setting.
1304      if (typeof container.selectionStart !== 'number') {
1305        return;
1306      }
1307      if (isReverse) {
1308        container.selectionStart = container.value.length;
1309        container.selectionEnd = container.value.length;
1310      } else {
1311        container.selectionStart = 0;
1312        container.selectionEnd = 0;
1313      }
1314      return;
1315    }
1316    if (!container.isContentEditable) {
1317      return;
1318    }
1319    const range = scrollIfNoRange(container, isReverse, () => getRange(container, isReverse, x));
1320    if (!range) return;
1321    const {
1322      ownerDocument
1323    } = container;
1324    const {
1325      defaultView
1326    } = ownerDocument;
1327    assertIsDefined(defaultView, 'defaultView');
1328    const selection = defaultView.getSelection();
1329    assertIsDefined(selection, 'selection');
1330    selection.removeAllRanges();
1331    selection.addRange(range);
1332  }
1333  
1334  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/place-caret-at-horizontal-edge.js
1335  /**
1336   * Internal dependencies
1337   */
1338  
1339  
1340  /**
1341   * Places the caret at start or end of a given element.
1342   *
1343   * @param {HTMLElement} container Focusable element.
1344   * @param {boolean}     isReverse True for end, false for start.
1345   */
1346  function placeCaretAtHorizontalEdge(container, isReverse) {
1347    return placeCaretAtEdge(container, isReverse, undefined);
1348  }
1349  
1350  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/place-caret-at-vertical-edge.js
1351  /**
1352   * Internal dependencies
1353   */
1354  
1355  
1356  /**
1357   * Places the caret at the top or bottom of a given element.
1358   *
1359   * @param {HTMLElement} container Focusable element.
1360   * @param {boolean}     isReverse True for bottom, false for top.
1361   * @param {DOMRect}     [rect]    The rectangle to position the caret with.
1362   */
1363  function placeCaretAtVerticalEdge(container, isReverse, rect) {
1364    return placeCaretAtEdge(container, isReverse, rect?.left);
1365  }
1366  
1367  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/insert-after.js
1368  /**
1369   * Internal dependencies
1370   */
1371  
1372  
1373  /**
1374   * Given two DOM nodes, inserts the former in the DOM as the next sibling of
1375   * the latter.
1376   *
1377   * @param {Node} newNode       Node to be inserted.
1378   * @param {Node} referenceNode Node after which to perform the insertion.
1379   * @return {void}
1380   */
1381  function insertAfter(newNode, referenceNode) {
1382    assertIsDefined(referenceNode.parentNode, 'referenceNode.parentNode');
1383    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
1384  }
1385  
1386  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/remove.js
1387  /**
1388   * Internal dependencies
1389   */
1390  
1391  
1392  /**
1393   * Given a DOM node, removes it from the DOM.
1394   *
1395   * @param {Node} node Node to be removed.
1396   * @return {void}
1397   */
1398  function remove(node) {
1399    assertIsDefined(node.parentNode, 'node.parentNode');
1400    node.parentNode.removeChild(node);
1401  }
1402  
1403  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/replace.js
1404  /**
1405   * Internal dependencies
1406   */
1407  
1408  
1409  
1410  
1411  /**
1412   * Given two DOM nodes, replaces the former with the latter in the DOM.
1413   *
1414   * @param {Element} processedNode Node to be removed.
1415   * @param {Element} newNode       Node to be inserted in its place.
1416   * @return {void}
1417   */
1418  function replace(processedNode, newNode) {
1419    assertIsDefined(processedNode.parentNode, 'processedNode.parentNode');
1420    insertAfter(newNode, processedNode.parentNode);
1421    remove(processedNode);
1422  }
1423  
1424  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/unwrap.js
1425  /**
1426   * Internal dependencies
1427   */
1428  
1429  
1430  /**
1431   * Unwrap the given node. This means any child nodes are moved to the parent.
1432   *
1433   * @param {Node} node The node to unwrap.
1434   *
1435   * @return {void}
1436   */
1437  function unwrap(node) {
1438    const parent = node.parentNode;
1439    assertIsDefined(parent, 'node.parentNode');
1440    while (node.firstChild) {
1441      parent.insertBefore(node.firstChild, node);
1442    }
1443    parent.removeChild(node);
1444  }
1445  
1446  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/replace-tag.js
1447  /**
1448   * Internal dependencies
1449   */
1450  
1451  
1452  /**
1453   * Replaces the given node with a new node with the given tag name.
1454   *
1455   * @param {Element} node    The node to replace
1456   * @param {string}  tagName The new tag name.
1457   *
1458   * @return {Element} The new node.
1459   */
1460  function replaceTag(node, tagName) {
1461    const newNode = node.ownerDocument.createElement(tagName);
1462    while (node.firstChild) {
1463      newNode.appendChild(node.firstChild);
1464    }
1465    assertIsDefined(node.parentNode, 'node.parentNode');
1466    node.parentNode.replaceChild(newNode, node);
1467    return newNode;
1468  }
1469  
1470  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/wrap.js
1471  /**
1472   * Internal dependencies
1473   */
1474  
1475  
1476  /**
1477   * Wraps the given node with a new node with the given tag name.
1478   *
1479   * @param {Element} newNode       The node to insert.
1480   * @param {Element} referenceNode The node to wrap.
1481   */
1482  function wrap(newNode, referenceNode) {
1483    assertIsDefined(referenceNode.parentNode, 'referenceNode.parentNode');
1484    referenceNode.parentNode.insertBefore(newNode, referenceNode);
1485    newNode.appendChild(referenceNode);
1486  }
1487  
1488  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/safe-html.js
1489  /**
1490   * Internal dependencies
1491   */
1492  
1493  
1494  /**
1495   * Strips scripts and on* attributes from HTML.
1496   *
1497   * @param {string} html HTML to sanitize.
1498   *
1499   * @return {string} The sanitized HTML.
1500   */
1501  function safeHTML(html) {
1502    const {
1503      body
1504    } = document.implementation.createHTMLDocument('');
1505    body.innerHTML = html;
1506    const elements = body.getElementsByTagName('*');
1507    let elementIndex = elements.length;
1508    while (elementIndex--) {
1509      const element = elements[elementIndex];
1510      if (element.tagName === 'SCRIPT') {
1511        remove(element);
1512      } else {
1513        let attributeIndex = element.attributes.length;
1514        while (attributeIndex--) {
1515          const {
1516            name: key
1517          } = element.attributes[attributeIndex];
1518          if (key.startsWith('on')) {
1519            element.removeAttribute(key);
1520          }
1521        }
1522      }
1523    }
1524    return body.innerHTML;
1525  }
1526  
1527  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/strip-html.js
1528  /**
1529   * Internal dependencies
1530   */
1531  
1532  
1533  /**
1534   * Removes any HTML tags from the provided string.
1535   *
1536   * @param {string} html The string containing html.
1537   *
1538   * @return {string} The text content with any html removed.
1539   */
1540  function stripHTML(html) {
1541    // Remove any script tags or on* attributes otherwise their *contents* will be left
1542    // in place following removal of HTML tags.
1543    html = safeHTML(html);
1544    const doc = document.implementation.createHTMLDocument('');
1545    doc.body.innerHTML = html;
1546    return doc.body.textContent || '';
1547  }
1548  
1549  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-empty.js
1550  /**
1551   * Recursively checks if an element is empty. An element is not empty if it
1552   * contains text or contains elements with attributes such as images.
1553   *
1554   * @param {Element} element The element to check.
1555   *
1556   * @return {boolean} Whether or not the element is empty.
1557   */
1558  function isEmpty(element) {
1559    switch (element.nodeType) {
1560      case element.TEXT_NODE:
1561        // We cannot use \s since it includes special spaces which we want
1562        // to preserve.
1563        return /^[ \f\n\r\t\v\u00a0]*$/.test(element.nodeValue || '');
1564      case element.ELEMENT_NODE:
1565        if (element.hasAttributes()) {
1566          return false;
1567        } else if (!element.hasChildNodes()) {
1568          return true;
1569        }
1570        return /** @type {Element[]} */Array.from(element.childNodes).every(isEmpty);
1571      default:
1572        return true;
1573    }
1574  }
1575  
1576  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/phrasing-content.js
1577  /**
1578   * All phrasing content elements.
1579   *
1580   * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content-0
1581   */
1582  
1583  /**
1584   * @typedef {Record<string,SemanticElementDefinition>} ContentSchema
1585   */
1586  
1587  /**
1588   * @typedef SemanticElementDefinition
1589   * @property {string[]}      [attributes] Content attributes
1590   * @property {ContentSchema} [children]   Content attributes
1591   */
1592  
1593  /**
1594   * All text-level semantic elements.
1595   *
1596   * @see https://html.spec.whatwg.org/multipage/text-level-semantics.html
1597   *
1598   * @type {ContentSchema}
1599   */
1600  const textContentSchema = {
1601    strong: {},
1602    em: {},
1603    s: {},
1604    del: {},
1605    ins: {},
1606    a: {
1607      attributes: ['href', 'target', 'rel', 'id']
1608    },
1609    code: {},
1610    abbr: {
1611      attributes: ['title']
1612    },
1613    sub: {},
1614    sup: {},
1615    br: {},
1616    small: {},
1617    // To do: fix blockquote.
1618    // cite: {},
1619    q: {
1620      attributes: ['cite']
1621    },
1622    dfn: {
1623      attributes: ['title']
1624    },
1625    data: {
1626      attributes: ['value']
1627    },
1628    time: {
1629      attributes: ['datetime']
1630    },
1631    var: {},
1632    samp: {},
1633    kbd: {},
1634    i: {},
1635    b: {},
1636    u: {},
1637    mark: {},
1638    ruby: {},
1639    rt: {},
1640    rp: {},
1641    bdi: {
1642      attributes: ['dir']
1643    },
1644    bdo: {
1645      attributes: ['dir']
1646    },
1647    wbr: {},
1648    '#text': {}
1649  };
1650  
1651  // Recursion is needed.
1652  // Possible: strong > em > strong.
1653  // Impossible: strong > strong.
1654  const excludedElements = ['#text', 'br'];
1655  Object.keys(textContentSchema).filter(element => !excludedElements.includes(element)).forEach(tag => {
1656    const {
1657      [tag]: removedTag,
1658      ...restSchema
1659    } = textContentSchema;
1660    textContentSchema[tag].children = restSchema;
1661  });
1662  
1663  /**
1664   * Embedded content elements.
1665   *
1666   * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#embedded-content-0
1667   *
1668   * @type {ContentSchema}
1669   */
1670  const embeddedContentSchema = {
1671    audio: {
1672      attributes: ['src', 'preload', 'autoplay', 'mediagroup', 'loop', 'muted']
1673    },
1674    canvas: {
1675      attributes: ['width', 'height']
1676    },
1677    embed: {
1678      attributes: ['src', 'type', 'width', 'height']
1679    },
1680    img: {
1681      attributes: ['alt', 'src', 'srcset', 'usemap', 'ismap', 'width', 'height']
1682    },
1683    object: {
1684      attributes: ['data', 'type', 'name', 'usemap', 'form', 'width', 'height']
1685    },
1686    video: {
1687      attributes: ['src', 'poster', 'preload', 'playsinline', 'autoplay', 'mediagroup', 'loop', 'muted', 'controls', 'width', 'height']
1688    }
1689  };
1690  
1691  /**
1692   * Phrasing content elements.
1693   *
1694   * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content-0
1695   */
1696  const phrasingContentSchema = {
1697    ...textContentSchema,
1698    ...embeddedContentSchema
1699  };
1700  
1701  /**
1702   * Get schema of possible paths for phrasing content.
1703   *
1704   * @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content
1705   *
1706   * @param {string} [context] Set to "paste" to exclude invisible elements and
1707   *                           sensitive data.
1708   *
1709   * @return {Partial<ContentSchema>} Schema.
1710   */
1711  function getPhrasingContentSchema(context) {
1712    if (context !== 'paste') {
1713      return phrasingContentSchema;
1714    }
1715  
1716    /**
1717     * @type {Partial<ContentSchema>}
1718     */
1719    const {
1720      u,
1721      // Used to mark misspelling. Shouldn't be pasted.
1722      abbr,
1723      // Invisible.
1724      data,
1725      // Invisible.
1726      time,
1727      // Invisible.
1728      wbr,
1729      // Invisible.
1730      bdi,
1731      // Invisible.
1732      bdo,
1733      // Invisible.
1734      ...remainingContentSchema
1735    } = {
1736      ...phrasingContentSchema,
1737      // We shouldn't paste potentially sensitive information which is not
1738      // visible to the user when pasted, so strip the attributes.
1739      ins: {
1740        children: phrasingContentSchema.ins.children
1741      },
1742      del: {
1743        children: phrasingContentSchema.del.children
1744      }
1745    };
1746    return remainingContentSchema;
1747  }
1748  
1749  /**
1750   * Find out whether or not the given node is phrasing content.
1751   *
1752   * @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content
1753   *
1754   * @param {Node} node The node to test.
1755   *
1756   * @return {boolean} True if phrasing content, false if not.
1757   */
1758  function isPhrasingContent(node) {
1759    const tag = node.nodeName.toLowerCase();
1760    return getPhrasingContentSchema().hasOwnProperty(tag) || tag === 'span';
1761  }
1762  
1763  /**
1764   * @param {Node} node
1765   * @return {boolean} Node is text content
1766   */
1767  function isTextContent(node) {
1768    const tag = node.nodeName.toLowerCase();
1769    return textContentSchema.hasOwnProperty(tag) || tag === 'span';
1770  }
1771  
1772  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-element.js
1773  /* eslint-disable jsdoc/valid-types */
1774  /**
1775   * @param {Node | null | undefined} node
1776   * @return {node is Element} True if node is an Element node
1777   */
1778  function isElement(node) {
1779    /* eslint-enable jsdoc/valid-types */
1780    return !!node && node.nodeType === node.ELEMENT_NODE;
1781  }
1782  
1783  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/clean-node-list.js
1784  /**
1785   * Internal dependencies
1786   */
1787  
1788  
1789  
1790  
1791  
1792  
1793  const noop = () => {};
1794  
1795  /* eslint-disable jsdoc/valid-types */
1796  /**
1797   * @typedef SchemaItem
1798   * @property {string[]}                            [attributes] Attributes.
1799   * @property {(string | RegExp)[]}                 [classes]    Classnames or RegExp to test against.
1800   * @property {'*' | { [tag: string]: SchemaItem }} [children]   Child schemas.
1801   * @property {string[]}                            [require]    Selectors to test required children against. Leave empty or undefined if there are no requirements.
1802   * @property {boolean}                             allowEmpty   Whether to allow nodes without children.
1803   * @property {(node: Node) => boolean}             [isMatch]    Function to test whether a node is a match. If left undefined any node will be assumed to match.
1804   */
1805  
1806  /** @typedef {{ [tag: string]: SchemaItem }} Schema */
1807  /* eslint-enable jsdoc/valid-types */
1808  
1809  /**
1810   * Given a schema, unwraps or removes nodes, attributes and classes on a node
1811   * list.
1812   *
1813   * @param {NodeList} nodeList The nodeList to filter.
1814   * @param {Document} doc      The document of the nodeList.
1815   * @param {Schema}   schema   An array of functions that can mutate with the provided node.
1816   * @param {boolean}  inline   Whether to clean for inline mode.
1817   */
1818  function cleanNodeList(nodeList, doc, schema, inline) {
1819    Array.from(nodeList).forEach(( /** @type {Node & { nextElementSibling?: unknown }} */node) => {
1820      const tag = node.nodeName.toLowerCase();
1821  
1822      // It's a valid child, if the tag exists in the schema without an isMatch
1823      // function, or with an isMatch function that matches the node.
1824      if (schema.hasOwnProperty(tag) && (!schema[tag].isMatch || schema[tag].isMatch?.(node))) {
1825        if (isElement(node)) {
1826          const {
1827            attributes = [],
1828            classes = [],
1829            children,
1830            require = [],
1831            allowEmpty
1832          } = schema[tag];
1833  
1834          // If the node is empty and it's supposed to have children,
1835          // remove the node.
1836          if (children && !allowEmpty && isEmpty(node)) {
1837            remove(node);
1838            return;
1839          }
1840          if (node.hasAttributes()) {
1841            // Strip invalid attributes.
1842            Array.from(node.attributes).forEach(({
1843              name
1844            }) => {
1845              if (name !== 'class' && !attributes.includes(name)) {
1846                node.removeAttribute(name);
1847              }
1848            });
1849  
1850            // Strip invalid classes.
1851            // In jsdom-jscore, 'node.classList' can be undefined.
1852            // TODO: Explore patching this in jsdom-jscore.
1853            if (node.classList && node.classList.length) {
1854              const mattchers = classes.map(item => {
1855                if (typeof item === 'string') {
1856                  return ( /** @type {string} */className) => className === item;
1857                } else if (item instanceof RegExp) {
1858                  return ( /** @type {string} */className) => item.test(className);
1859                }
1860                return noop;
1861              });
1862              Array.from(node.classList).forEach(name => {
1863                if (!mattchers.some(isMatch => isMatch(name))) {
1864                  node.classList.remove(name);
1865                }
1866              });
1867              if (!node.classList.length) {
1868                node.removeAttribute('class');
1869              }
1870            }
1871          }
1872          if (node.hasChildNodes()) {
1873            // Do not filter any content.
1874            if (children === '*') {
1875              return;
1876            }
1877  
1878            // Continue if the node is supposed to have children.
1879            if (children) {
1880              // If a parent requires certain children, but it does
1881              // not have them, drop the parent and continue.
1882              if (require.length && !node.querySelector(require.join(','))) {
1883                cleanNodeList(node.childNodes, doc, schema, inline);
1884                unwrap(node);
1885                // If the node is at the top, phrasing content, and
1886                // contains children that are block content, unwrap
1887                // the node because it is invalid.
1888              } else if (node.parentNode && node.parentNode.nodeName === 'BODY' && isPhrasingContent(node)) {
1889                cleanNodeList(node.childNodes, doc, schema, inline);
1890                if (Array.from(node.childNodes).some(child => !isPhrasingContent(child))) {
1891                  unwrap(node);
1892                }
1893              } else {
1894                cleanNodeList(node.childNodes, doc, children, inline);
1895              }
1896              // Remove children if the node is not supposed to have any.
1897            } else {
1898              while (node.firstChild) {
1899                remove(node.firstChild);
1900              }
1901            }
1902          }
1903        }
1904        // Invalid child. Continue with schema at the same place and unwrap.
1905      } else {
1906        cleanNodeList(node.childNodes, doc, schema, inline);
1907  
1908        // For inline mode, insert a line break when unwrapping nodes that
1909        // are not phrasing content.
1910        if (inline && !isPhrasingContent(node) && node.nextElementSibling) {
1911          insertAfter(doc.createElement('br'), node);
1912        }
1913        unwrap(node);
1914      }
1915    });
1916  }
1917  
1918  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/remove-invalid-html.js
1919  /**
1920   * Internal dependencies
1921   */
1922  
1923  
1924  /**
1925   * Given a schema, unwraps or removes nodes, attributes and classes on HTML.
1926   *
1927   * @param {string}                             HTML   The HTML to clean up.
1928   * @param {import('./clean-node-list').Schema} schema Schema for the HTML.
1929   * @param {boolean}                            inline Whether to clean for inline mode.
1930   *
1931   * @return {string} The cleaned up HTML.
1932   */
1933  function removeInvalidHTML(HTML, schema, inline) {
1934    const doc = document.implementation.createHTMLDocument('');
1935    doc.body.innerHTML = HTML;
1936    cleanNodeList(doc.body.childNodes, doc, schema, inline);
1937    return doc.body.innerHTML;
1938  }
1939  
1940  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/index.js
1941  
1942  
1943  
1944  
1945  
1946  
1947  
1948  
1949  
1950  
1951  
1952  
1953  
1954  
1955  
1956  
1957  
1958  
1959  
1960  
1961  
1962  
1963  
1964  
1965  
1966  
1967  
1968  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/data-transfer.js
1969  /**
1970   * Gets all files from a DataTransfer object.
1971   *
1972   * @param {DataTransfer} dataTransfer DataTransfer object to inspect.
1973   *
1974   * @return {File[]} An array containing all files.
1975   */
1976  function getFilesFromDataTransfer(dataTransfer) {
1977    const files = Array.from(dataTransfer.files);
1978    Array.from(dataTransfer.items).forEach(item => {
1979      const file = item.getAsFile();
1980      if (file && !files.find(({
1981        name,
1982        type,
1983        size
1984      }) => name === file.name && type === file.type && size === file.size)) {
1985        files.push(file);
1986      }
1987    });
1988    return files;
1989  }
1990  
1991  ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/index.js
1992  /**
1993   * Internal dependencies
1994   */
1995  
1996  
1997  
1998  /**
1999   * Object grouping `focusable` and `tabbable` utils
2000   * under the keys with the same name.
2001   */
2002  const build_module_focus = {
2003    focusable: focusable_namespaceObject,
2004    tabbable: tabbable_namespaceObject
2005  };
2006  
2007  
2008  
2009  
2010  (window.wp = window.wp || {}).dom = __webpack_exports__;
2011  /******/ })()
2012  ;


Generated : Mon Mar 18 08:20:01 2024 Cross-referenced by PHPXref