waveterm/frontend/layout/lib/model.ts

248 lines
6.1 KiB
TypeScript
Raw Normal View History

// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import { WritableAtom } from "jotai";
import { DropDirection, FlexDirection } from "./utils.js";
/**
* Represents an operation to insert a node into a tree.
*/
export type MoveOperation<T> = {
/**
* The index at which the node will be inserted in the parent.
*/
index: number;
/**
* The parent node. Undefined if inserting at root.
*/
parentId?: string;
/**
* Whether the node will be inserted at the root of the tree.
*/
insertAtRoot?: boolean;
/**
* The node to insert.
*/
node: LayoutNode<T>;
};
/**
* Types of actions that modify the layout tree.
*/
export enum LayoutTreeActionType {
ComputeMove = "computemove",
Move = "move",
Swap = "swap",
SetPendingAction = "setpending",
CommitPendingAction = "commitpending",
ClearPendingAction = "clearpending",
ResizeNode = "resize",
InsertNode = "insert",
InsertNodeAtIndex = "insertatindex",
DeleteNode = "delete",
MagnifyNodeToggle = "magnify",
}
/**
* Base class for actions that modify the layout tree.
*/
export interface LayoutTreeAction {
type: LayoutTreeActionType;
}
/**
* Action for computing a move operation and saving it as a pending action in the tree state.
*
* @template T The type of data associated with the nodes of the tree.
* @see MoveOperation
* @see LayoutTreeMoveNodeAction
*/
export interface LayoutTreeComputeMoveNodeAction<T> extends LayoutTreeAction {
type: LayoutTreeActionType.ComputeMove;
node: LayoutNode<T>;
nodeToMove: LayoutNode<T>;
direction: DropDirection;
}
/**
* Action for moving a node within the layout tree.
*
* @template T The type of data associated with the nodes of the tree.
* @see MoveOperation
*/
export interface LayoutTreeMoveNodeAction<T> extends LayoutTreeAction, MoveOperation<T> {
type: LayoutTreeActionType.Move;
}
2024-06-17 23:18:27 +02:00
/**
* Action for swapping two nodes within the layout tree.
*
* @template T The type of data associated with the nodes of the tree.
*/
export interface LayoutTreeSwapNodeAction extends LayoutTreeAction {
type: LayoutTreeActionType.Swap;
2024-06-17 23:18:27 +02:00
/**
* The node that node2 will replace.
*/
node1Id: string;
2024-06-17 23:18:27 +02:00
/**
* The node that node1 will replace.
*/
node2Id: string;
}
/**
* Action for inserting a new node to the layout tree.
*
* @template T The type of data associated with the nodes of the tree.
*/
export interface LayoutTreeInsertNodeAction<T> extends LayoutTreeAction {
type: LayoutTreeActionType.InsertNode;
node: LayoutNode<T>;
}
/**
* Action for inserting a node into the layout tree at the specified index.
*/
export interface LayoutTreeInsertNodeAtIndexAction<T> extends LayoutTreeAction {
type: LayoutTreeActionType.InsertNodeAtIndex;
/**
* The node to insert.
*/
node: LayoutNode<T>;
/**
* The array of indices to traverse when inserting the node.
* The last index is the index within the parent node where the node should be inserted.
*/
indexArr: number[];
}
/**
* Action for deleting a node from the layout tree.
*/
export interface LayoutTreeDeleteNodeAction extends LayoutTreeAction {
type: LayoutTreeActionType.DeleteNode;
nodeId: string;
}
/**
* Action for setting the pendingAction field of the layout tree state.
*/
export interface LayoutTreeSetPendingAction extends LayoutTreeAction {
type: LayoutTreeActionType.SetPendingAction;
/**
* The new value for the pending action field.
*/
action: LayoutTreeAction;
}
/**
* Action for committing the action in the pendingAction field of the layout tree state.
*/
export interface LayoutTreeCommitPendingAction extends LayoutTreeAction {
type: LayoutTreeActionType.CommitPendingAction;
}
/**
* Action for clearing the pendingAction field from the layout tree state.
*/
export interface LayoutTreeClearPendingAction extends LayoutTreeAction {
type: LayoutTreeActionType.ClearPendingAction;
}
/**
* An operation to resize a node.
*/
export interface ResizeNodeOperation {
/**
* The id of the node to resize.
*/
nodeId: string;
/**
* The new size for the node.
*/
size: number;
}
/**
* Action for resizing a node from the layout tree.
*/
export interface LayoutTreeResizeNodeAction extends LayoutTreeAction {
type: LayoutTreeActionType.ResizeNode;
/**
* A list of node ids to update and their respective new sizes.
*/
resizeOperations: ResizeNodeOperation[];
}
/**
* Action for toggling magnification of a node from the layout tree.
*/
export interface LayoutTreeMagnifyNodeToggleAction extends LayoutTreeAction {
type: LayoutTreeActionType.MagnifyNodeToggle;
/**
* The id of the node to maximize;
*/
nodeId: string;
}
/**
* Represents the state of a layout tree.
*
* @template T The type of data associated with the nodes of the tree.
*/
export type LayoutTreeState<T> = {
rootNode: LayoutNode<T>;
leafs: LayoutNode<T>[];
pendingAction: LayoutTreeAction;
generation: number;
magnifiedNodeId?: string;
};
/**
* Represents a single node in the layout tree.
* @template T The type of data associated with the node.
*/
export interface LayoutNode<T> {
id: string;
data?: T;
children?: LayoutNode<T>[];
flexDirection: FlexDirection;
size: number;
}
/**
* An abstraction of the type definition for a writable layout node atom.
*/
export type WritableLayoutNodeAtom<T> = WritableAtom<LayoutNode<T>, [value: LayoutNode<T>], void>;
/**
* An abstraction of the type definition for a writable layout tree state atom.
*/
export type WritableLayoutTreeStateAtom<T> = WritableAtom<LayoutTreeState<T>, [value: LayoutTreeState<T>], void>;
2024-06-20 08:00:57 +02:00
export type ContentRenderer<T> = (
data: T,
ready: boolean,
disablePointerEvents: boolean,
onMagnifyToggle: () => void,
2024-06-20 08:00:57 +02:00
onClose: () => void,
dragHandleRef: React.RefObject<HTMLDivElement>
) => React.ReactNode;
Implement outer drop direction, add rudimentary drag preview image rendering (#29) This PR adds support for Outer variants of each DropDirection. When calculating the drop direction, the cursor position is calculated relevant to the box over which it is hovering. The following diagram shows how drop directions are calculated. The colored in center is currently not supported, it is assigned to the top, bottom, left, right direction for now, though it will ultimately be its own distinct direction. ![IMG_3505](https://github.com/wavetermdev/thenextwave/assets/16651283/a7ea7387-b95d-4831-9e29-d3225b824c97) When an outer drop direction is provided for a move operation, if the reference node flexes in the same axis as the drop direction, the new node will be inserted at the same level as the parent of the reference node. If the reference node flexes in a different direction or the reference node does not have a grandparent, the operation will fall back to its non-Outer variant. This also removes some chatty debug statements, adds a blur to the currently-dragging node to indicate that it cannot be dropped onto, and simplifies the deriving of the layout state atom from the tab atom so there's no longer another intermediate derived atom for the layout node. This also adds rudimentary support for rendering custom preview images for any tile being dragged. Right now, this is a simple block containing the block ID, but this can be anything. This resolves an issue where letting React-DnD generate its own previews could take up to a half second, and would block dragging until complete. For Monaco, this was outright failing. It also fixes an issue where the tile layout could animate on first paint. Now, I use React Suspense to prevent the layout from displaying until all the children have loaded.
2024-06-11 22:03:41 +02:00
export type PreviewRenderer<T> = (data: T) => React.ReactElement;
export interface LayoutNodeWaveObj<T> extends WaveObj {
node: LayoutNode<T>;
magnifiednodeid: string;
}
export const DefaultNodeSize = 10;