@carbon/ibm-products
Version:
Carbon for IBM Products
92 lines (88 loc) • 2.49 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2025
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Makes a given element draggable using a handle element.
*@param draggable - object which accepts el and optional attributes handle,focusableInHandle,dragStep and shiftDragStep
*/
function makeDraggable(_ref) {
let {
el,
dragHandle,
focusableDragHandle,
dragStep,
shiftDragStep
} = _ref;
const computedStyle = window.getComputedStyle(el);
if (dragHandle) {
dragHandle.style.cursor = 'move';
el.style.cursor = 'default';
} else {
el.style.cursor = 'move';
}
const position = computedStyle.position;
if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') {
el.style.position = 'relative';
}
let isDragging = false;
let offsetX = 0;
let offsetY = 0;
function onKeyDown(e) {
const distance = e.shiftKey ? shiftDragStep ?? 32 : dragStep ?? 8;
switch (e.key) {
case 'Enter':
case ' ':
e.preventDefault();
break;
case 'ArrowLeft':
el.style.left = `${el.offsetLeft - distance}px`;
break;
case 'ArrowRight':
el.style.left = `${el.offsetLeft + distance}px`;
break;
case 'ArrowUp':
el.style.top = `${el.offsetTop - distance}px`;
break;
case 'ArrowDown':
el.style.top = `${el.offsetTop + distance}px`;
break;
}
}
function onMouseDown(e) {
const isTargetInHandle = dragHandle ? dragHandle.contains(e.target) : el.contains(e.target);
if (!isTargetInHandle) {
return;
}
offsetX = e.clientX - el.offsetLeft;
offsetY = e.clientY - el.offsetTop;
isDragging = true;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp, {
once: true
});
}
function onMouseMove(e) {
if (!isDragging) {
return;
}
el.style.left = `${e.clientX - offsetX}px`;
el.style.top = `${e.clientY - offsetY}px`;
}
function onMouseUp() {
if (!isDragging) {
return;
}
isDragging = false;
document.removeEventListener('mousemove', onMouseMove);
}
if (dragHandle) {
dragHandle.addEventListener('mousedown', onMouseDown);
} else {
el.addEventListener('mousedown', onMouseDown);
}
focusableDragHandle?.addEventListener('keydown', onKeyDown);
}
export { makeDraggable };