waveterm/frontend/layout/lib/utils.ts

104 lines
2.9 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: boolean = true): CSSProperties {
// Replace unitless items with px
const topRounded = Math.floor(top);
const leftRounded = Math.floor(left);
const widthRounded = Math.ceil(width);
const heightRounded = Math.ceil(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",
};
}