mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
<img width="2056" height="1047" alt="Screenshot 2026-06-16 at 12 42 05 AM" src="https://github.com/user-attachments/assets/74a38b93-f31f-4263-bb62-24c2334a22e8" /> <img width="1443" height="1051" alt="Screenshot 2026-06-16 at 12 42 33 AM" src="https://github.com/user-attachments/assets/adb3ba47-f3e6-44a7-bbc3-2097e15843b6" />
53 lines
2.2 KiB
TypeScript
53 lines
2.2 KiB
TypeScript
// Pure layout/geometry for the draggable ChatFAB panel. Kept free of React so
|
|
// the constants and clamping math stay readable and unit-testable; ChatFAB.tsx
|
|
// owns the stateful wiring (refs, effects, the ResizeObserver) that consumes them.
|
|
|
|
export const PANEL_WIDTH_PX = 390;
|
|
export const PANEL_HEIGHT_PX = 520;
|
|
export const PANEL_MIN_WIDTH_PX = 300;
|
|
export const PANEL_MIN_HEIGHT_PX = 380;
|
|
export const FAB_GAP_PX = 16;
|
|
const FAB_BOTTOM_OFFSET_PX = FAB_GAP_PX;
|
|
|
|
export const RESET_MS = 380;
|
|
const RESET_EASING = "cubic-bezier(0.32, 0.72, 0, 1)";
|
|
export const RESET_TRANSITION = `transform ${RESET_MS}ms ${RESET_EASING}, width ${RESET_MS}ms ${RESET_EASING}, height ${RESET_MS}ms ${RESET_EASING}`;
|
|
|
|
// Handle strips straddle the border; zIndex:1 lifts them above ChatFABWindow's transform stacking context.
|
|
export const RESIZE_HANDLES = {
|
|
top: { top: -3, left: 14, right: 14, height: 6, zIndex: 1 },
|
|
bottom: { bottom: -3, left: 14, right: 14, height: 6, zIndex: 1 },
|
|
left: { left: -3, top: 14, bottom: 14, width: 6, zIndex: 1 },
|
|
right: { right: -3, top: 14, bottom: 14, width: 6, zIndex: 1 },
|
|
topLeft: { top: -4, left: -4, width: 14, height: 14, zIndex: 1 },
|
|
topRight: { top: -4, right: -4, width: 14, height: 14, zIndex: 1 },
|
|
bottomLeft: { bottom: -4, left: -4, width: 14, height: 14, zIndex: 1 },
|
|
bottomRight: { bottom: -4, right: -4, width: 14, height: 14, zIndex: 1 },
|
|
};
|
|
|
|
// Default resting position: bottom-right of the overlay, inset by the gap.
|
|
export function defaultPanelPos(
|
|
overlayWidth: number,
|
|
overlayHeight: number,
|
|
): { x: number; y: number } {
|
|
return {
|
|
x: overlayWidth - PANEL_WIDTH_PX - FAB_GAP_PX,
|
|
y: overlayHeight - PANEL_HEIGHT_PX - FAB_BOTTOM_OFFSET_PX,
|
|
};
|
|
}
|
|
|
|
// Clamps pos to [gap, max] on each axis; pins to top-left gap when the overlay is too small so the header stays reachable.
|
|
export function clampToOverlay(
|
|
pos: { x: number; y: number },
|
|
size: { width: number; height: number },
|
|
overlayWidth: number,
|
|
overlayHeight: number,
|
|
): { x: number; y: number } {
|
|
const maxX = overlayWidth - size.width - FAB_GAP_PX;
|
|
const maxY = overlayHeight - size.height - FAB_GAP_PX;
|
|
return {
|
|
x: Math.max(FAB_GAP_PX, Math.min(pos.x, maxX)),
|
|
y: Math.max(FAB_GAP_PX, Math.min(pos.y, maxY)),
|
|
};
|
|
}
|