This commit is contained in:
2025-10-21 19:42:39 +05:00
2 changed files with 64 additions and 4 deletions
+61 -1
View File
@@ -7,6 +7,7 @@ export interface Position {
left?: number | string;
right?: number | string;
bottom?: number | string;
transform?: string;
}
export type Corner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
@@ -20,6 +21,10 @@ interface DraggableContainerProps {
autoAlign?: boolean;
/** Ограничить перетаскивание границами окна (по умолчанию false) */
constrainToBounds?: boolean;
/** Центрировать контейнер по вертикали (имеет приоритет над initialCorner и initialPosition) */
centerVertical?: boolean;
/** Центрировать контейнер по горизонтали (имеет приоритет над initialCorner и initialPosition) */
centerHorizontal?: boolean;
/** Начальный угол экрана (имеет приоритет над initialPosition) */
initialCorner?: Corner;
/** Начальная позиция контейнера (используется если не указан initialCorner) */
@@ -47,6 +52,24 @@ interface DraggableContainerProps {
* </DraggableContainer>
*
* @example
* // Размещение по центру экрана (вертикально и горизонтально)
* <DraggableContainer centerVertical={true} centerHorizontal={true}>
* <YourContent />
* </DraggableContainer>
*
* @example
* // Центрирование только по вертикали
* <DraggableContainer centerVertical={true}>
* <YourContent />
* </DraggableContainer>
*
* @example
* // Центрирование только по горизонтали
* <DraggableContainer centerHorizontal={true}>
* <YourContent />
* </DraggableContainer>
*
* @example
* // С указанием начального угла и отступами в процентах
* <DraggableContainer initialCorner="bottom-right" padding="2%">
* <YourContent />
@@ -75,6 +98,8 @@ export default function DraggableContainer({
enableSnapping = false,
autoAlign = false,
constrainToBounds = false,
centerVertical = false,
centerHorizontal = false,
initialCorner,
initialPosition,
padding = "16px",
@@ -105,6 +130,32 @@ export default function DraggableContainer({
// Определяем начальную позицию
const getInitialPosition = (): Position => {
// Если используется центрирование
if (centerVertical || centerHorizontal) {
const position: Position = {};
const transforms: string[] = [];
if (centerVertical) {
position.top = "50%";
transforms.push("translateY(-50%)");
} else {
position.top = padding;
}
if (centerHorizontal) {
position.left = "50%";
transforms.push("translateX(-50%)");
} else {
position.left = padding;
}
if (transforms.length > 0) {
position.transform = transforms.join(" ");
}
return position;
}
if (initialCorner) {
return getPositionFromCorner(initialCorner);
}
@@ -112,7 +163,7 @@ export default function DraggableContainer({
return initialPosition;
}
// По умолчанию - верхний правый угол
return { top: padding, right: padding };
return { top: padding, left: padding };
};
const [position, setPosition] = useState<Position>(getInitialPosition());
@@ -173,6 +224,14 @@ export default function DraggableContainer({
setDragStartAlignment(getAlignmentClassesFromPosition(position));
}
// Если контейнер был по центру с transform, убираем transform и используем абсолютную позицию
if (position.transform) {
setPosition({
top: rect.top,
left: rect.left,
});
}
dragRef.current = {
isDragging: true,
startX: clientX,
@@ -331,6 +390,7 @@ export default function DraggableContainer({
if (position.right !== undefined) style.right = formatValue(position.right);
if (position.bottom !== undefined)
style.bottom = formatValue(position.bottom);
if (position.transform !== undefined) style.transform = position.transform;
return style;
};
+3 -3
View File
@@ -33,7 +33,7 @@ export default function ChatPopup() {
}
return (
<DraggableContainer constrainToBounds>
<DraggableContainer centerVertical>
<PopupWrapper title="Чат" draggable className="sm:overflow-hidden">
<div className="flex flex-col 2xl:h-[27.778vw] relative 2xl:-m-[1.389vw] -m-5">
<MessageFeed messages={messages} />
@@ -111,13 +111,13 @@ function MessageItem({ senderId, timestamp, content }: MessageItemProps) {
)}
<div>{content}</div>
</div>
<span className="caption-xs opacity-30">{timestamp}</span>
<span className="opacity-30 caption-xs">{timestamp}</span>
</div>
<div className="2xl:size-[2.222vw] size-8 rounded-full">
<img
src="/img/popups/MessageUserPfp.png"
className="size-full object-cover"
className="object-cover size-full"
alt="user"
/>
</div>