mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 15:36:33 +00:00
51c59e28b8
The column took the page's room and cut the spread off. The Studio now opens the same movable, resizable window as the planner, kept under its own key and below the Studio's bar; its frame moved into assistantFrame.ts and AssistantFrameEdges so both windows share it.
51 lines
2.0 KiB
TypeScript
51 lines
2.0 KiB
TypeScript
import { useState } from 'react';
|
|
|
|
import { type WindowSize, useDragResize } from '../../hooks/useDragResize';
|
|
|
|
/**
|
|
* The floating window's frame, shared by the planner's window and TREK
|
|
* Studio's: moved by its head, resized from any edge or corner, kept inside
|
|
* the screen and below the navbar, remembered under its own key.
|
|
*/
|
|
|
|
const MIN_SIZE: WindowSize = { width: 340, height: 420 };
|
|
const DEFAULT_SIZE: WindowSize = { width: 400, height: 600 };
|
|
/** Never closer to the screen's edge than this. */
|
|
const MARGIN = 16;
|
|
/** The default distance from the edges, and how near a corner a released window snaps into it. */
|
|
const GAP = 24;
|
|
const expandedSize = (viewport: WindowSize): WindowSize => ({
|
|
width: Math.min(720, viewport.width - 2 * MARGIN),
|
|
height: Math.round(viewport.height * 0.8),
|
|
});
|
|
|
|
/** The fixed navbar's height (`--nav-h`, a calc() and 0 where there is none), measured. */
|
|
function navbarHeight(): number {
|
|
if (typeof document === 'undefined') return 0;
|
|
const probe = document.createElement('div');
|
|
probe.style.cssText = 'position:fixed;visibility:hidden;height:var(--nav-h, 0px)';
|
|
document.body.appendChild(probe);
|
|
const height = probe.offsetHeight;
|
|
probe.remove();
|
|
return height;
|
|
}
|
|
|
|
/** The frame of a floating assistant window, its place and size kept under `storageKey`. */
|
|
export function useAssistantFrame(storageKey: string, topInsetPx?: number) {
|
|
// The navbar sits on the same layer and later in the page: the head never goes under it.
|
|
const [topInset] = useState(() => topInsetPx ?? navbarHeight());
|
|
return useDragResize({
|
|
storageKey,
|
|
minSize: MIN_SIZE,
|
|
defaultSize: DEFAULT_SIZE,
|
|
expandedSize,
|
|
margin: MARGIN,
|
|
gap: GAP,
|
|
topInset,
|
|
});
|
|
}
|
|
|
|
/** The glass window's own classes; `active` while it is being moved or resized. */
|
|
export const FRAME_CLASS =
|
|
'fixed z-[var(--z-nav)] flex-col overflow-visible rounded-xl border border-edge-faint bg-surface-elevated shadow-[var(--sidebar-shadow)] backdrop-blur-2xl backdrop-saturate-150';
|