@fulate/core 1.0.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,64 @@
1
+ import { type PointView, type Rect } from "@fulate/share";
2
+ import type { ElementOptionPatch } from "./element";
3
+ import { type OriginX, type OriginY } from "./properties";
4
+ /** 交互开始时直接借用的作者 frame 标量。 */
5
+ export interface ReferenceTransformFrame {
6
+ readonly left: number;
7
+ readonly top: number;
8
+ readonly width: number;
9
+ readonly height: number;
10
+ readonly angle: number;
11
+ readonly scaleX: number;
12
+ readonly scaleY: number;
13
+ readonly skewX: number;
14
+ readonly skewY: number;
15
+ readonly originX: OriginX;
16
+ readonly originY: OriginY;
17
+ }
18
+ /** 一次连续 Transform 唯一的 frozen reference。 */
19
+ export interface ReferenceTransformBaseline {
20
+ readonly writeMode: "frame-authored" | "authored-geometry" | "pose-authored";
21
+ readonly startWorldMatrix: DOMMatrixReadOnly;
22
+ readonly startParentWorldMatrix: DOMMatrixReadOnly;
23
+ readonly startParentWorldInverseMatrix: DOMMatrixReadOnly;
24
+ readonly referenceBounds: Readonly<Rect>;
25
+ readonly frame: Readonly<ReferenceTransformFrame>;
26
+ }
27
+ /** owner 自有 immutable branch 与通用 reference baseline。 */
28
+ export interface ElementTransformBaseline<OwnedState = unknown> {
29
+ readonly ownedState: OwnedState;
30
+ readonly reference: ReferenceTransformBaseline;
31
+ }
32
+ /** 当前显示帧从 frozen baseline 直接求值的世界 intent。 */
33
+ export interface TransformIntent {
34
+ readonly worldDelta: DOMMatrixReadOnly;
35
+ /** 连续旋转手势从 frozen baseline 累积的未折叠 world 角度。 */
36
+ readonly unwrappedRotationDelta?: number;
37
+ }
38
+ /** 只有显式 reparent 才携带的新 parent world reference。 */
39
+ export interface ReparentTransformIntent extends TransformIntent {
40
+ readonly targetParentWorldMatrix: DOMMatrixReadOnly;
41
+ }
42
+ /** 已由调用方持有的最终 world pose 与目标 parent inverse。 */
43
+ export interface ReferenceTransformTarget {
44
+ readonly worldMatrix: DOMMatrixReadOnly;
45
+ readonly worldCenter: PointView;
46
+ readonly parentInverseMatrix: DOMMatrixReadOnly;
47
+ }
48
+ /** 通用 frame patch 与 authored local 坐标 delta。 */
49
+ export interface ReferenceTransformResolution {
50
+ readonly framePatch: Readonly<ElementOptionPatch>;
51
+ readonly authoredLocalDelta: DOMMatrixReadOnly;
52
+ }
53
+ /** 判断变换意图是否包含跨父级重挂载所需的目标父级矩阵。 */
54
+ export declare function isReparentTransformIntent(intent: Readonly<TransformIntent | ReparentTransformIntent>): intent is Readonly<ReparentTransformIntent>;
55
+ /**
56
+ * 从调用方已经持有的最终 world pose 解析 frame/authored geometry。
57
+ * target 与 reference 都是当前操作的权威输入;函数只计算,不提交或调度。
58
+ */
59
+ export declare function resolveReferenceTransformTarget(baseline: Readonly<ReferenceTransformBaseline>, target: Readonly<ReferenceTransformTarget>): ReferenceTransformResolution;
60
+ /**
61
+ * 从 frozen reference 与当前 intent 纯计算最终 frame/authored delta。
62
+ * 不读取 owner/live state,不提交、不校验、不 clone structured authored state。
63
+ */
64
+ export declare function resolveReferenceTransform(baseline: Readonly<ReferenceTransformBaseline>, intent: Readonly<TransformIntent | ReparentTransformIntent>): ReferenceTransformResolution;
@@ -0,0 +1,146 @@
1
+ import { Element, BaseElementOption, ElementProperties, type ElementOptionPatch } from "./element";
2
+ import { ElementTransform, type ElementTransformClass } from "./element-transform";
3
+ import { ChangeImpact, type PropertyChanges } from "./properties";
4
+ import { type BackgroundColor, type Edge, type PointView } from "@fulate/share";
5
+ import { type GeometryQuery, type GeometrySnapshot } from "../geometry";
6
+ /** border 相对内容轮廓的绘制位置。 */
7
+ export type BorderPosition = "inside" | "outside";
8
+ /** Shape 阴影样式。 */
9
+ export interface ShadowOption {
10
+ /** 阴影颜色;默认半透明黑色。 */
11
+ color?: string;
12
+ /** 模糊半径,单位为 local 坐标。 */
13
+ blur?: number;
14
+ /** x 方向偏移,单位为 local 坐标。 */
15
+ offsetX?: number;
16
+ /** y 方向偏移,单位为 local 坐标。 */
17
+ offsetY?: number;
18
+ }
19
+ /** local 边界四个方向的视觉外扩量。 */
20
+ export interface Outset {
21
+ /** 顶部外扩量。 */
22
+ top: number;
23
+ /** 右侧外扩量。 */
24
+ right: number;
25
+ /** 底部外扩量。 */
26
+ bottom: number;
27
+ /** 左侧外扩量。 */
28
+ left: number;
29
+ }
30
+ /** Shape 的填充、border、透明度和阴影选项。 */
31
+ export interface ShapeOption<T = Shape> extends BaseElementOption<T> {
32
+ /** Canvas 填充和裁剪规则;默认 `"nonzero"`。 */
33
+ fillRule?: CanvasFillRule;
34
+ /** 显式填充颜色或渐变;省略时使用 Skin,`null` 表示不填充。 */
35
+ backgroundColor?: BackgroundColor | null;
36
+ /** 显式 border 颜色或渐变;省略时使用 Skin,`null` 表示不描边。 */
37
+ borderColor?: BackgroundColor | null;
38
+ /** border 宽度,单位为 local 坐标,默认 `0`。 */
39
+ borderWidth?: number;
40
+ /** border 绘制位置,默认 `"inside"`。 */
41
+ borderPosition?: BorderPosition;
42
+ /** 绘制透明度,默认 `1`。 */
43
+ opacity?: number;
44
+ /** 阴影样式;默认 `null`。 */
45
+ shadow?: ShadowOption | null;
46
+ }
47
+ /** Shape 的增量选项。 */
48
+ export type ShapeOptionPatch<O extends ShapeOption<any> = ShapeOption> = ElementOptionPatch<O>;
49
+ /** Shape 规范化后的样式属性。 */
50
+ export declare class ShapeProperties extends ElementProperties {
51
+ /** 当前 Canvas 填充和裁剪规则。 */
52
+ fillRule: CanvasFillRule;
53
+ /** 当前显式填充颜色或渐变;`undefined` 表示继承 Skin。 */
54
+ backgroundColor?: BackgroundColor | null;
55
+ /** 当前显式 border 颜色或渐变;`undefined` 表示继承 Skin。 */
56
+ borderColor?: BackgroundColor | null;
57
+ /** 当前 border 宽度。 */
58
+ borderWidth: number;
59
+ /** 当前 border 绘制位置。 */
60
+ borderPosition: BorderPosition;
61
+ /** 当前绘制透明度。 */
62
+ opacity: number;
63
+ /** 当前阴影样式。 */
64
+ shadow: Readonly<ShadowOption> | null;
65
+ /** 创建 Shape 样式属性;gradient、shadow 等结构值直接采用输入引用。 */
66
+ constructor(options?: ShapeOption);
67
+ getImpact(changes: PropertyChanges): ChangeImpact;
68
+ }
69
+ /** Shape 的 border/shadow hit 与 visual geometry companion runtime。 */
70
+ export declare class ShapeTransform<E extends Shape = Shape> extends ElementTransform<E> {
71
+ /** 构建包含 outside border、但不含 shadow 的 local 命中边界。 */
72
+ protected buildLocalHitBounds(snapshot: GeometrySnapshot): Readonly<import("@fulate/share").Rect>;
73
+ /** 使用 canonical query 命中填充和 outside border。 */
74
+ protected containsLocalHitPoint(point: PointView, query: GeometryQuery): boolean;
75
+ /** 构建包含绘制外扩的保守 local 轮廓。 */
76
+ protected buildVisualOutline(snapshot: GeometrySnapshot): PointView[];
77
+ /** 构建空间索引使用的 local 绘制 AABB。 */
78
+ protected buildVisualBounds(snapshot: GeometrySnapshot): Readonly<import("@fulate/share").Rect>;
79
+ }
80
+ /** 提供填充、border、阴影及对应命中几何的可绘制元素。 */
81
+ export declare class Shape<P extends ShapeProperties = ShapeProperties, O extends ShapeOption<any> = ShapeOption<any>> extends Element<P, O> {
82
+ readonly type: string;
83
+ /** 当前 Canvas 填充和裁剪规则。 */
84
+ get fillRule(): CanvasFillRule;
85
+ /** 当前显式填充颜色或渐变;`undefined` 表示继承 Skin。 */
86
+ get backgroundColor(): BackgroundColor;
87
+ /** 当前显式 border 颜色或渐变;`undefined` 表示继承 Skin。 */
88
+ get borderColor(): BackgroundColor;
89
+ /** 当前 border 宽度,单位为 local 坐标。 */
90
+ get borderWidth(): number;
91
+ /** 当前 border 相对内容轮廓的位置。 */
92
+ get borderPosition(): BorderPosition;
93
+ /** 当前绘制透明度。 */
94
+ get opacity(): number;
95
+ /** 当前阴影样式;`null` 表示无阴影。 */
96
+ get shadow(): Readonly<ShadowOption>;
97
+ /** 创建带填充、border、透明度和阴影样式的 Shape。 */
98
+ constructor(options?: NoInfer<O>, properties?: P, Transform?: ElementTransformClass);
99
+ /** 返回 outside border 对 local hit/visual 边界的单侧外扩量。 */
100
+ getBorderOutset(): number;
101
+ /** 返回包含 outside border 和 shadow 的四向视觉外扩量。 */
102
+ getVisualOutset(): Outset;
103
+ /**
104
+ * 返回逻辑边对应的局部坐标线段(不含 visual outset)。
105
+ * 多边形 / 三角形等子类覆写此方法即可让锚点贴着实际轮廓。
106
+ */
107
+ getEdgeSegment(edge: Edge): {
108
+ /** 线段起点。 */
109
+ start: PointView;
110
+ /** 线段终点。 */
111
+ end: PointView;
112
+ };
113
+ /**
114
+ * 返回某条逻辑边上 ratio 处的局部坐标和朝外法线。
115
+ * 默认实现基于 getEdgeSegment 做线性插值;圆形等曲线形状可直接覆写。
116
+ */
117
+ getEdgePosition(edge: Edge, ratio: number): {
118
+ /** ratio 对应的边上位置。 */
119
+ pos: PointView;
120
+ /** 朝外法线的 x 分量。 */
121
+ nx: number;
122
+ /** 朝外法线的 y 分量。 */
123
+ ny: number;
124
+ };
125
+ getConnectionPortPosition(edge: Edge, ratio: number): PointView;
126
+ /** Replay the committed line/cubic snapshot into the current Canvas path. */
127
+ protected buildResolvedPath(ctx: CanvasRenderingContext2D): void;
128
+ paint(ctx?: CanvasRenderingContext2D): void;
129
+ /** 定义形状路径(width × height),hover 复用此路径 */
130
+ protected buildPath(ctx: CanvasRenderingContext2D): void;
131
+ /** 构建 border 描边路径 */
132
+ protected buildBorderPath(ctx: CanvasRenderingContext2D): void;
133
+ /** 使用 Shape 的实际路径裁剪 children。 */
134
+ protected applyChildClip(ctx: CanvasRenderingContext2D): void;
135
+ /** Shape 的 child clip 与其实际填充 path 使用同一 canonical query。 */
136
+ containsChildClipPoint(point: PointView): boolean;
137
+ /** 绘制元素自身内容(文字、图片等),默认为空 */
138
+ protected paintContent(_ctx: CanvasRenderingContext2D): void;
139
+ /** 绘制 Shape 的填充背景。 */
140
+ protected paintBackground(ctx: CanvasRenderingContext2D): void;
141
+ /** 按当前 border 样式绘制内容轮廓。 */
142
+ protected paintBorder(ctx: CanvasRenderingContext2D): void;
143
+ /** 在隔离的 Context 状态中绘制 shadow,不影响后续 fill 和 border。 */
144
+ private paintShadow;
145
+ paintHover(ctx: CanvasRenderingContext2D, scale: number): void;
146
+ }
@@ -0,0 +1,122 @@
1
+ import { Group } from "@tweenjs/tween.js";
2
+ import type { Layer } from "../layer";
3
+ import type { ElementTransform } from "../node/element-transform";
4
+ import type { Root } from "./index";
5
+ import type { PointView } from "@fulate/share";
6
+ import { Element } from "../node/element";
7
+ /** Root 唯一 frame runtime 可安装的单 participant 基础协议。 */
8
+ export interface RootFrameParticipant {
9
+ /** authored mutation work 是否仍需进入 stabilization round。 */
10
+ hasPendingWork(): boolean;
11
+ /** 消费本轮唯一 queued authored intent。 */
12
+ flushMutationPhase(): void;
13
+ /** stabilization 后是否有待更新的 Editor spatial projection。 */
14
+ hasPendingSpatialWork?(): boolean;
15
+ /** stabilization 后、overlay/RBush/paint 前更新 Editor spatial projection。 */
16
+ flushSpatialProjection?(): void;
17
+ /** stabilization 后是否需要重建唯一 Editor overlay projection。 */
18
+ hasPendingOverlayWork?(): boolean;
19
+ /** stabilization 后、RBush/paint 前重建唯一 Editor overlay projection。 */
20
+ flushOverlayProjection?(): void;
21
+ /** frame 派生工作和 transform completion 后是否还有完成通知。 */
22
+ hasPendingCompletionWork?(): boolean;
23
+ /** 在 geometry/spatial/overlay/RBush/paint/hover 后发布完成通知。 */
24
+ flushCompletionWork?(): void;
25
+ /** 使用当前 overlay projection 仲裁 content cursor。 */
26
+ resolveCursor?(point: PointView | undefined, contentCursor: string): string;
27
+ /** stabilization failure 时报告仍 dirty 的 owner keys。 */
28
+ getDirtyOwnerKeys?(): readonly string[];
29
+ }
30
+ /** 在唯一 Root frame 中提交派生布局的稳定 owner。 */
31
+ export interface RootFrameLayoutOwner {
32
+ readonly key: string;
33
+ /** 在当前 stabilization round 安装该 owner 的最终派生布局。 */
34
+ flushLayout(): void | readonly Element[];
35
+ }
36
+ /** Root frame-final 内部 work;相同函数引用在同一轮只执行一次。 */
37
+ export type RootFrameCompletionWork = () => void;
38
+ /** stabilization 超过统一轮次上限时暴露仍 dirty 的 owner keys。 */
39
+ export declare class FrameStabilizationError extends Error {
40
+ readonly dirtyOwnerKeys: readonly string[];
41
+ /** 创建包含稳定化结束时仍 dirty owner keys 的错误。 */
42
+ constructor(dirtyOwnerKeys: readonly string[]);
43
+ }
44
+ /** 管理 Root 唯一 RAF、稳定化循环、Tween、paint、hover 与 nextTick。 */
45
+ export declare class RootFrameRuntime {
46
+ private readonly root;
47
+ readonly animationGroup: Group;
48
+ private pendingLayers;
49
+ private pendingLayouts;
50
+ private pendingDirtyTransforms;
51
+ private pendingTransformCompletions;
52
+ private transformCompletionScratch;
53
+ private hoverRefreshPending;
54
+ private geometryStabilizing;
55
+ private publishingTransformCompletions;
56
+ private completionFollowUpFrameRequested;
57
+ private animationFrameScheduled;
58
+ private animationFrameId;
59
+ private participant;
60
+ private completionWork;
61
+ private nextTickPromise;
62
+ private nextTickResolve;
63
+ private nextTickReject;
64
+ /** 创建绑定指定 Root 生命周期的唯一 frame runtime。 */
65
+ constructor(root: Root);
66
+ /** 当前是否正在同步运行 geometry stabilization rounds。 */
67
+ get isStabilizingGeometry(): boolean;
68
+ /** 安装或移除 Root 生命周期内唯一的无调度 participant。 */
69
+ setParticipant(participant: RootFrameParticipant | null): void;
70
+ /** 判断 Layer 是否仍由当前活动 Root 拥有。 */
71
+ ownsLayer(layer: Layer): boolean;
72
+ /** 激活后为已存在的 animation、Layer 或 participant 工作请求帧。 */
73
+ activate(): void;
74
+ /** Layer 离开 Root 时丢弃其尚未消费的帧登记。 */
75
+ forgetLayer(layer: Layer): void;
76
+ /** 合并一个活动 Layer 的 geometry/paint 提交请求。 */
77
+ scheduleLayerCommit(layer: Layer): void;
78
+ /** 登记 stabilization round 结束时需要重置的 dirty transform。 */
79
+ registerDirtyTransform(transform: ElementTransform): void;
80
+ /** 合并一个派生布局 owner;同一稳定对象在一轮只提交一次。 */
81
+ scheduleLayout(owner: RootFrameLayoutOwner): void;
82
+ /** owner 离开当前 Root 时丢弃其尚未消费的布局工作。 */
83
+ forgetLayout(owner: RootFrameLayoutOwner): void;
84
+ /** @internal 合并实际完成 world transform commit 的 element identity。 */
85
+ recordTransformCommit(element: Element): void;
86
+ /** 把内部 work 合并到当前 Root 唯一 frame 的 completion phase。 */
87
+ requestCompletion(work: RootFrameCompletionWork): void;
88
+ /** 请求推进当前 animation group。 */
89
+ scheduleAnimation(): void;
90
+ /** 请求在 geometry、spatial index 和 paint 提交后刷新 hover。 */
91
+ scheduleHoverRefresh(): void;
92
+ /**
93
+ * 合并到当前 Root 唯一待执行 RAF。重复调用幂等,且不直接执行任何 phase。
94
+ */
95
+ requestFrame(): void;
96
+ /**
97
+ * 唯一同步稳定入口。取消尚未执行的 RAF,并使用与 RAF 相同的 phase 实现清空工作。
98
+ */
99
+ drain(): void;
100
+ private hasPendingSynchronousWork;
101
+ private needsAnotherFrame;
102
+ private runFrame;
103
+ /** 在 geometry/spatial/overlay/RBush/paint/hover 后派发实际 transform completion。 */
104
+ private publishTransformCompletions;
105
+ /** callback 边界后只发布当前 Root 和当前 transform 关系仍证明有效的完成事实。 */
106
+ private isCurrentTransformCompletion;
107
+ /** Core hit path 使用当前唯一 participant 仲裁 overlay/content cursor。 */
108
+ get hasCursorResolver(): boolean;
109
+ /** Core hit path 使用当前唯一 participant 仲裁 overlay/content cursor。 */
110
+ resolveCursor(point: PointView | undefined, contentCursor: string): string;
111
+ private consumeDirtyTransforms;
112
+ private flushLayouts;
113
+ private takePendingLayers;
114
+ private dirtyOwnerKeys;
115
+ private stabilize;
116
+ /** 停止 RAF、Tween 和待处理工作,并结清当前 `nextTick()`。 */
117
+ stop(): void;
118
+ private resolveNextTick;
119
+ private rejectNextTick;
120
+ /** 返回在当前已安排帧完成后结算的共享 Promise。 */
121
+ nextTick(): Promise<void>;
122
+ }
@@ -0,0 +1,34 @@
1
+ import { type PointView, type RectWithCenter } from "@fulate/share";
2
+ import type { Root } from "./index";
3
+ import { Element } from "../node/element";
4
+ /** `queryArea()` 使用的 world AABB 类型。 */
5
+ export type QueryAreaBounds = "visual" | "hit";
6
+ /** `queryArea()` 的返回顺序。 */
7
+ export type QueryAreaOrder = "paint" | "none";
8
+ /** `queryArea()` 的边界类型和排序选项。 */
9
+ export interface QueryAreaOptions {
10
+ /** 默认 `"visual"`;使用包含 shadow 的视觉边界或不含 shadow 的命中边界。 */
11
+ bounds?: QueryAreaBounds;
12
+ /** 默认 `"paint"`;`"none"` 不保证返回顺序。 */
13
+ order?: QueryAreaOrder;
14
+ }
15
+ /** Root ordered point-query filters applied before precise geometry. */
16
+ export interface IteratePointOptions {
17
+ /** Candidate element keys to omit. */
18
+ readonly exclude?: ReadonlySet<string>;
19
+ /** Only strict descendants of this active container key are considered. */
20
+ readonly scopeRootKey?: string;
21
+ }
22
+ /** 判断元素是否符合当前 Root 的 pointer target 语义。@internal */
23
+ export declare function isPointerTarget(root: Root, element: Element): boolean;
24
+ /**
25
+ * Yield the single canonical ordered point candidate stream. Broad-phase
26
+ * Layer/RBush work happens per yielded Layer; filters and precise geometry
27
+ * are evaluated only as the consumer advances the iterator.
28
+ */
29
+ export declare function iteratePointElements(root: Root, point: PointView, options?: IteratePointOptions): IterableIterator<Element>;
30
+ /** Consume and close exactly the first item from Root's canonical stream. */
31
+ export declare function firstPointElement(root: Root, point: PointView, options?: IteratePointOptions): any;
32
+ export declare function checkHit(root: Root, point?: PointView, sourceEvent?: MouseEvent): void;
33
+ export declare function clearHit(root: Root, point?: PointView, sourceEvent?: MouseEvent): void;
34
+ export declare function queryAreaElements(root: Root, area: RectWithCenter, options?: QueryAreaOptions): Element[];
@@ -0,0 +1,196 @@
1
+ import { Node } from "../node/node";
2
+ import type { NodeProperties } from "../node/properties";
3
+ import type { Layer } from "../layer";
4
+ import { Element } from "../node/element";
5
+ import { CustomEvent, type EventName, type FulateEventDetail } from "../event";
6
+ import type { PointView } from "@fulate/share";
7
+ import { RectWithCenter } from "@fulate/share";
8
+ import { RootInputController } from "./input-controller";
9
+ import { Viewport } from "./viewport";
10
+ import { type QueryAreaOptions, type IteratePointOptions } from "./hit-test";
11
+ import { Skin, type SkinChange } from "../skin";
12
+ import { RootFrameRuntime } from "./frame-runtime";
13
+ import { SceneRegistry } from "./scene-registry";
14
+ import { type ChangeHistorySink, type OwnerPropertyChange, type StructureChange } from "../mutation/change-batch";
15
+ export type { QueryAreaBounds, QueryAreaOptions, QueryAreaOrder, IteratePointOptions } from "./hit-test";
16
+ /** Root 当前 committed Canvas/element 绘制顺序。 */
17
+ export interface PaintOrderKey {
18
+ readonly layer: number;
19
+ readonly element: number;
20
+ }
21
+ /** 场景树根节点,统一管理 Layer、Viewport、输入、查询和帧提交。 */
22
+ export declare class Root extends Node<NodeProperties, Layer> {
23
+ /** Root 的序列化类型。 */
24
+ readonly type: string;
25
+ /** 承载 Layer Canvas 和 DOM 输入监听的容器。 */
26
+ readonly container: HTMLElement;
27
+ /** Root 使用的唯一 Skin;调用者直接修改其属性。 */
28
+ readonly skin: Skin;
29
+ /** 只在真实 Text dependent 存在时创建的 Skin text commit observers。 */
30
+ private skinTextCommitObservers?;
31
+ /** Root 的平移、缩放、DPR 和坐标换算对象。 */
32
+ readonly viewport: Viewport;
33
+ /** @internal Root 拥有的 DOM 输入和指针会话控制器。 */
34
+ readonly input: RootInputController;
35
+ /** @internal 活动节点 key 索引和场景变化观察器。 */
36
+ readonly sceneRegistry: SceneRegistry;
37
+ /** @internal 跨 Layer 帧队列、动画时钟和 nextTick 状态。 */
38
+ readonly frameRuntime: RootFrameRuntime;
39
+ /** Port 绘制、发现、Snap 和新建连接的全局开关;不影响已有 relation。 */
40
+ enablePorts: boolean;
41
+ /** 当前 hover 路径中最深的元素。 */
42
+ get currentElement(): Element<import("..").ElementProperties, import("..").BaseElementOption<any>, Partial<Omit<import("..").BaseElementOption<any>, "key" | "children">>>;
43
+ /** @internal 当前命中元素从祖先到叶子的 hover 路径。 */
44
+ hoverPath: Element[];
45
+ /** 当前 Root 逻辑宽度。 */
46
+ private widthValue;
47
+ /** 当前 Root 逻辑高度。 */
48
+ private heightValue;
49
+ /** Root 当前的逻辑宽度。 */
50
+ get width(): number;
51
+ /** Root 当前的逻辑高度。 */
52
+ get height(): number;
53
+ /** 已激活并按最终 Canvas 顺序排列的 Layer。 */
54
+ private registeredLayers;
55
+ /** 按 zIndex 和 Root 树顺序排列的活动 Layer 快照。 */
56
+ get layers(): readonly Layer[];
57
+ /** Root 每帧推进的 Tween group;自定义 Tween 还需请求动画帧。 */
58
+ get animationGroup(): import("@tweenjs/tween.js").Group;
59
+ /**
60
+ * 创建场景 Root;未传尺寸时读取容器 clientWidth/clientHeight。
61
+ * children 只能包含 Layer。
62
+ */
63
+ constructor(el: HTMLElement, options?: {
64
+ /** Root 构造期只读 key;省略时由 Core 自动生成。 */
65
+ readonly key?: string;
66
+ /** Root 逻辑宽度;默认读取容器 `clientWidth`。 */
67
+ width?: number;
68
+ /** Root 逻辑高度;默认读取容器 `clientHeight`。 */
69
+ height?: number;
70
+ /** Viewport 允许的最小和最大缩放倍率。 */
71
+ scale?: {
72
+ min?: number;
73
+ max?: number;
74
+ };
75
+ /** 是否初始启用 Port 绘制、发现、Snap 和新建连接;默认 `false`。 */
76
+ readonly enablePorts?: boolean;
77
+ /** 直接采用的 Skin 实例;省略时为当前内置默认皮肤。 */
78
+ readonly skin?: Skin;
79
+ /** 首次挂载的 Layer。 */
80
+ children?: readonly Layer[];
81
+ });
82
+ /** 运行时切换 Port 交互,并失效绘制和场景查询缓存。 */
83
+ setEnablePorts(enabled: boolean): void;
84
+ /** @internal Skin setter 安装新值后直接提交到当前 Root。 */
85
+ commitSkinChange(change: SkinChange): void;
86
+ /** @internal 订阅 Skin text commit;返回同一 observer 的注销函数。 */
87
+ observeSkinTextCommit(observer: () => void): () => void;
88
+ /** @internal 激活 Root 的输入、Viewport 和帧运行时。 */
89
+ protected onActivate(root: Root | null, layer: Layer | null): void;
90
+ /** @internal 停用 Root 拥有的输入、Viewport 和帧运行时。 */
91
+ protected onDeactivate(root: Root | null, layer: Layer | null): void;
92
+ /**
93
+ * 更新逻辑尺寸和所有 Layer surface,并在需要时重新布局和绘制;
94
+ * 实际尺寸变化安装完成后派发一次 `resize`。
95
+ * @param width Root 的逻辑宽度,通常来自容器 `clientWidth`。
96
+ * @param height Root 的逻辑高度,通常来自容器 `clientHeight`。
97
+ */
98
+ resize(width: number, height: number): void;
99
+ /** @internal 注册已激活的 Layer,并同步 Canvas 顺序。 */
100
+ registerLayer(layer: Layer): void;
101
+ /** 按 zIndex 和 Root children 顺序重排 Layer 及其 Canvas DOM。 */
102
+ private sortLayers;
103
+ /** @internal 在 children 事务提交后刷新 Layer 顺序、布局、绘制和 hover。 */
104
+ commitStructureChange(owner: Node, changed: readonly Node[]): void;
105
+ /** @internal trusted batch 只消费受影响 owners/subgraph,并合并 Layer 工作。 */
106
+ commitBatchStructureChanges(changes: readonly {
107
+ readonly owner: Node;
108
+ readonly changed: readonly Node[];
109
+ }[], layerOrderImpact?: boolean): void;
110
+ private commitStructureChanges;
111
+ /** @internal 返回结构提交后记录的 Layer 内 paint preorder。 */
112
+ getPaintOrder(element: Element): number | undefined;
113
+ /** @internal 返回跨 Layer 可直接比较的 committed paint key。 */
114
+ getPaintOrderKey(element: Element): PaintOrderKey | undefined;
115
+ /** @internal Layer zIndex 变化后重排 Canvas 并刷新 hover。 */
116
+ commitLayerOrderChange(): void;
117
+ /** @internal 注销停用的 Layer,并清除其待提交帧工作。 */
118
+ unregisterLayer(layer: Layer): void;
119
+ /** 请求所有活动 Layer 完整重绘。 */
120
+ invalidateAll(): void;
121
+ /** 判断 Layer 是否仍由当前活动 Root 拥有。 */
122
+ private ownsLayer;
123
+ /** @internal 将一个 Layer 的待处理工作加入 Root 帧队列。 */
124
+ scheduleLayerCommit(layer: Layer): void;
125
+ /** 请求动画帧以推进 animationGroup;本方法不会注册 Tween。 */
126
+ scheduleAnimation(): void;
127
+ /**
128
+ * 等待当前 frame-final completion 及其监听器同步新增的帧工作。
129
+ * 监听器抛错时以同一个 error reject;没有待处理帧时立即完成。
130
+ */
131
+ nextTick(): Promise<void>;
132
+ /**
133
+ * 同步应用领域已经决定的 owner/structure effects。
134
+ * 同 owner 只 finalize/install 一次,全部 fields/raw links 安装后统一发布。
135
+ */
136
+ applyChangeBatch(owners: readonly OwnerPropertyChange[], structure?: readonly StructureChange[], history?: ChangeHistorySink): void;
137
+ /** 按活动场景中的唯一 key 查询节点;key 来自 `node.key`。 */
138
+ getByKey(key: string): Node | undefined;
139
+ /**
140
+ * @internal 立即按给定 world 点或最近指针位置刷新 hover。
141
+ * @param point world 坐标;省略时转换 `input.lastPointerPos` 的 client 坐标。
142
+ * @param sourceEvent 触发本次重算的原始 DOM 鼠标事件。
143
+ */
144
+ checkHit(point?: PointView, sourceEvent?: MouseEvent): void;
145
+ /** @internal 节点停用后,如果它仍在 hover 路径中则重新命中。 */
146
+ clearHoverFor(node: Node): void;
147
+ /** @internal 安排在下一帧几何和绘制提交后刷新 hover。 */
148
+ scheduleHoverRefresh(): void;
149
+ /** 当前 Element 是否符合 Root 的 pointer target 语义。 @internal */
150
+ isPointerTarget(element: Element): boolean;
151
+ /**
152
+ * Lazily yield the topmost precise point candidates in committed paint order.
153
+ * Scope and exclusions are applied before each candidate's precise hit query.
154
+ */
155
+ iteratePoint(point: PointView, options?: IteratePointOptions): IterableIterator<Element>;
156
+ /**
157
+ * 返回 world 坐标下最上层的精确命中元素。
158
+ * @param point 可直接使用 Fulate 指针事件的 `detail.x/y`;DOM client 坐标先用 `viewport.getLogicalPosition()` 转换。
159
+ */
160
+ hitTest(point: PointView): Element | undefined;
161
+ /**
162
+ * 按 visual/hit world AABB 查询已提交的可选元素。
163
+ * @param area world 坐标查询矩形。
164
+ * @param options 选择 visual/hit 边界和返回顺序;省略时使用 visual + paint。
165
+ */
166
+ queryArea(area: RectWithCenter, options?: QueryAreaOptions): readonly Element[];
167
+ /**
168
+ * @internal 创建并派发一个带 world 坐标的 Fulate 输入事件。
169
+ * @param eventName Core 输入事件名。
170
+ * @param originalEvent 触发它的原始 DOM 事件;手动派发时可省略。
171
+ * @param point 已转换为 Root world 坐标的点。
172
+ * @param element 命中的活动元素;省略时事件目标为 Root。
173
+ */
174
+ dispatchInputEvent(eventName: EventName, originalEvent: Event | undefined, point: PointView, element?: Element): CustomEvent<FulateEventDetail<Element<import("..").ElementProperties, import("..").BaseElementOption<any>, Partial<Omit<import("..").BaseElementOption<any>, "key" | "children">>> | Root>>;
175
+ /** 导出 Root 尺寸、Skin 和 Viewport 状态。 */
176
+ toJSON(): {
177
+ /** Viewport 的可序列化状态。 */
178
+ viewport: {
179
+ x: number;
180
+ y: number;
181
+ scale: number;
182
+ minScale: number;
183
+ maxScale: number;
184
+ };
185
+ /** 当前 Skin 的独立可序列化值。 */
186
+ skin: Required<import("..").SkinOptions>;
187
+ /** Root 逻辑宽度。 */
188
+ width: number;
189
+ /** Root 逻辑高度。 */
190
+ height: number;
191
+ };
192
+ /** @internal 递归卸载前停止并释放 Root 运行时。 */
193
+ protected onBeforeUnmount(): void;
194
+ /** @internal children 清理后释放 Root 持有的索引和输入状态。 */
195
+ protected onUnmount(): void;
196
+ }
@@ -0,0 +1,103 @@
1
+ import { Element } from "../node/element";
2
+ import type { Node as SceneNode } from "../node/node";
3
+ import type { Root } from "./index";
4
+ import type { MutablePointView } from "@fulate/share";
5
+ /** 判断键盘事件目标是否应保留浏览器原生空格输入。 */
6
+ export declare function isFormControlTarget(target: EventTarget | null): boolean;
7
+ /** Root 拥有的 DOM 输入监听、指针会话和交互范围控制器。 */
8
+ export declare class RootInputController {
9
+ private readonly root;
10
+ /** @internal 当前 Root 是否处于空格平移模式。 */
11
+ isSpacePressed: boolean;
12
+ /** @internal 是否正在用指针平移 Viewport。 */
13
+ isPanning: boolean;
14
+ /** @internal 是否应在连续指针操作期间暂停 hover 重算。 */
15
+ hasLockPoint: boolean;
16
+ /** @internal 最近一次 DOM 指针的 clientX/clientY,不是 world 坐标。 */
17
+ lastPointerPos: MutablePointView;
18
+ /** 最近一次记录的指针是否位于 Root 容器内。 */
19
+ private pointerInside;
20
+ /** 当前允许接收元素级输入的工具子树根节点。 */
21
+ private readonly interactionScopes;
22
+ /** 一次 Root 激活周期内全部 DOM listener 的统一清理器。 */
23
+ private abortController;
24
+ /** 当前捕获的 primary pointer id;`null` 表示没有会话。 */
25
+ private activePointerId;
26
+ /** 当前场景点击或空格平移会话。 */
27
+ private pointerSession;
28
+ /** 上一次有效 click,用于 500ms/4px 的双击判断。 */
29
+ private lastClick;
30
+ /** @internal 由 Root 构造;单独实例化不会接入 Root 生命周期。 */
31
+ constructor(root: Root);
32
+ /** @internal Root 当前是否认为指针位于容器内。 */
33
+ get isPointerInside(): boolean;
34
+ /** @internal 安装当前 Root 的键盘、指针、滚轮和焦点监听。 */
35
+ activate(): void;
36
+ /** @internal 移除监听并清理当前输入和 hover 会话。 */
37
+ deactivate(): void;
38
+ /** @internal 停用控制器并释放全部 interaction scope。 */
39
+ dispose(): void;
40
+ /** @internal 取消全部指针会话,或仅取消目标位于指定节点子树的场景会话。 */
41
+ cancelSession(node?: SceneNode): void;
42
+ /** @internal 更新容器内外状态。 */
43
+ setPointerInside(inside: boolean): void;
44
+ /** @internal 注册工具交互范围,只让其子树接收元素级输入,并返回注销函数。 */
45
+ registerInteractionScope(scope: Element): () => void;
46
+ /** @internal 判断命中元素是否属于当前任一 interaction scope。 */
47
+ isInteractionTarget(element: Element): boolean;
48
+ /** Root 容器所属的 Document。 */
49
+ private get ownerDocument();
50
+ /** Root 容器所属的 Window;缺失时回退当前全局 window。 */
51
+ private get ownerWindow();
52
+ /** 在指针、焦点和捕获均不属于本 Root 时释放键盘输入归属。 */
53
+ private releaseActiveRoot;
54
+ /** 保存 DOM client 坐标,供无显式事件的 hover 重算使用。 */
55
+ private updatePointer;
56
+ /** 将一个 DOM 输入转换为 Fulate world 事件并派给当前场景目标。 */
57
+ private dispatchDomEvent;
58
+ /** 清除活动 pointer id,并释放容器上的 pointer capture。 */
59
+ private releasePointer;
60
+ /** 释放 InputController 自己创建的 pointer capture 和 ephemeral session 状态。 */
61
+ private releasePointerSessionResources;
62
+ /** 把 pointerup/pointercancel 发给 pointerdown 时捕获的场景目标。 */
63
+ private notifySceneSession;
64
+ /** 取消当前会话、释放捕获,并清除 hover 锁和双击候选。 */
65
+ private cancelPointerSession;
66
+ /** 回调可能同步停用 Root;发生时立即取消剩余输入流程。 */
67
+ private stopIfRootInactive;
68
+ /** 进入空格平移模式,并清除普通 hover。 */
69
+ private readonly onKeyDown;
70
+ /** 退出空格平移模式,并在没有平移会话时恢复 hover。 */
71
+ private readonly onKeyUp;
72
+ /** 记录指针进入,并把同 Document 的键盘归属切到当前 Root。 */
73
+ private readonly onPointerEnter;
74
+ /** Root 内获得焦点时取得同 Document 的键盘归属。 */
75
+ private readonly onFocusIn;
76
+ /** 焦点离开后按当前指针和捕获状态决定是否释放键盘归属。 */
77
+ private readonly onFocusOut;
78
+ /** 更新拖动阈值、Viewport 平移或普通场景 pointermove。 */
79
+ private readonly onPointerMove;
80
+ /** 无 pointer capture 时清空 hover,并尝试释放键盘归属。 */
81
+ private readonly onPointerLeave;
82
+ /** 捕获 primary pointer,并创建场景或平移会话。 */
83
+ private readonly onPointerDown;
84
+ /**
85
+ * 结束捕获会话,派发 up/cancel,并在满足阈值时生成 click/dblclick。
86
+ *
87
+ * @privateRemarks
88
+ * click 必须使用会话结束后重新命中的目标,并与 pointerdown 目标相同。
89
+ */
90
+ private finishPointer;
91
+ /** 正常结束当前 pointer 会话。 */
92
+ private readonly onPointerUp;
93
+ /** 以取消状态结束当前 pointer 会话。 */
94
+ private readonly onPointerCancel;
95
+ /** 先派发 scene wheel;未取消时再按 DOM delta 缩放 Viewport。 */
96
+ private readonly onWheel;
97
+ /** 派发场景 contextmenu,并按 defaultPrevented 决定是否阻止浏览器菜单。 */
98
+ private readonly onContextMenu;
99
+ /** pointer capture 意外丢失时取消匹配的活动会话。 */
100
+ private readonly onLostPointerCapture;
101
+ /** 宿主窗口失焦时取消会话、空格模式和 hover。 */
102
+ private readonly onWindowBlur;
103
+ }