PluginProbe
Gutenberg / 24.0.0
Gutenberg v24.0.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / build / scripts / dom / index.js

index.js in Gutenberg 24.0.0, at build/scripts/dom/index.js

1,127 lines 36.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function() {
2 "use strict";
3 var wp;
4 (wp ||= {}).dom = (() => {
5 var __create = Object.create;
6 var __defProp = Object.defineProperty;
7 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8 var __getOwnPropNames = Object.getOwnPropertyNames;
9 var __getProtoOf = Object.getPrototypeOf;
10 var __hasOwnProp = Object.prototype.hasOwnProperty;
11 var __commonJS = (cb, mod) => function __require() {
12 return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13 };
14 var __export = (target, all) => {
15 for (var name in all)
16 __defProp(target, name, { get: all[name], enumerable: true });
17 };
18 var __copyProps = (to, from, except, desc) => {
19 if (from && typeof from === "object" || typeof from === "function") {
20 for (let key of __getOwnPropNames(from))
21 if (!__hasOwnProp.call(to, key) && key !== except)
22 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23 }
24 return to;
25 };
26 var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
27 // If the importer is in node compatibility mode or this is not an ESM
28 // file that has been converted to a CommonJS file using a Babel-
29 // compatible transform (i.e. "__esModule" has not been set), then set
30 // "default" to the CommonJS "module.exports" for node compatibility.
31 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
32 mod
33 ));
34 var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
36 // package-external:@wordpress/deprecated
37 var require_deprecated = __commonJS({
38 "package-external:@wordpress/deprecated"(exports, module) {
39 module.exports = window.wp.deprecated;
40 }
41 });
42
43 // packages/dom/build-module/index.mjs
44 var index_exports = {};
45 __export(index_exports, {
46 __unstableStripHTML: () => stripHTML,
47 computeCaretRect: () => computeCaretRect,
48 documentHasSelection: () => documentHasSelection,
49 documentHasTextSelection: () => documentHasTextSelection,
50 documentHasUncollapsedSelection: () => documentHasUncollapsedSelection,
51 focus: () => focus,
52 getFilesFromDataTransfer: () => getFilesFromDataTransfer,
53 getOffsetParent: () => getOffsetParent,
54 getPhrasingContentSchema: () => getPhrasingContentSchema,
55 getRectangleFromRange: () => getRectangleFromRange,
56 getScrollContainer: () => getScrollContainer,
57 insertAfter: () => insertAfter,
58 isEmpty: () => isEmpty,
59 isEntirelySelected: () => isEntirelySelected,
60 isFormElement: () => isFormElement,
61 isHorizontalEdge: () => isHorizontalEdge,
62 isNumberInput: () => isNumberInput,
63 isPhrasingContent: () => isPhrasingContent,
64 isRTL: () => isRTL,
65 isSelectionForward: () => isSelectionForward,
66 isTextContent: () => isTextContent,
67 isTextField: () => isTextField,
68 isVerticalEdge: () => isVerticalEdge,
69 placeCaretAtHorizontalEdge: () => placeCaretAtHorizontalEdge,
70 placeCaretAtVerticalEdge: () => placeCaretAtVerticalEdge,
71 remove: () => remove,
72 removeInvalidHTML: () => removeInvalidHTML,
73 replace: () => replace,
74 replaceTag: () => replaceTag,
75 safeHTML: () => safeHTML,
76 unwrap: () => unwrap,
77 wrap: () => wrap
78 });
79
80 // packages/dom/build-module/focusable.mjs
81 var focusable_exports = {};
82 __export(focusable_exports, {
83 find: () => find
84 });
85 function buildSelector(sequential) {
86 return [
87 sequential ? '[tabindex]:not([tabindex^="-"])' : "[tabindex]",
88 "a[href]",
89 "button:not([disabled])",
90 'input:not([type="hidden"]):not([disabled])',
91 "select:not([disabled])",
92 "textarea:not([disabled])",
93 'iframe:not([tabindex^="-"])',
94 "object",
95 "embed",
96 "summary",
97 "area[href]",
98 "[contenteditable]:not([contenteditable=false])"
99 ].join(",");
100 }
101 function isVisible(element) {
102 if (typeof element.checkVisibility === "function") {
103 if (!element.checkVisibility({ visibilityProperty: true })) {
104 return false;
105 }
106 } else {
107 const visibility = element.ownerDocument.defaultView?.getComputedStyle(
108 element
109 ).visibility;
110 if (visibility === "hidden" || visibility === "collapse") {
111 return false;
112 }
113 }
114 return element.offsetWidth > 0 || element.offsetHeight > 0 || element.getClientRects().length > 0;
115 }
116 function isValidFocusableArea(element) {
117 const map = element.closest("map[name]");
118 if (!map) {
119 return false;
120 }
121 const img = element.ownerDocument.querySelector(
122 'img[usemap="#' + map.name + '"]'
123 );
124 return !!img && isVisible(img);
125 }
126 function find(context, { sequential = false } = {}) {
127 const elements = context.querySelectorAll(buildSelector(sequential));
128 return Array.from(elements).filter((element) => {
129 if (!isVisible(element)) {
130 return false;
131 }
132 if (element.closest("[inert]")) {
133 return false;
134 }
135 const { nodeName } = element;
136 if ("AREA" === nodeName) {
137 return isValidFocusableArea(
138 /** @type {HTMLAreaElement} */
139 element
140 );
141 }
142 return true;
143 });
144 }
145
146 // packages/dom/build-module/tabbable.mjs
147 var tabbable_exports = {};
148 __export(tabbable_exports, {
149 find: () => find2,
150 findNext: () => findNext,
151 findPrevious: () => findPrevious,
152 isTabbableIndex: () => isTabbableIndex
153 });
154 function getTabIndex(element) {
155 const tabIndex = element.getAttribute("tabindex");
156 return tabIndex === null ? 0 : parseInt(tabIndex, 10);
157 }
158 function isTabbableIndex(element) {
159 return getTabIndex(element) !== -1;
160 }
161 function createStatefulCollapseRadioGroup() {
162 const CHOSEN_RADIO_BY_NAME = {};
163 return function collapseRadioGroup(result, element) {
164 const { nodeName, type, checked, name } = element;
165 if (nodeName !== "INPUT" || type !== "radio" || !name) {
166 return result.concat(element);
167 }
168 const hasChosen = CHOSEN_RADIO_BY_NAME.hasOwnProperty(name);
169 const isChosen = checked || !hasChosen;
170 if (!isChosen) {
171 return result;
172 }
173 if (hasChosen) {
174 const hadChosenElement = CHOSEN_RADIO_BY_NAME[name];
175 result = result.filter((e) => e !== hadChosenElement);
176 }
177 CHOSEN_RADIO_BY_NAME[name] = element;
178 return result.concat(element);
179 };
180 }
181 function mapElementToObjectTabbable(element, index) {
182 return { element, index };
183 }
184 function mapObjectTabbableToElement(object) {
185 return object.element;
186 }
187 function compareObjectTabbables(a, b) {
188 const aTabIndex = getTabIndex(a.element);
189 const bTabIndex = getTabIndex(b.element);
190 if (aTabIndex === bTabIndex) {
191 return a.index - b.index;
192 }
193 return aTabIndex - bTabIndex;
194 }
195 function filterTabbable(focusables) {
196 return focusables.filter(isTabbableIndex).map(mapElementToObjectTabbable).sort(compareObjectTabbables).map(mapObjectTabbableToElement).reduce(createStatefulCollapseRadioGroup(), []);
197 }
198 function find2(context) {
199 return filterTabbable(find(context));
200 }
201 function findPrevious(element) {
202 return filterTabbable(find(element.ownerDocument.body)).reverse().find(
203 (focusable) => (
204 // eslint-disable-next-line no-bitwise
205 element.compareDocumentPosition(focusable) & element.DOCUMENT_POSITION_PRECEDING
206 )
207 );
208 }
209 function findNext(element) {
210 return filterTabbable(find(element.ownerDocument.body)).find(
211 (focusable) => (
212 // eslint-disable-next-line no-bitwise
213 element.compareDocumentPosition(focusable) & element.DOCUMENT_POSITION_FOLLOWING
214 )
215 );
216 }
217
218 // packages/dom/build-module/utils/assert-is-defined.mjs
219 function assertIsDefined(val, name) {
220 if (val === void 0 || val === null) {
221 throw new Error(
222 `Expected '${name}' to be defined, but received ${val}`
223 );
224 }
225 }
226
227 // packages/dom/build-module/dom/get-rectangle-from-range.mjs
228 function getRectangleFromRange(range) {
229 if (!range.collapsed) {
230 const rects2 = Array.from(range.getClientRects());
231 if (rects2.length === 1) {
232 return rects2[0];
233 }
234 const filteredRects = rects2.filter(({ width }) => width > 1);
235 if (filteredRects.length === 0) {
236 return range.getBoundingClientRect();
237 }
238 if (filteredRects.length === 1) {
239 return filteredRects[0];
240 }
241 let {
242 top: furthestTop,
243 bottom: furthestBottom,
244 left: furthestLeft,
245 right: furthestRight
246 } = filteredRects[0];
247 for (const { top, bottom, left, right } of filteredRects) {
248 if (top < furthestTop) {
249 furthestTop = top;
250 }
251 if (bottom > furthestBottom) {
252 furthestBottom = bottom;
253 }
254 if (left < furthestLeft) {
255 furthestLeft = left;
256 }
257 if (right > furthestRight) {
258 furthestRight = right;
259 }
260 }
261 return new window.DOMRect(
262 furthestLeft,
263 furthestTop,
264 furthestRight - furthestLeft,
265 furthestBottom - furthestTop
266 );
267 }
268 const { startContainer } = range;
269 const { ownerDocument } = startContainer;
270 if (startContainer.nodeName === "BR") {
271 const { parentNode } = startContainer;
272 assertIsDefined(parentNode, "parentNode");
273 const index = (
274 /** @type {Node[]} */
275 Array.from(parentNode.childNodes).indexOf(startContainer)
276 );
277 assertIsDefined(ownerDocument, "ownerDocument");
278 range = ownerDocument.createRange();
279 range.setStart(parentNode, index);
280 range.setEnd(parentNode, index);
281 }
282 const rects = range.getClientRects();
283 if (rects.length > 1) {
284 return null;
285 }
286 if (rects.length === 1 && startContainer.nodeType === startContainer.TEXT_NODE && range.startOffset > 0 && range.startOffset < /** @type {Text} */
287 startContainer.length) {
288 assertIsDefined(ownerDocument, "ownerDocument");
289 const measure = (start, end) => {
290 const charRange = ownerDocument.createRange();
291 charRange.setStart(startContainer, start);
292 charRange.setEnd(startContainer, end);
293 return charRange.getBoundingClientRect();
294 };
295 const before = measure(range.startOffset - 1, range.startOffset);
296 const after = measure(range.startOffset, range.startOffset + 1);
297 if (before.bottom <= after.top) {
298 return null;
299 }
300 }
301 let rect = rects[0];
302 if (!rect || rect.height === 0) {
303 assertIsDefined(ownerDocument, "ownerDocument");
304 const padNode = ownerDocument.createTextNode("\u200B");
305 range = range.cloneRange();
306 range.insertNode(padNode);
307 rect = range.getClientRects()[0];
308 assertIsDefined(padNode.parentNode, "padNode.parentNode");
309 padNode.parentNode.removeChild(padNode);
310 }
311 return rect;
312 }
313
314 // packages/dom/build-module/dom/compute-caret-rect.mjs
315 function computeCaretRect(win) {
316 const selection = win.getSelection();
317 assertIsDefined(selection, "selection");
318 const range = selection.rangeCount ? selection.getRangeAt(0) : null;
319 if (!range) {
320 return null;
321 }
322 return getRectangleFromRange(range);
323 }
324
325 // packages/dom/build-module/dom/document-has-text-selection.mjs
326 function documentHasTextSelection(doc) {
327 assertIsDefined(doc.defaultView, "doc.defaultView");
328 const selection = doc.defaultView.getSelection();
329 assertIsDefined(selection, "selection");
330 const range = selection.rangeCount ? selection.getRangeAt(0) : null;
331 return !!range && !range.collapsed;
332 }
333
334 // packages/dom/build-module/dom/is-html-input-element.mjs
335 function isHTMLInputElement(node) {
336 return node?.nodeName === "INPUT";
337 }
338
339 // packages/dom/build-module/dom/is-text-field.mjs
340 function isTextField(node) {
341 const nonTextInputs = [
342 "button",
343 "checkbox",
344 "hidden",
345 "file",
346 "radio",
347 "image",
348 "range",
349 "reset",
350 "submit",
351 "number",
352 "email",
353 "time"
354 ];
355 return isHTMLInputElement(node) && node.type && !nonTextInputs.includes(node.type) || node.nodeName === "TEXTAREA" || /** @type {HTMLElement} */
356 node.contentEditable === "true";
357 }
358
359 // packages/dom/build-module/dom/input-field-has-uncollapsed-selection.mjs
360 function inputFieldHasUncollapsedSelection(element) {
361 if (!isHTMLInputElement(element) && !isTextField(element)) {
362 return false;
363 }
364 try {
365 const { selectionStart, selectionEnd } = (
366 /** @type {HTMLInputElement | HTMLTextAreaElement} */
367 element
368 );
369 return (
370 // `null` means the input type doesn't implement selection, thus we
371 // cannot determine whether the selection is collapsed, so we
372 // default to true.
373 selectionStart === null || // when not null, compare the two points
374 selectionStart !== selectionEnd
375 );
376 } catch {
377 return true;
378 }
379 }
380
381 // packages/dom/build-module/dom/document-has-uncollapsed-selection.mjs
382 function documentHasUncollapsedSelection(doc) {
383 return documentHasTextSelection(doc) || !!doc.activeElement && inputFieldHasUncollapsedSelection(doc.activeElement);
384 }
385
386 // packages/dom/build-module/dom/document-has-selection.mjs
387 function documentHasSelection(doc) {
388 return !!doc.activeElement && (isHTMLInputElement(doc.activeElement) || isTextField(doc.activeElement) || documentHasTextSelection(doc));
389 }
390
391 // packages/dom/build-module/dom/get-computed-style.mjs
392 function getComputedStyle(element) {
393 assertIsDefined(
394 element.ownerDocument.defaultView,
395 "element.ownerDocument.defaultView"
396 );
397 return element.ownerDocument.defaultView.getComputedStyle(element);
398 }
399
400 // packages/dom/build-module/dom/get-scroll-container.mjs
401 function getScrollContainer(node, direction = "vertical") {
402 if (!node) {
403 return void 0;
404 }
405 if (direction === "vertical" || direction === "all") {
406 if (node.scrollHeight > node.clientHeight) {
407 const { overflowY } = getComputedStyle(node);
408 if (/(auto|scroll)/.test(overflowY)) {
409 return node;
410 }
411 }
412 }
413 if (direction === "horizontal" || direction === "all") {
414 if (node.scrollWidth > node.clientWidth) {
415 const { overflowX } = getComputedStyle(node);
416 if (/(auto|scroll)/.test(overflowX)) {
417 return node;
418 }
419 }
420 }
421 if (node.ownerDocument === node.parentNode) {
422 return node;
423 }
424 return getScrollContainer(
425 /** @type {Element} */
426 node.parentNode,
427 direction
428 );
429 }
430
431 // packages/dom/build-module/dom/get-offset-parent.mjs
432 function getOffsetParent(node) {
433 let closestElement;
434 while (closestElement = /** @type {Node} */
435 node.parentNode) {
436 if (closestElement.nodeType === closestElement.ELEMENT_NODE) {
437 break;
438 }
439 }
440 if (!closestElement) {
441 return null;
442 }
443 if (getComputedStyle(
444 /** @type {Element} */
445 closestElement
446 ).position !== "static") {
447 return closestElement;
448 }
449 return (
450 /** @type {Node & { offsetParent: Node }} */
451 closestElement.offsetParent
452 );
453 }
454
455 // packages/dom/build-module/dom/is-input-or-text-area.mjs
456 function isInputOrTextArea(element) {
457 return element.tagName === "INPUT" || element.tagName === "TEXTAREA";
458 }
459
460 // packages/dom/build-module/dom/is-entirely-selected.mjs
461 var ZWNBSP = "\uFEFF";
462 function isEntirelySelected(element) {
463 if (isInputOrTextArea(element)) {
464 return element.selectionStart === 0 && element.value.length === element.selectionEnd;
465 }
466 if (!element.isContentEditable) {
467 return true;
468 }
469 const text = element.textContent || "";
470 if (text === "" || text === ZWNBSP) {
471 return true;
472 }
473 const { ownerDocument } = element;
474 const { defaultView } = ownerDocument;
475 assertIsDefined(defaultView, "defaultView");
476 const selection = defaultView.getSelection();
477 assertIsDefined(selection, "selection");
478 const range = selection.rangeCount ? selection.getRangeAt(0) : null;
479 if (!range) {
480 return true;
481 }
482 const { startContainer, endContainer, startOffset, endOffset } = range;
483 if (startContainer === element && endContainer === element && startOffset === 0 && endOffset === element.childNodes.length) {
484 return true;
485 }
486 const lastChild = element.lastChild;
487 assertIsDefined(lastChild, "lastChild");
488 const endContainerContentLength = endContainer.nodeType === endContainer.TEXT_NODE ? (
489 /** @type {Text} */
490 endContainer.data.length
491 ) : endContainer.childNodes.length;
492 return isDeepChild(startContainer, element, "firstChild") && isDeepChild(endContainer, element, "lastChild") && startOffset === 0 && endOffset === endContainerContentLength;
493 }
494 function isDeepChild(query, container, propName) {
495 let candidate = container;
496 do {
497 if (query === candidate) {
498 return true;
499 }
500 candidate = candidate[propName];
501 while (candidate && candidate.nodeType === candidate.TEXT_NODE && candidate.nodeValue === "") {
502 candidate = candidate[propName === "lastChild" ? "previousSibling" : "nextSibling"];
503 }
504 } while (candidate);
505 return false;
506 }
507
508 // packages/dom/build-module/dom/is-form-element.mjs
509 function isFormElement(element) {
510 if (!element) {
511 return false;
512 }
513 const { tagName } = element;
514 const checkForInputTextarea = isInputOrTextArea(element);
515 return checkForInputTextarea || tagName === "BUTTON" || tagName === "SELECT";
516 }
517
518 // packages/dom/build-module/dom/is-rtl.mjs
519 function isRTL(element) {
520 return getComputedStyle(element).direction === "rtl";
521 }
522
523 // packages/dom/build-module/dom/get-range-height.mjs
524 function getRangeHeight(range) {
525 const rects = Array.from(range.getClientRects());
526 if (!rects.length) {
527 return;
528 }
529 const highestTop = Math.min(...rects.map(({ top }) => top));
530 const lowestBottom = Math.max(...rects.map(({ bottom }) => bottom));
531 return lowestBottom - highestTop;
532 }
533
534 // packages/dom/build-module/dom/is-selection-forward.mjs
535 function isSelectionForward(selection) {
536 const { anchorNode, focusNode, anchorOffset, focusOffset } = selection;
537 assertIsDefined(anchorNode, "anchorNode");
538 assertIsDefined(focusNode, "focusNode");
539 const position = anchorNode.compareDocumentPosition(focusNode);
540 if (position & anchorNode.DOCUMENT_POSITION_PRECEDING) {
541 return false;
542 }
543 if (position & anchorNode.DOCUMENT_POSITION_FOLLOWING) {
544 return true;
545 }
546 if (position === 0) {
547 return anchorOffset <= focusOffset;
548 }
549 return true;
550 }
551
552 // packages/dom/build-module/dom/caret-range-from-point.mjs
553 function caretRangeFromPoint(doc, x, y) {
554 if (doc.caretPositionFromPoint) {
555 const point = doc.caretPositionFromPoint(x, y);
556 if (!point) {
557 return null;
558 }
559 const range = doc.createRange();
560 range.setStart(point.offsetNode, point.offset);
561 range.collapse(true);
562 return range;
563 }
564 if (doc.caretRangeFromPoint) {
565 return doc.caretRangeFromPoint(x, y);
566 }
567 return null;
568 }
569
570 // packages/dom/build-module/dom/hidden-caret-range-from-point.mjs
571 function hiddenCaretRangeFromPoint(doc, x, y, container) {
572 const originalZIndex = container.style.zIndex;
573 const originalPosition = container.style.position;
574 const originalBorderRadius = container.style.borderRadius;
575 const { position = "static" } = getComputedStyle(container);
576 if (position === "static") {
577 container.style.position = "relative";
578 }
579 container.style.zIndex = "10000";
580 container.style.borderRadius = "0";
581 const range = caretRangeFromPoint(doc, x, y);
582 container.style.zIndex = originalZIndex;
583 container.style.position = originalPosition;
584 container.style.borderRadius = originalBorderRadius;
585 return range;
586 }
587
588 // packages/dom/build-module/dom/scroll-if-no-range.mjs
589 function scrollIfNoRange(container, alignToTop, callback) {
590 let range = callback();
591 if (!range || !range.startContainer || !container.contains(range.startContainer)) {
592 container.scrollIntoView(alignToTop);
593 range = callback();
594 if (!range || !range.startContainer || !container.contains(range.startContainer)) {
595 return null;
596 }
597 }
598 return range;
599 }
600
601 // packages/dom/build-module/dom/is-edge.mjs
602 function isEdge(container, isReverse, onlyVertical = false) {
603 if (isInputOrTextArea(container) && typeof container.selectionStart === "number") {
604 if (container.selectionStart !== container.selectionEnd) {
605 return false;
606 }
607 if (isReverse) {
608 return container.selectionStart === 0;
609 }
610 return container.value.length === container.selectionStart;
611 }
612 if (!container.isContentEditable) {
613 return true;
614 }
615 const { ownerDocument } = container;
616 const { defaultView } = ownerDocument;
617 assertIsDefined(defaultView, "defaultView");
618 const selection = defaultView.getSelection();
619 if (!selection || !selection.rangeCount) {
620 return false;
621 }
622 const range = selection.getRangeAt(0);
623 const collapsedRange = range.cloneRange();
624 const isForward = isSelectionForward(selection);
625 const isCollapsed = selection.isCollapsed;
626 if (!isCollapsed) {
627 collapsedRange.collapse(!isForward);
628 }
629 const collapsedRangeRect = getRectangleFromRange(collapsedRange);
630 const rangeRect = getRectangleFromRange(range);
631 if (!collapsedRangeRect || !rangeRect) {
632 return false;
633 }
634 const rangeHeight = getRangeHeight(range);
635 if (!isCollapsed && rangeHeight && rangeHeight > collapsedRangeRect.height && isForward === isReverse) {
636 return false;
637 }
638 const isReverseDir = isRTL(container) ? !isReverse : isReverse;
639 const containerRect = container.getBoundingClientRect();
640 const x = isReverseDir ? containerRect.left + 1 : containerRect.right - 1;
641 const y = isReverse ? containerRect.top + 1 : containerRect.bottom - 1;
642 const isFarFromVerticalEdge = (y < 0 || y > defaultView.innerHeight) && rangeRect.top >= 0 && rangeRect.bottom <= defaultView.innerHeight;
643 const isFarFromHorizontalEdge = (x < 0 || x > defaultView.innerWidth) && rangeRect.left >= 0 && rangeRect.right <= defaultView.innerWidth;
644 if (isFarFromVerticalEdge || !onlyVertical && isFarFromHorizontalEdge) {
645 return false;
646 }
647 const testRange = scrollIfNoRange(
648 container,
649 isReverse,
650 () => hiddenCaretRangeFromPoint(ownerDocument, x, y, container)
651 );
652 if (!testRange) {
653 return false;
654 }
655 const testRect = getRectangleFromRange(testRange);
656 if (!testRect) {
657 return false;
658 }
659 const verticalSide = isReverse ? "top" : "bottom";
660 const horizontalSide = isReverseDir ? "left" : "right";
661 const verticalDiff = testRect[verticalSide] - rangeRect[verticalSide];
662 const horizontalDiff = testRect[horizontalSide] - collapsedRangeRect[horizontalSide];
663 const hasVerticalDiff = Math.abs(verticalDiff) <= 1;
664 const hasHorizontalDiff = Math.abs(horizontalDiff) <= 1;
665 return onlyVertical ? hasVerticalDiff : hasVerticalDiff && hasHorizontalDiff;
666 }
667
668 // packages/dom/build-module/dom/is-horizontal-edge.mjs
669 function isHorizontalEdge(container, isReverse) {
670 return isEdge(container, isReverse);
671 }
672
673 // packages/dom/build-module/dom/is-number-input.mjs
674 var import_deprecated = __toESM(require_deprecated(), 1);
675 function isNumberInput(node) {
676 (0, import_deprecated.default)("wp.dom.isNumberInput", {
677 since: "6.1",
678 version: "6.5"
679 });
680 return isHTMLInputElement(node) && node.type === "number" && !isNaN(node.valueAsNumber);
681 }
682
683 // packages/dom/build-module/dom/is-vertical-edge.mjs
684 function isVerticalEdge(container, isReverse) {
685 return isEdge(container, isReverse, true);
686 }
687
688 // packages/dom/build-module/dom/place-caret-at-edge.mjs
689 function getRange(container, isReverse, x) {
690 const { ownerDocument } = container;
691 const isReverseDir = isRTL(container) ? !isReverse : isReverse;
692 const containerRect = container.getBoundingClientRect();
693 if (x === void 0) {
694 x = isReverse ? containerRect.right - 1 : containerRect.left + 1;
695 } else if (x <= containerRect.left) {
696 x = containerRect.left + 1;
697 } else if (x >= containerRect.right) {
698 x = containerRect.right - 1;
699 }
700 const y = isReverseDir ? containerRect.bottom - 1 : containerRect.top + 1;
701 return hiddenCaretRangeFromPoint(ownerDocument, x, y, container);
702 }
703 function placeCaretAtEdge(container, isReverse, x) {
704 if (!container) {
705 return;
706 }
707 container.focus();
708 if (isInputOrTextArea(container)) {
709 if (typeof container.selectionStart !== "number") {
710 return;
711 }
712 if (isReverse) {
713 container.selectionStart = container.value.length;
714 container.selectionEnd = container.value.length;
715 } else {
716 container.selectionStart = 0;
717 container.selectionEnd = 0;
718 }
719 return;
720 }
721 if (container.contentEditable !== "true") {
722 return;
723 }
724 const range = scrollIfNoRange(
725 container,
726 isReverse,
727 () => getRange(container, isReverse, x)
728 );
729 if (!range) {
730 return;
731 }
732 const { ownerDocument } = container;
733 const { defaultView } = ownerDocument;
734 assertIsDefined(defaultView, "defaultView");
735 const selection = defaultView.getSelection();
736 assertIsDefined(selection, "selection");
737 selection.removeAllRanges();
738 selection.addRange(range);
739 }
740
741 // packages/dom/build-module/dom/place-caret-at-horizontal-edge.mjs
742 function placeCaretAtHorizontalEdge(container, isReverse) {
743 return placeCaretAtEdge(container, isReverse, void 0);
744 }
745
746 // packages/dom/build-module/dom/place-caret-at-vertical-edge.mjs
747 function placeCaretAtVerticalEdge(container, isReverse, rect) {
748 return placeCaretAtEdge(container, isReverse, rect?.left);
749 }
750
751 // packages/dom/build-module/dom/insert-after.mjs
752 function insertAfter(newNode, referenceNode) {
753 assertIsDefined(referenceNode.parentNode, "referenceNode.parentNode");
754 referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
755 }
756
757 // packages/dom/build-module/dom/remove.mjs
758 function remove(node) {
759 assertIsDefined(node.parentNode, "node.parentNode");
760 node.parentNode.removeChild(node);
761 }
762
763 // packages/dom/build-module/dom/replace.mjs
764 function replace(processedNode, newNode) {
765 assertIsDefined(processedNode.parentNode, "processedNode.parentNode");
766 insertAfter(newNode, processedNode.parentNode);
767 remove(processedNode);
768 }
769
770 // packages/dom/build-module/dom/unwrap.mjs
771 function unwrap(node) {
772 const parent = node.parentNode;
773 assertIsDefined(parent, "node.parentNode");
774 while (node.firstChild) {
775 parent.insertBefore(node.firstChild, node);
776 }
777 parent.removeChild(node);
778 }
779
780 // packages/dom/build-module/dom/replace-tag.mjs
781 function replaceTag(node, tagName) {
782 const newNode = node.ownerDocument.createElement(tagName);
783 while (node.firstChild) {
784 newNode.appendChild(node.firstChild);
785 }
786 assertIsDefined(node.parentNode, "node.parentNode");
787 node.parentNode.replaceChild(newNode, node);
788 return newNode;
789 }
790
791 // packages/dom/build-module/dom/wrap.mjs
792 function wrap(newNode, referenceNode) {
793 assertIsDefined(referenceNode.parentNode, "referenceNode.parentNode");
794 referenceNode.parentNode.insertBefore(newNode, referenceNode);
795 newNode.appendChild(referenceNode);
796 }
797
798 // packages/dom/build-module/dom/safe-html.mjs
799 function safeHTML(html) {
800 const { body } = document.implementation.createHTMLDocument("");
801 body.innerHTML = html;
802 const elements = body.getElementsByTagName("*");
803 let elementIndex = elements.length;
804 while (elementIndex--) {
805 const element = elements[elementIndex];
806 if (element.tagName === "SCRIPT") {
807 remove(element);
808 } else {
809 let attributeIndex = element.attributes.length;
810 while (attributeIndex--) {
811 const { name: key } = element.attributes[attributeIndex];
812 if (key.startsWith("on")) {
813 element.removeAttribute(key);
814 }
815 }
816 }
817 }
818 return body.innerHTML;
819 }
820
821 // packages/dom/build-module/dom/strip-html.mjs
822 function stripHTML(html) {
823 html = safeHTML(html);
824 const doc = document.implementation.createHTMLDocument("");
825 doc.body.innerHTML = html;
826 return doc.body.textContent || "";
827 }
828
829 // packages/dom/build-module/dom/is-empty.mjs
830 function isEmpty(element) {
831 switch (element.nodeType) {
832 case element.TEXT_NODE:
833 return /^[ \f\n\r\t\v\u00a0]*$/.test(element.nodeValue || "");
834 case element.ELEMENT_NODE:
835 if (element.hasAttributes()) {
836 return false;
837 } else if (!element.hasChildNodes()) {
838 return true;
839 }
840 return (
841 /** @type {Element[]} */
842 Array.from(element.childNodes).every(isEmpty)
843 );
844 default:
845 return true;
846 }
847 }
848
849 // packages/dom/build-module/phrasing-content.mjs
850 var textContentSchema = {
851 strong: {},
852 em: {},
853 s: {},
854 del: {},
855 ins: {},
856 a: { attributes: ["href", "target", "rel", "id"] },
857 code: {},
858 abbr: { attributes: ["title"] },
859 sub: {},
860 sup: {},
861 br: {},
862 small: {},
863 // To do: fix blockquote.
864 // cite: {},
865 q: { attributes: ["cite"] },
866 dfn: { attributes: ["title"] },
867 data: { attributes: ["value"] },
868 time: { attributes: ["datetime"] },
869 var: {},
870 samp: {},
871 kbd: {},
872 i: {},
873 b: {},
874 u: {},
875 mark: {},
876 ruby: {},
877 rt: {},
878 rp: {},
879 bdi: { attributes: ["dir"] },
880 bdo: { attributes: ["dir"] },
881 wbr: {},
882 "#text": {}
883 };
884 var embeddedContentSchema = {
885 audio: {
886 attributes: [
887 "src",
888 "preload",
889 "autoplay",
890 "mediagroup",
891 "loop",
892 "muted"
893 ]
894 },
895 canvas: { attributes: ["width", "height"] },
896 embed: { attributes: ["src", "type", "width", "height"] },
897 img: {
898 attributes: [
899 "alt",
900 "src",
901 "srcset",
902 "usemap",
903 "ismap",
904 "width",
905 "height"
906 ]
907 },
908 object: {
909 attributes: [
910 "data",
911 "type",
912 "name",
913 "usemap",
914 "form",
915 "width",
916 "height"
917 ]
918 },
919 video: {
920 attributes: [
921 "src",
922 "poster",
923 "preload",
924 "playsinline",
925 "autoplay",
926 "mediagroup",
927 "loop",
928 "muted",
929 "controls",
930 "width",
931 "height"
932 ]
933 },
934 math: {
935 attributes: ["display", "xmlns"],
936 children: "*"
937 }
938 };
939 var excludedElements = ["#text", "br", "wbr"];
940 Object.keys(textContentSchema).filter((element) => !excludedElements.includes(element)).forEach((tag) => {
941 const { [tag]: removedTag, ...restSchema } = textContentSchema;
942 textContentSchema[tag].children = {
943 ...restSchema,
944 img: embeddedContentSchema.img
945 };
946 });
947 var phrasingContentSchema = {
948 ...textContentSchema,
949 ...embeddedContentSchema
950 };
951 function getPhrasingContentSchema(context) {
952 if (context !== "paste") {
953 return phrasingContentSchema;
954 }
955 const {
956 u,
957 // Used to mark misspelling. Shouldn't be pasted.
958 abbr,
959 // Invisible.
960 data,
961 // Invisible.
962 time,
963 // Invisible.
964 wbr,
965 // Invisible.
966 bdi,
967 // Invisible.
968 bdo,
969 // Invisible.
970 ...remainingContentSchema
971 } = {
972 ...phrasingContentSchema,
973 // We shouldn't paste potentially sensitive information which is not
974 // visible to the user when pasted, so strip the attributes.
975 ins: { children: phrasingContentSchema.ins.children },
976 del: { children: phrasingContentSchema.del.children }
977 };
978 return remainingContentSchema;
979 }
980 function isPhrasingContent(node) {
981 const tag = node.nodeName.toLowerCase();
982 return getPhrasingContentSchema().hasOwnProperty(tag) || tag === "span";
983 }
984 function isTextContent(node) {
985 const tag = node.nodeName.toLowerCase();
986 return textContentSchema.hasOwnProperty(tag) || tag === "span";
987 }
988
989 // packages/dom/build-module/dom/is-element.mjs
990 function isElement(node) {
991 return !!node && node.nodeType === node.ELEMENT_NODE;
992 }
993
994 // packages/dom/build-module/dom/clean-node-list.mjs
995 var noop = () => {
996 };
997 function cleanNodeList(nodeList, doc, schema, inline) {
998 Array.from(nodeList).forEach(
999 (node) => {
1000 const tag = node.nodeName.toLowerCase();
1001 if (schema.hasOwnProperty(tag) && (!schema[tag].isMatch || schema[tag].isMatch?.(node))) {
1002 if (isElement(node)) {
1003 const {
1004 attributes = [],
1005 classes = [],
1006 children,
1007 require: require2 = [],
1008 allowEmpty
1009 } = schema[tag];
1010 if (children && !allowEmpty && isEmpty(node)) {
1011 if (isPhrasingContent(node) && node.hasChildNodes()) {
1012 unwrap(node);
1013 } else {
1014 remove(node);
1015 }
1016 return;
1017 }
1018 if (node.hasAttributes()) {
1019 Array.from(node.attributes).forEach(({ name }) => {
1020 if (name !== "class" && !attributes.includes(name)) {
1021 node.removeAttribute(name);
1022 }
1023 });
1024 if (node.classList && node.classList.length) {
1025 const mattchers = classes.map((item) => {
1026 if (item === "*") {
1027 return () => true;
1028 } else if (typeof item === "string") {
1029 return (className) => className === item;
1030 } else if (item instanceof RegExp) {
1031 return (className) => item.test(className);
1032 }
1033 return noop;
1034 });
1035 Array.from(node.classList).forEach((name) => {
1036 if (!mattchers.some(
1037 (isMatch) => isMatch(name)
1038 )) {
1039 node.classList.remove(name);
1040 }
1041 });
1042 if (!node.classList.length) {
1043 node.removeAttribute("class");
1044 }
1045 }
1046 }
1047 if (node.hasChildNodes()) {
1048 if (children === "*") {
1049 return;
1050 }
1051 if (children) {
1052 if (require2.length && !node.querySelector(require2.join(","))) {
1053 cleanNodeList(
1054 node.childNodes,
1055 doc,
1056 schema,
1057 inline
1058 );
1059 unwrap(node);
1060 } else if (node.parentNode && node.parentNode.nodeName === "BODY" && isPhrasingContent(node)) {
1061 cleanNodeList(
1062 node.childNodes,
1063 doc,
1064 schema,
1065 inline
1066 );
1067 if (Array.from(node.childNodes).some(
1068 (child) => !isPhrasingContent(child)
1069 )) {
1070 unwrap(node);
1071 }
1072 } else {
1073 cleanNodeList(
1074 node.childNodes,
1075 doc,
1076 children,
1077 inline
1078 );
1079 }
1080 } else {
1081 while (node.firstChild) {
1082 remove(node.firstChild);
1083 }
1084 }
1085 }
1086 }
1087 } else {
1088 cleanNodeList(node.childNodes, doc, schema, inline);
1089 if (inline && !isPhrasingContent(node) && node.nextElementSibling) {
1090 insertAfter(doc.createElement("br"), node);
1091 }
1092 unwrap(node);
1093 }
1094 }
1095 );
1096 }
1097
1098 // packages/dom/build-module/dom/remove-invalid-html.mjs
1099 function removeInvalidHTML(HTML, schema, inline) {
1100 const doc = document.implementation.createHTMLDocument("");
1101 doc.body.innerHTML = HTML;
1102 cleanNodeList(doc.body.childNodes, doc, schema, inline);
1103 return doc.body.innerHTML;
1104 }
1105
1106 // packages/dom/build-module/data-transfer.mjs
1107 function getFilesFromDataTransfer(dataTransfer) {
1108 const files = Array.from(dataTransfer.files);
1109 Array.from(dataTransfer.items).forEach((item) => {
1110 const file = item.getAsFile();
1111 if (file && !files.find(
1112 ({ name, type, size }) => name === file.name && type === file.type && size === file.size
1113 )) {
1114 files.push(file);
1115 }
1116 });
1117 return files;
1118 }
1119
1120 // packages/dom/build-module/index.mjs
1121 var focus = { focusable: focusable_exports, tabbable: tabbable_exports };
1122 return __toCommonJS(index_exports);
1123 })();
1124 (window.wp ||= {}).dom = wp.dom;
1125 })();
1126 //# sourceMappingURL=index.js.map
1127