headless-vpl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,51 @@
1
+ import Container from './Container';
2
+ import Workspace from './Workspace';
3
+ import Position from './Position';
4
+ import type { IWorkspaceElement } from './types';
5
+ type AutoLayoutDirection = 'horizontal' | 'vertical';
6
+ type AutoLayoutAlignment = 'start' | 'center' | 'end';
7
+ type AutoLayoutProps = {
8
+ workspace?: Workspace;
9
+ position: Position;
10
+ width?: number;
11
+ height?: number;
12
+ direction?: AutoLayoutDirection;
13
+ gap?: number;
14
+ alignment?: AutoLayoutAlignment;
15
+ containers: Container[];
16
+ };
17
+ /**
18
+ * 子 Container を配置するレイアウトマネージャ。
19
+ * direction で水平/垂直、gap で間隔、alignment で交差軸の揃えを制御する。
20
+ * IWorkspaceElement を実装し、MovableObject と同じインターフェースを持つ。
21
+ */
22
+ declare class AutoLayout implements IWorkspaceElement {
23
+ readonly id: string;
24
+ Children: Container[];
25
+ position: Position;
26
+ parentContainer: Container | null;
27
+ width: number;
28
+ height: number;
29
+ direction: AutoLayoutDirection;
30
+ gap: number;
31
+ alignment: AutoLayoutAlignment;
32
+ workspace: Workspace;
33
+ name: string;
34
+ type: string;
35
+ frame: number;
36
+ constructor({ workspace, position, width, height, direction, gap, alignment, containers }: AutoLayoutProps);
37
+ get absolutePosition(): {
38
+ x: number;
39
+ y: number;
40
+ };
41
+ setParent(container: Container): void;
42
+ addElement(element: Container): void;
43
+ update(): void;
44
+ private layoutHorizontal;
45
+ private layoutVertical;
46
+ private alignCrossAxis;
47
+ private computeContentSize;
48
+ move(x: number, y: number): void;
49
+ toJSON(): Record<string, unknown>;
50
+ }
51
+ export default AutoLayout;
@@ -0,0 +1,14 @@
1
+ import Position from './Position';
2
+ import Workspace from './Workspace';
3
+ import { MovableObject } from './MovableObject';
4
+ type ConnectorProps = {
5
+ workspace?: Workspace;
6
+ position: Position;
7
+ name: string;
8
+ type: 'input' | 'output';
9
+ };
10
+ declare class Connector extends MovableObject {
11
+ constructor({ workspace, position, name, type }: ConnectorProps);
12
+ toJSON(): Record<string, unknown>;
13
+ }
14
+ export default Connector;
@@ -0,0 +1,54 @@
1
+ import AutoLayout from './AutoLayout';
2
+ import { MovableObject } from './MovableObject';
3
+ import Position from './Position';
4
+ import Workspace from './Workspace';
5
+ import type { SizingMode, Padding } from './types';
6
+ type ContainerProps<T extends {
7
+ [key: string]: MovableObject | AutoLayout;
8
+ } = {}> = {
9
+ workspace?: Workspace;
10
+ position?: Position;
11
+ name: string;
12
+ color?: string;
13
+ width?: number;
14
+ height?: number;
15
+ widthMode?: SizingMode;
16
+ heightMode?: SizingMode;
17
+ padding?: Partial<Padding>;
18
+ minWidth?: number;
19
+ maxWidth?: number;
20
+ minHeight?: number;
21
+ maxHeight?: number;
22
+ resizable?: boolean;
23
+ children?: T;
24
+ };
25
+ declare class Container<T extends {
26
+ [key: string]: MovableObject | AutoLayout;
27
+ } = {}> extends MovableObject {
28
+ color: string;
29
+ width: number;
30
+ height: number;
31
+ widthMode: SizingMode;
32
+ heightMode: SizingMode;
33
+ padding: Padding;
34
+ minWidth: number;
35
+ maxWidth: number;
36
+ minHeight: number;
37
+ maxHeight: number;
38
+ resizable: boolean;
39
+ children: T;
40
+ constructor({ workspace, position, name, color, width, height, widthMode, heightMode, padding, minWidth, maxWidth, minHeight, maxHeight, resizable, children, }: ContainerProps<T>);
41
+ private propagateWorkspace;
42
+ private bindChildWorkspace;
43
+ setColor(color: string): void;
44
+ applyContentSize(contentWidth: number, contentHeight: number): void;
45
+ updateChildren(): void;
46
+ private updateChildPosition;
47
+ private updateChildLayout;
48
+ move(x: number, y: number): void;
49
+ private updateChildrenPosition;
50
+ private isMovableObject;
51
+ private isAutoLayout;
52
+ toJSON(): Record<string, unknown>;
53
+ }
54
+ export default Container;
@@ -0,0 +1,42 @@
1
+ import type Connector from './Connector';
2
+ import Workspace from './Workspace';
3
+ import type { IEdge, EdgeType, EdgeMarker } from './types';
4
+ import type { IPosition } from './Position';
5
+ import type { EdgePathResult } from '../util/edgePath';
6
+ type EdgeProps = {
7
+ workspace?: Workspace;
8
+ start: Connector;
9
+ end: Connector;
10
+ edgeType?: EdgeType;
11
+ label?: string;
12
+ markerStart?: EdgeMarker;
13
+ markerEnd?: EdgeMarker;
14
+ };
15
+ /**
16
+ * 2 つの Connector を結ぶ接続線。
17
+ * Position ではなく Connector への参照を保持し、
18
+ * Connector の移動に自動追従する(Renderer 側で処理)。
19
+ */
20
+ declare class Edge implements IEdge {
21
+ readonly id: string;
22
+ workspace: Workspace;
23
+ startConnector: Connector;
24
+ endConnector: Connector;
25
+ edgeType: EdgeType;
26
+ label?: string;
27
+ markerStart?: EdgeMarker;
28
+ markerEnd?: EdgeMarker;
29
+ constructor({ workspace, start, end, edgeType, label, markerStart, markerEnd }: EdgeProps);
30
+ get startPosition(): import("./Position").default;
31
+ get endPosition(): import("./Position").default;
32
+ /**
33
+ * edgeType に応じたパス文字列とラベル位置を計算する。
34
+ */
35
+ computePath(): EdgePathResult;
36
+ /**
37
+ * ラベルの表示位置を返す。
38
+ */
39
+ getLabelPosition(): IPosition;
40
+ toJSON(): Record<string, unknown>;
41
+ }
42
+ export default Edge;
@@ -0,0 +1,10 @@
1
+ import type { VplEventType, VplEvent } from './types';
2
+ /**
3
+ * 最小限のイベントシステム。
4
+ * move / connect / disconnect / add / remove / update の 6 種のイベントを扱う。
5
+ */
6
+ export declare class EventBus {
7
+ private handlers;
8
+ on(type: VplEventType, handler: (event: VplEvent) => void): () => void;
9
+ emit(type: VplEventType, target: unknown, data?: Record<string, unknown>): void;
10
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * コマンドインターフェース。Undo/Redo のための do/undo ペア。
3
+ */
4
+ export interface Command {
5
+ execute(): void;
6
+ undo(): void;
7
+ }
8
+ /**
9
+ * Command パターンベースの Undo/Redo 履歴。
10
+ * execute() でコマンドを実行しスタックに積む。
11
+ * undo()/redo() でスタックを戻す/進む。
12
+ */
13
+ export declare class History {
14
+ private _undoStack;
15
+ private _redoStack;
16
+ private _maxDepth;
17
+ constructor(maxDepth?: number);
18
+ /**
19
+ * コマンドを実行し、Undo スタックに追加する。
20
+ * 新しいコマンド実行時に Redo スタックはクリアされる。
21
+ */
22
+ execute(command: Command): void;
23
+ undo(): void;
24
+ redo(): void;
25
+ get canUndo(): boolean;
26
+ get canRedo(): boolean;
27
+ clear(): void;
28
+ }
@@ -0,0 +1,29 @@
1
+ import Position from './Position';
2
+ import Workspace from './Workspace';
3
+ import type { IWorkspaceElement } from './types';
4
+ /**
5
+ * 動くオブジェクトに共通するプロパティ・処理をまとめた基底クラス。
6
+ * DOM 依存はゼロ — 描画は外部の Renderer が EventBus 経由で行う。
7
+ */
8
+ export declare abstract class MovableObject implements IWorkspaceElement {
9
+ readonly id: string;
10
+ /** スナップ接続による親 (型安全) */
11
+ Parent: MovableObject | null;
12
+ /** スナップ接続による子 (型安全) */
13
+ Children: MovableObject | null;
14
+ workspace: Workspace;
15
+ position: Position;
16
+ name: string;
17
+ type: string;
18
+ selected: boolean;
19
+ constructor(workspace: Workspace | undefined, position: Position, name: string, type: string);
20
+ /**
21
+ * プロパティ変更を通知する。Renderer が 'update' イベントで再描画する。
22
+ */
23
+ update(): void;
24
+ /**
25
+ * 位置を変更し 'move' イベントを発火する。
26
+ */
27
+ move(x: number, y: number): void;
28
+ toJSON(): Record<string, unknown>;
29
+ }
@@ -0,0 +1,12 @@
1
+ export interface IPosition {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ declare class Position {
6
+ x: number;
7
+ y: number;
8
+ constructor(x: number, y: number);
9
+ setPosition(x: number, y: number): void;
10
+ getPosition(): IPosition;
11
+ }
12
+ export default Position;
@@ -0,0 +1,19 @@
1
+ import type { EventBus } from './EventBus';
2
+ import type { MovableObject } from './MovableObject';
3
+ /**
4
+ * 選択状態を管理するクラス。
5
+ * Workspace のプロパティとして保持し、EventBus 経由で select/deselect イベントを発火する。
6
+ */
7
+ export declare class SelectionManager {
8
+ private _selected;
9
+ private eventBus;
10
+ constructor(eventBus: EventBus);
11
+ select(element: MovableObject): void;
12
+ deselect(element: MovableObject): void;
13
+ toggleSelect(element: MovableObject): void;
14
+ selectAll(elements: readonly MovableObject[]): void;
15
+ deselectAll(): void;
16
+ getSelection(): readonly MovableObject[];
17
+ isSelected(element: MovableObject): boolean;
18
+ get size(): number;
19
+ }
@@ -0,0 +1,40 @@
1
+ import { EventBus } from './EventBus';
2
+ import { History } from './History';
3
+ import { SelectionManager } from './SelectionManager';
4
+ import type { IWorkspaceElement, IEdge, VplEventType, VplEvent, Viewport } from './types';
5
+ /**
6
+ * 要素の管理と EventBus を提供するワークスペース。
7
+ * DOM への依存はゼロ — 描画は外部の Renderer が担う。
8
+ */
9
+ declare class Workspace {
10
+ readonly eventBus: EventBus;
11
+ readonly viewport: Viewport;
12
+ readonly selection: SelectionManager;
13
+ readonly history: History;
14
+ private _elements;
15
+ private _edges;
16
+ addElement(element: IWorkspaceElement): void;
17
+ addEdge(edge: IEdge): void;
18
+ removeElement(element: IWorkspaceElement): void;
19
+ removeEdge(edge: IEdge): void;
20
+ /**
21
+ * コンテナを削除する。関連 Edge の自動削除、Parent/Children 関係のクリア、
22
+ * 子要素の再帰削除を行う。
23
+ * instanceof を使わずダックタイピングで判定し、循環参照を回避する。
24
+ */
25
+ removeContainer(element: IWorkspaceElement): void;
26
+ get elements(): readonly IWorkspaceElement[];
27
+ get edges(): readonly IEdge[];
28
+ on(type: VplEventType, handler: (event: VplEvent) => void): () => void;
29
+ pan(x: number, y: number): void;
30
+ panBy(dx: number, dy: number): void;
31
+ zoomAt(screenX: number, screenY: number, newScale: number): void;
32
+ setScale(scale: number): void;
33
+ /**
34
+ * 全要素が収まるようにビューポートを自動調整する。
35
+ * scale は 1.0 を上限とし、過度なズームインを防止する。
36
+ * canvasWidth/canvasHeight は引数で渡す(DOM 依存回避)。
37
+ */
38
+ fitView(canvasWidth: number, canvasHeight: number, padding?: number): void;
39
+ }
40
+ export default Workspace;
@@ -0,0 +1,55 @@
1
+ import type { Command } from './History';
2
+ import type { IWorkspaceElement } from './types';
3
+ import type Workspace from './Workspace';
4
+ /**
5
+ * 移動コマンド。要素を指定位置に移動する。
6
+ */
7
+ export declare class MoveCommand implements Command {
8
+ private element;
9
+ private fromX;
10
+ private fromY;
11
+ private toX;
12
+ private toY;
13
+ constructor(element: IWorkspaceElement, fromX: number, fromY: number, toX: number, toY: number);
14
+ execute(): void;
15
+ undo(): void;
16
+ }
17
+ /**
18
+ * 要素追加コマンド。
19
+ */
20
+ export declare class AddCommand implements Command {
21
+ private workspace;
22
+ private element;
23
+ constructor(workspace: Workspace, element: IWorkspaceElement);
24
+ execute(): void;
25
+ undo(): void;
26
+ }
27
+ /**
28
+ * 要素削除コマンド。Undo で再追加する。
29
+ */
30
+ export declare class RemoveCommand implements Command {
31
+ private workspace;
32
+ private element;
33
+ private relatedEdges;
34
+ private savedParent;
35
+ private savedChildren;
36
+ constructor(workspace: Workspace, element: IWorkspaceElement);
37
+ private findRelatedEdges;
38
+ execute(): void;
39
+ undo(): void;
40
+ }
41
+ /**
42
+ * 接続コマンド。2 つの要素の Parent/Children 関係を設定する。
43
+ */
44
+ export declare class ConnectCommand implements Command {
45
+ private workspace;
46
+ private parent;
47
+ private child;
48
+ constructor(workspace: Workspace, parent: IWorkspaceElement & {
49
+ Children: unknown;
50
+ }, child: IWorkspaceElement & {
51
+ Parent: unknown;
52
+ });
53
+ execute(): void;
54
+ undo(): void;
55
+ }
@@ -0,0 +1,51 @@
1
+ import type Position from './Position';
2
+ import type { IPosition } from './Position';
3
+ export type SizingMode = 'fixed' | 'hug' | 'fill';
4
+ export type Padding = {
5
+ top: number;
6
+ right: number;
7
+ bottom: number;
8
+ left: number;
9
+ };
10
+ export declare function generateId(prefix?: string): string;
11
+ /**
12
+ * Workspace 上に配置される要素の共通インターフェース。
13
+ * MovableObject と AutoLayout が共有するプロパティを統一する。
14
+ */
15
+ export interface IWorkspaceElement {
16
+ readonly id: string;
17
+ position: Position;
18
+ name: string;
19
+ type: string;
20
+ move(x: number, y: number): void;
21
+ update(): void;
22
+ toJSON(): Record<string, unknown>;
23
+ }
24
+ /**
25
+ * Edge のインターフェース(Position を 2 つ持つため IWorkspaceElement とは別)
26
+ */
27
+ export interface IEdge {
28
+ readonly id: string;
29
+ readonly startPosition: IPosition;
30
+ readonly endPosition: IPosition;
31
+ toJSON(): Record<string, unknown>;
32
+ }
33
+ export type VplEventType = 'move' | 'connect' | 'disconnect' | 'add' | 'remove' | 'update' | 'pan' | 'zoom' | 'select' | 'deselect';
34
+ export type EdgeType = 'straight' | 'bezier' | 'step' | 'smoothstep';
35
+ export type MarkerType = 'arrow' | 'arrowClosed' | 'none';
36
+ export type EdgeMarker = {
37
+ type: MarkerType;
38
+ color?: string;
39
+ size?: number;
40
+ };
41
+ export type ResizeHandleDirection = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
42
+ export interface Viewport {
43
+ x: number;
44
+ y: number;
45
+ scale: number;
46
+ }
47
+ export interface VplEvent {
48
+ type: VplEventType;
49
+ target: unknown;
50
+ data?: Record<string, unknown>;
51
+ }