@wordpress/components
Version:
UI components for WordPress.
230 lines (226 loc) • 8.25 kB
JavaScript
// packages/components/src/draggable/index.tsx
import { throttle } from "@wordpress/compose";
import { useEffect, useRef } from "@wordpress/element";
import { getWpCompatOverlaySlot } from "@wordpress/ui";
// packages/style-runtime/src/index.ts
var STYLE_HASH_ATTRIBUTE = "data-wp-hash";
function getRuntime() {
const globalScope = globalThis;
if (globalScope.__wpStyleRuntime) {
return globalScope.__wpStyleRuntime;
}
globalScope.__wpStyleRuntime = {
documents: /* @__PURE__ */ new Map(),
styles: /* @__PURE__ */ new Map(),
injectedStyles: /* @__PURE__ */ new WeakMap()
};
if (typeof document !== "undefined") {
registerDocument(document);
}
return globalScope.__wpStyleRuntime;
}
function documentContainsStyleHash(targetDocument, hash) {
if (!targetDocument.head) {
return false;
}
for (const style of targetDocument.head.querySelectorAll(`style[${STYLE_HASH_ATTRIBUTE}]`)) {
if (style.getAttribute(STYLE_HASH_ATTRIBUTE) === hash) {
return true;
}
}
return false;
}
function injectStyle(targetDocument, hash, css) {
if (!targetDocument.head) {
return;
}
const runtime = getRuntime();
let injectedStyles = runtime.injectedStyles.get(targetDocument);
if (!injectedStyles) {
injectedStyles = /* @__PURE__ */ new Set();
runtime.injectedStyles.set(targetDocument, injectedStyles);
}
if (injectedStyles.has(hash)) {
return;
}
if (documentContainsStyleHash(targetDocument, hash)) {
injectedStyles.add(hash);
return;
}
const style = targetDocument.createElement("style");
style.setAttribute(STYLE_HASH_ATTRIBUTE, hash);
style.appendChild(targetDocument.createTextNode(css));
targetDocument.head.appendChild(style);
injectedStyles.add(hash);
}
function registerDocument(targetDocument) {
const runtime = getRuntime();
runtime.documents.set(targetDocument, (runtime.documents.get(targetDocument) ?? 0) + 1);
for (const [hash, css] of runtime.styles) {
injectStyle(targetDocument, hash, css);
}
return () => {
const count = runtime.documents.get(targetDocument);
if (count === void 0) {
return;
}
if (count <= 1) {
runtime.documents.delete(targetDocument);
return;
}
runtime.documents.set(targetDocument, count - 1);
};
}
function registerStyle(hash, css) {
const runtime = getRuntime();
runtime.styles.set(hash, css);
for (const targetDocument of runtime.documents.keys()) {
injectStyle(targetDocument, hash, css);
}
}
// packages/components/src/draggable/style.module.scss
if (typeof process === "undefined" || process.env.NODE_ENV !== "test") {
registerStyle("e7e88c1781", "._3476c2e530687f96__invisible-drag-image{height:50px;left:-1000px;position:fixed;width:50px}._6f00e51ab7574306__clone{background:transparent;padding:0;pointer-events:none;position:fixed}._6f00e51ab7574306__clone:not(._664ecd37377558df__is-in-compat-slot){z-index:1000000000}body.is-dragging-components-draggable{cursor:move;cursor:grabbing!important}");
}
var style_module_default = { "invisible-drag-image": "_3476c2e530687f96__invisible-drag-image", "clone": "_6f00e51ab7574306__clone", "is-in-compat-slot": "_664ecd37377558df__is-in-compat-slot" };
// packages/components/src/draggable/index.tsx
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
var dragImageClasses = [style_module_default["invisible-drag-image"], "components-draggable__invisible-drag-image"].filter(Boolean);
var cloneWrapperClasses = [style_module_default.clone, "components-draggable__clone"].filter(Boolean);
var bodyClass = "is-dragging-components-draggable";
var clonePadding = 0;
function Draggable({
children,
onDragStart,
onDragOver,
onDragEnd,
appendToOwnerDocument = false,
cloneClassname,
elementId,
transferData,
__experimentalTransferDataType: transferDataType = "text",
__experimentalDragComponent: dragComponent
}) {
const dragComponentRef = useRef(null);
const cleanupRef = useRef(() => {
});
function end(event) {
event.preventDefault();
cleanupRef.current();
if (onDragEnd) {
onDragEnd(event);
}
}
function start(event) {
const {
ownerDocument
} = event.target;
const slot = getWpCompatOverlaySlot();
const compatSlot = slot?.ownerDocument === ownerDocument ? slot : null;
event.dataTransfer.setData(transferDataType, JSON.stringify(transferData));
const cloneWrapper = ownerDocument.createElement("div");
cloneWrapper.style.top = "0";
cloneWrapper.style.left = "0";
const dragImage = ownerDocument.createElement("div");
if ("function" === typeof event.dataTransfer.setDragImage) {
dragImage.classList.add(...dragImageClasses);
ownerDocument.body.appendChild(dragImage);
event.dataTransfer.setDragImage(dragImage, 0, 0);
}
cloneWrapper.classList.add(...cloneWrapperClasses);
const inSlotClass = style_module_default["is-in-compat-slot"];
if (compatSlot && inSlotClass) {
cloneWrapper.classList.add(inSlotClass);
}
if (cloneClassname) {
cloneWrapper.classList.add(cloneClassname);
}
let x = 0;
let y = 0;
if (dragComponentRef.current) {
x = event.clientX;
y = event.clientY;
cloneWrapper.style.transform = `translate( ${x}px, ${y}px )`;
const clonedDragComponent = ownerDocument.createElement("div");
clonedDragComponent.innerHTML = dragComponentRef.current.innerHTML;
cloneWrapper.appendChild(clonedDragComponent);
(compatSlot ?? ownerDocument.body).appendChild(cloneWrapper);
} else {
const element = ownerDocument.getElementById(elementId);
const elementRect = element.getBoundingClientRect();
const elementWrapper = element.parentNode;
const elementTopOffset = elementRect.top;
const elementLeftOffset = elementRect.left;
cloneWrapper.style.width = `${elementRect.width + clonePadding * 2}px`;
const clone = element.cloneNode(true);
clone.id = `clone-${elementId}`;
x = elementLeftOffset - clonePadding;
y = elementTopOffset - clonePadding;
cloneWrapper.style.transform = `translate( ${x}px, ${y}px )`;
Array.from(clone.querySelectorAll("iframe")).forEach((child) => child.parentNode?.removeChild(child));
cloneWrapper.appendChild(clone);
if (compatSlot) {
compatSlot.appendChild(cloneWrapper);
} else if (appendToOwnerDocument) {
ownerDocument.body.appendChild(cloneWrapper);
} else {
elementWrapper?.appendChild(cloneWrapper);
}
}
let cursorLeft = event.clientX;
let cursorTop = event.clientY;
function over(e) {
if (cursorLeft === e.clientX && cursorTop === e.clientY) {
return;
}
const nextX = x + e.clientX - cursorLeft;
const nextY = y + e.clientY - cursorTop;
cloneWrapper.style.transform = `translate( ${nextX}px, ${nextY}px )`;
cursorLeft = e.clientX;
cursorTop = e.clientY;
x = nextX;
y = nextY;
if (onDragOver) {
onDragOver(e);
}
}
const throttledDragOver = throttle(over, 16);
ownerDocument.addEventListener("dragover", throttledDragOver);
ownerDocument.body.classList.add(bodyClass);
if (onDragStart) {
onDragStart(event);
}
cleanupRef.current = () => {
if (cloneWrapper && cloneWrapper.parentNode) {
cloneWrapper.parentNode.removeChild(cloneWrapper);
}
if (dragImage && dragImage.parentNode) {
dragImage.parentNode.removeChild(dragImage);
}
ownerDocument.body.classList.remove(bodyClass);
ownerDocument.removeEventListener("dragover", throttledDragOver);
};
}
useEffect(() => () => {
cleanupRef.current();
}, []);
return /* @__PURE__ */ _jsxs(_Fragment, {
children: [children({
onDraggableStart: start,
onDraggableEnd: end
}), dragComponent && /* @__PURE__ */ _jsx("div", {
className: "components-draggable-drag-component-root",
style: {
display: "none"
},
ref: dragComponentRef,
children: dragComponent
})]
});
}
var draggable_default = Draggable;
export {
Draggable,
draggable_default as default
};
//# sourceMappingURL=index.mjs.map