mirror of
https://github.com/wavetermdev/waveterm
synced 2026-05-06 15:08:34 +00:00
This PR is a large refactoring of the layout code to move as much of the layout state logic as possible into a unified model class, with atoms and derived atoms to notify the display logic of changes. It also fixes some latent bugs in the node resize code, significantly speeds up response times for resizing and dragging, and sets us up to fully replace the React-DnD library in the future.
107 lines
3 KiB
TypeScript
107 lines
3 KiB
TypeScript
// Copyright 2024, Command Line Inc.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
import { CSSProperties } from "react";
|
|
import { XYCoord } from "react-dnd";
|
|
|
|
export interface Dimensions {
|
|
width: number;
|
|
height: number;
|
|
left: number;
|
|
top: number;
|
|
}
|
|
|
|
export enum DropDirection {
|
|
Top = 0,
|
|
Right = 1,
|
|
Bottom = 2,
|
|
Left = 3,
|
|
OuterTop = 4,
|
|
OuterRight = 5,
|
|
OuterBottom = 6,
|
|
OuterLeft = 7,
|
|
Center = 8,
|
|
}
|
|
|
|
export enum FlexDirection {
|
|
Row = "row",
|
|
Column = "column",
|
|
}
|
|
|
|
export function reverseFlexDirection(flexDirection: FlexDirection): FlexDirection {
|
|
return flexDirection === FlexDirection.Row ? FlexDirection.Column : FlexDirection.Row;
|
|
}
|
|
|
|
export function determineDropDirection(dimensions?: Dimensions, offset?: XYCoord | null): DropDirection | undefined {
|
|
// console.log("determineDropDirection", dimensions, offset);
|
|
if (!offset || !dimensions) return undefined;
|
|
const { width, height, left, top } = dimensions;
|
|
let { x, y } = offset;
|
|
x -= left;
|
|
y -= top;
|
|
|
|
// Lies outside of the box
|
|
if (y < 0 || y > height || x < 0 || x > width) return undefined;
|
|
|
|
// Determines if a drop point falls within the center fifth of the box, meaning we should return Center.
|
|
const centerX1 = (2 * width) / 5;
|
|
const centerX2 = (3 * width) / 5;
|
|
const centerY1 = (2 * height) / 5;
|
|
const centerY2 = (3 * height) / 5;
|
|
|
|
if (x > centerX1 && x < centerX2 && y > centerY1 && y < centerY2) return DropDirection.Center;
|
|
|
|
const diagonal1 = y * width - x * height;
|
|
const diagonal2 = y * width + x * height - height * width;
|
|
|
|
// Lies on diagonal
|
|
if (diagonal1 == 0 || diagonal2 == 0) return undefined;
|
|
|
|
let code = 0;
|
|
|
|
if (diagonal2 > 0) {
|
|
code += 1;
|
|
}
|
|
|
|
if (diagonal1 > 0) {
|
|
code += 2;
|
|
code = 5 - code;
|
|
}
|
|
|
|
// Determines whether a drop is close to an edge of the box, meaning drop direction should be OuterX, instead of X
|
|
const xOuter1 = width / 5;
|
|
const xOuter2 = width - width / 5;
|
|
const yOuter1 = height / 5;
|
|
const yOuter2 = height - height / 5;
|
|
|
|
if (y < yOuter1 || y > yOuter2 || x < xOuter1 || x > xOuter2) {
|
|
code += 4;
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
export function setTransform(
|
|
{ top, left, width, height }: Dimensions,
|
|
setSize = true,
|
|
roundVals = true
|
|
): CSSProperties {
|
|
// Replace unitless items with px
|
|
const topRounded = roundVals ? Math.floor(top) : top;
|
|
const leftRounded = roundVals ? Math.floor(left) : left;
|
|
const widthRounded = roundVals ? Math.ceil(width) : width;
|
|
const heightRounded = roundVals ? Math.ceil(height) : height;
|
|
const translate = `translate3d(${leftRounded}px,${topRounded}px, 0)`;
|
|
return {
|
|
top: 0,
|
|
left: 0,
|
|
transform: translate,
|
|
WebkitTransform: translate,
|
|
MozTransform: translate,
|
|
msTransform: translate,
|
|
OTransform: translate,
|
|
width: setSize ? `${widthRounded}px` : undefined,
|
|
height: setSize ? `${heightRounded}px` : undefined,
|
|
position: "absolute",
|
|
};
|
|
}
|