PluginProbe
Gutenberg / 22.9.0
Gutenberg v22.9.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 7.4.0 All 402 releases
gutenberg / build / scripts / dom / index.js

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

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