aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
143 lines (140 loc) • 4.16 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import { cn } from '../../lib/utilsComprehensive.js';
import { GripVertical } from 'lucide-react';
import { useState, useRef, useCallback, useEffect } from 'react';
import '../../primitives/GlassCore.js';
import '../../primitives/glass/GlassAdvanced.js';
import '../../primitives/OptimizedGlassCore.js';
import '../../primitives/glass/OptimizedGlassAdvanced.js';
import '../../primitives/MotionNative.js';
import { MotionFramer } from '../../primitives/motion/MotionFramer.js';
/**
* GlassDraggable component
* Makes any element draggable with visual feedback
*/
const GlassDraggable = ({
id,
type,
data,
handle,
children,
disabled = false,
onDragStart,
onDragEnd,
className,
...props
}) => {
const [isDragging, setIsDragging] = useState(false);
const [dragOffset, setDragOffset] = useState({
x: 0,
y: 0
});
const dragRef = useRef(null);
const dragStartPos = useRef({
x: 0,
y: 0
});
const elementStartPos = useRef({
x: 0,
y: 0
});
const dragData = {
id,
type,
data
};
// Handle mouse down
const handleMouseDown = useCallback(e => {
if (disabled) return;
e.preventDefault();
const rect = dragRef.current?.getBoundingClientRect();
if (!rect) return;
dragStartPos.current = {
x: e.clientX,
y: e.clientY
};
elementStartPos.current = {
x: rect.left,
y: rect.top
};
setIsDragging(true);
setDragOffset({
x: 0,
y: 0
});
onDragStart?.(dragData);
// Add global event listeners
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
}, [disabled, dragData, onDragStart]);
// Handle mouse move
const handleMouseMove = useCallback(e => {
if (!isDragging) return;
const deltaX = e.clientX - dragStartPos.current.x;
const deltaY = e.clientY - dragStartPos.current.y;
setDragOffset({
x: deltaX,
y: deltaY
});
}, [isDragging]);
// Handle mouse up
const handleMouseUp = useCallback(() => {
if (!isDragging) return;
setIsDragging(false);
setDragOffset({
x: 0,
y: 0
});
onDragEnd?.(dragData);
// Remove global event listeners
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
}, [isDragging, dragData, onDragEnd]);
// Clean up event listeners
useEffect(() => {
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
}, [handleMouseMove, handleMouseUp]);
// Default drag handle
const defaultHandle = handle || jsx("div", {
className: 'glass-flex glass-items-center glass-justify-center w-6 h-6 text-primary/60 hover:text-primary cursor-grab active:cursor-grabbing',
children: jsx(GripVertical, {
className: 'w-4 h-4'
})
});
return jsxs(MotionFramer, {
"data-glass-component": true,
preset: "fadeIn",
className: cn("relative cursor-grab active:cursor-grabbing select-none", isDragging && "z-50", disabled && "cursor-not-allowed opacity-50", className),
style: isDragging ? {
transform: `translate(${dragOffset.x}px, ${dragOffset.y}px)`,
zIndex: 50
} : undefined,
ref: dragRef,
onMouseDown: handleMouseDown,
...props,
children: [jsx("div", {
className: 'absolute glass-top-2 right-2 z-10',
children: defaultHandle
}), jsx("div", {
className: cn("transition-all duration-200", isDragging && "shadow-2xl scale-105 rotate-2"),
children: children
}), isDragging && jsx("div", {
className: 'fixed pointer-events-none z-40 opacity-50',
style: {
left: elementStartPos.current.x,
top: elementStartPos.current.y,
transform: `translate(${dragOffset.x}px, ${dragOffset.y}px)`
},
children: jsx("div", {
className: 'scale-95',
children: children
})
})]
});
};
export { GlassDraggable, GlassDraggable as default };
//# sourceMappingURL=GlassDraggable.js.map