@fulate/ui 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/README.md +197 -199
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,199 +1,197 @@
1
- # @fulate/ui authored paths
2
-
3
- > 文档角色:`GUIDE`。权威来源:UI 源码 TSDoc 与测试;Path/Line 的跨域长期契约见 [`docs/specs/path-line-core.md`](../../docs/specs/path-line-core.md)。
4
-
5
- ## Bitmap surface
6
-
7
- `Bitmap`唯一拥有主线程当前frame,并向位图producer提供`renderPixelRatio = Viewport scale × DPR`。
8
- producer保持authored-local布局;需要超采样时,在自己的backend中基于该倍率增加质量倍率和资源预算。
9
- `paintBitmap()`仍把最终位图绘制到图元authored宽高,再由Layer应用Viewport与DPR。
10
-
11
- 位图、DPR和超采样质量都不改变逻辑坐标。鼠标与Worker返回的坐标保持authored-local,不经过
12
- `Bitmap`的scale换算。
13
-
14
- ## Workspace fit
15
-
16
- `WorkspaceOption.fit`控制首次进入Root时的自动聚焦,`WorkspaceOption.fitOnResize`控制Root尺寸
17
- 变化后的自动重新聚焦;两者默认都是`true`,也可以独立关闭。首次fit在Workspace的初始几何提交后、
18
- 首个Canvas paint前直接安装最终Viewport,不播放动画。同一帧内连续发生的Root尺寸变化只按最终尺寸
19
- 执行一次无动画fit。两条路径都读取当前Root提供的实时可见区insets。
20
-
21
- 编辑器按钮、导入完成等外部流程直接调用同一公开函数,不复制Workspace bounds或Viewport focus规则:
22
-
23
- ```ts
24
- import { fitWorkspace } from "@fulate/ui";
25
-
26
- await fitWorkspace(workspace, { padding: 0 });
27
- ```
28
-
29
- 显式调用不受`WorkspaceOption.fit`或`WorkspaceOption.fitOnResize`限制;传入的focus options会按原引用
30
- 直接交给Workspace所属Root的Viewport。用户触发的fit需要动画时由调用者显式传入`animate`。
31
-
32
- `Line`、`Polygon` `VectorPath` 都只有一份 live canonical authored owner:
33
-
34
- | 元素 | 普通创建输入 | live getter | topology |
35
- | --- | --- | --- | --- |
36
- | `Line` | `path: PointView[]` | `line.path` | 一个 openline-only subpath |
37
- | `Polygon` | `contour: PointView[]` | `polygon.contour` | 一个 closed、line-only subpath |
38
- | `VectorPath` | `path: VectorPathCommand[]` | `vector.path.subpaths` | ordered open/closed line/cubic subpaths |
39
-
40
- 普通输入只在入口解释一次。每个 canonical anchor record 直接保存 `anchorId`、原 `point` 引用,
41
- 并在存在 outgoing segment 时共置 `segmentId` 与 `line | cubic` 数据;普通 line segment 没有
42
- 独立 wrapper。Geometry resolver 让 `vertices` 和 `segmentShapes` 直接复用这些 records。
43
-
44
- ```ts
45
- const line = new Line({
46
- path: [{ x: 0, y: 0 }, { x: 80, y: 30 }]
47
- });
48
-
49
- const anchorId = line.headAnchor.anchorId;
50
- line.setLocalPoint(anchorId, { x: 10, y: 5 });
51
- ```
52
-
53
- 坐标更新、transform、History restore 保留既有 local IDs;insert 只创建新增 IDs,delete 保留
54
- 未受影响 IDs。传入 canonical whole value 时按引用 identity 判断:同一引用是 noop,不同引用
55
- 即使内容相同也会被采用。point/control 等结构化值不做 caller-isolation clone;需要隔离时由
56
- 调用者在传入前复制。调用者在所有权移交后原地修改同一对象不会自动产生 commit、dirty、
57
- History frame。
58
-
59
- ## Connection、Port 与 Line endpoints
60
-
61
- Path authored `anchorId` 与 target owner-local `portId` 是两个概念。Line 首尾 endpoint 与
62
- LineTree root/leaf endpoint只保存source-owned relation:
63
-
64
- ```ts
65
- interface EndpointRelation {
66
- readonly kind: "endpoint-binding";
67
- readonly target: {
68
- readonly elementKey: string;
69
- readonly portId: string;
70
- };
71
- }
72
- ```
73
-
74
- relation不保存坐标。`Line.path`与`LineTree.topology.points`保存authored fallback;paint、hit、bounds、
75
- query和controls从当前target Port解析effective geometry。target变化只通过Root唯一
76
- `EndpointRelationIndex`精确dirty dependents,不反写source authored值或History。
77
-
78
- Line的`relations` patch省略时两端保持;对象中省略一端也表示保持,own `undefined`清除该端,
79
- `EndpointRelation`建立或替换。程序化连接使用同步`connectEndpoint(root, source, target)`与
80
- `disconnectEndpoint(root, source)`;普通noop返回`void`且不创建结果状态机。
81
-
82
- Line首端/root endpoint的连接role是`output`,尾端/leaf是`input`;装饰不决定连接role。同步
83
- `connectEndpoint()`从live source与target Port读取role、`direction`和对应capacity;方向不兼容、容量
84
- 已满或target Port不存在时保持noop。Tools picker复用同一规则,受阻Port不能降级成自由落点。
85
-
86
- `Element.ports`是`false | true | readonly ConnectionPortDefinition[]`的唯一authored owner。构造时
87
- 省略等同`false`;`false`没有Port,`true`使用元素类型的默认schema,数组作为custom whole-value按
88
- 原引用采用,`[]`表示当前custom配置为空。patch省略`ports`保持当前值;不支持`null`。数组同引用
89
- noop,不clone、freeze、normalize或deep-equal。
90
- `Root.enablePorts`默认`false`并可通过`setEnablePorts()`切换;关闭时不绘制、发现或Snap Port,也不
91
- 允许`connectEndpoint()`新建relation。按已知Port ID解析和已有relation的target observer始终有效,
92
- 因此Line/LineTree继续跟随目标;显式Port删除/替换仍物化当前fallback并detach。完整开关边界见
93
- [`path-line-core.md`](../../docs/specs/path-line-core.md#10-transformpointbinding-与-routing-边界)。
94
-
95
- JSON、clipboard和History的独立输出复制所需数据;restore直接安装canonical path/topology、IDs
96
- source-owned relations。source与target一起复制时只重映射element key;只复制source时使用当前
97
- resolved source-local fallback并删除外部relation;完整owner的subpath/anchor/segment/Port IDs保留。
98
-
99
- ## LineTree
100
-
101
- `LineTree`是一整个场景元素,不包含隐藏的`Line` child。`topology.points`唯一拥有坐标和可选
102
- EndpointRelation,`topology.branches`只通过稳定`SubpathId/AnchorId/
103
- SegmentId`引用这些points;非root branch用`parentSubpathId`表达同一owner内的唯一父分支。
104
- 当前branch只有straight/polyline,不保存kind或Orthogonal/cubic预留variant。
105
-
106
- ```ts
107
- const topology = createLineTreeTopology([
108
- { x: 0, y: 0 },
109
- { x: 120, y: 0 }
110
- ]);
111
- const tree = new LineTree({ topology });
112
- const root = topology.branches[0];
113
-
114
- tree.replaceTopology(addLineTreeBranchAtTail(
115
- tree.topology,
116
- root.subpathId,
117
- [{ x: 120, y: 80 }]
118
- ).topology);
119
- ```
120
-
121
- 普通选择、hover、copy、delete、Transform、RBush和History owner始终只有`tree`一个。双击精确
122
- branch后Point projection只请求该subpath;删除父branch由`removeLineTreeBranch()`在一个owner-local
123
- delta中删除全部descendants和孤儿points。外部topology输入按原引用采用;domain edit只复制实际
124
- changed records及必要外层数组。新增branch只复用parent branch的尾点;Editor交互允许任意branch
125
- tail成为source,同一junction tail可重复产生sibling branches,但junction不绘制tail三角形。树干segment和中间anchor都不是branch source,也
126
- 不会因扩展操作被插入junction。
127
-
128
- LineLineTree的stroke和端点decoration在world空间按固定宽度绘制;自身visual bounds与render
129
- coverage覆盖同一完整绘制范围,反向近零Transform也不会缩掉dirty coverage。固定world paint padding
130
- 不贡献ancestor content bounds;Group selection、resize与snap只消费Line/LineTree的effective path
131
- geometry。hover与active branch highlight复用同一polyline paint,箭头和线段保持同色。
132
-
133
- Rectangle、Triangle及其他Shape省略`backgroundColor`/`borderColor`时读取当前Root的
134
- `skin.shapeFill`/`skin.shapeStroke`;Line和LineTree branch省略`strokeColor`时读取
135
- `skin.lineStroke`。显式值始终优先,Shape的显式`null`关闭绘制,显式字段清回`undefined`后立即重新
136
- 继承Skin。Skin改变只触发现有Root/Layer重绘,不改写element、branch topology或History。
137
-
138
- LineTree整体resize继续使用O(1) pose。随后Point移动或插入anchor时在同一owner change内保留当前
139
- world pose;包括反向scale在内,只有目标anchor改变world位置,其他points保持不动。
140
-
141
- ## Text 尺寸与显示
142
-
143
- `Text` 未提供 `width`/`height` 时使用当前文字的 intrinsic 尺寸;提供尺寸后,该尺寸成为布局盒。
144
- `wordWrap` 只控制是否按布局宽度换行,`ellipsis` 只控制是否把被截断内容绘制为 `…`,`overflow`
145
- 只控制是否裁剪绘制内容,三个选项可以独立组合。Text 默认使用 intrinsic 尺寸、`wordWrap=false`、
146
- `overflow="visible"` 且不启用省略号;组件若需要 Web 控件式的填满、裁剪或省略,应显式传入对应属性。
147
-
148
- Editor 的 Text selection/resize frame 使用布局盒,不使用可见溢出 glyph 的 visual bounds。因此
149
- `wordWrap={false}`、`overflow="visible"` 的文本被缩放后,取消选择再重新选择仍保持上一次 authored
150
- 尺寸,下一次缩放也从该尺寸继续。
151
-
152
- ### 原生 Canvas 文本 run
153
-
154
- 组合型原生 Shape 可以直接传入 live resolved Skin,按 `Text` 相同的字体、行高、Canvas baseline
155
- 和字符间距语义测量一段文本,不需要复制或整理 style:
156
-
157
- ```ts
158
- import { measureTextRun } from "@fulate/ui";
159
-
160
- const metrics = measureTextRun(ctx, text, root.skin.text, 14, 500);
161
- ```
162
-
163
- 每次调用只执行一次 `ctx.measureText()`,返回 `font`、`width`、`lineHeight`、`drawY`
164
- `alphabeticBaseline`。空文本的 `width` 为 `0`,但仍测量一个空格以取得稳定基线。函数会把本次
165
- 测量所需的文字状态写入 `ctx`,不会调用 `save()` 或 `restore()`;Canvas 生命周期以及业务特有的
166
- 文字顺序、对齐和绘制仍由 Shape 自己拥有。
167
-
168
- ## Editor capabilities
169
-
170
- UI 元素通过对象 identity token 直接提供 Selection、Transform、Snap、Point 与 Content capability;
171
- 没有 registry、字符串 key、implicit default、layout writer 或 Tools duck fields。
172
- Selection 的闭集策略使用公开枚举:
173
-
174
- ```ts
175
- import {
176
- SelectionBehaviorMode,
177
- SelectionDiveMode,
178
- SelectionSnapMode
179
- } from "@fulate/ui";
180
-
181
- const behavior = {
182
- mode: SelectionBehaviorMode.OwnerDirect,
183
- dive: SelectionDiveMode.None,
184
- snap: SelectionSnapMode.Disabled
185
- };
186
- ```
187
-
188
- `OwnerDirect` 用于不绘制单选 frame、首次位移可直接提升 owner drag 的自定义对象;Group 使用
189
- `DirectChild` dive,普通 Shape/Line 使用 `Standard`。Transform provider 在 gesture start 捕获 frozen
190
- reference 与领域 owned state,每帧只纯解析最终 owner change;frame-authored Shape、pose-authored
191
- Group authored-geometry Line/Polygon/VectorPath 共用 Core reference-transform primitive,结构化
192
- authored value 不为 caller isolation cloneGroup 的稳定 reference 由创建时的 width/height/origin 与
193
- pose 拥有;当前 content bounds 是只读 local derived view。Line/LineTree 的
194
- 固定world paint padding不贡献ancestor content bounds,但仍进入各自render coverage。group/ungroup
195
- 只转换 local pose,保留 width/path/contour/topologyeffect relation 的值和引用。
196
-
197
- `selectable:false`只限制Editor交互选择,并对该owner分支生效:普通点击、marquee、Select All与
198
- Group DirectChild下钻都不能进入该分支。公开`Select.select(elements)`和History selection replay由
199
- 调用者直接控制,不增加过滤;把已选owner改为`selectable:false`也不会自动清除当前selection。
1
+ # @fulate/ui authored paths
2
+
3
+ ## Bitmap surface
4
+
5
+ `Bitmap`唯一拥有主线程当前frame,并向位图producer提供`renderPixelRatio = Viewport scale × DPR`。
6
+ producer保持authored-local布局;需要超采样时,在自己的backend中基于该倍率增加质量倍率和资源预算。
7
+ `paintBitmap()`仍把最终位图绘制到图元authored宽高,再由Layer应用ViewportDPR
8
+
9
+ 位图、DPR和超采样质量都不改变逻辑坐标。鼠标与Worker返回的坐标保持authored-local,不经过
10
+ `Bitmap`的scale换算。
11
+
12
+ ## Workspace fit
13
+
14
+ `WorkspaceOption.fit`控制首次进入Root时的自动聚焦,`WorkspaceOption.fitOnResize`控制Root尺寸
15
+ 变化后的自动重新聚焦;两者默认都是`true`,也可以独立关闭。首次fit在Workspace的初始几何提交后、
16
+ 首个Canvas paint前直接安装最终Viewport,不播放动画。同一帧内连续发生的Root尺寸变化只按最终尺寸
17
+ 执行一次无动画fit。两条路径都读取当前Root提供的实时可见区insets。
18
+
19
+ 编辑器按钮、导入完成等外部流程直接调用同一公开函数,不复制Workspace bounds或Viewport focus规则:
20
+
21
+ ```ts
22
+ import { fitWorkspace } from "@fulate/ui";
23
+
24
+ await fitWorkspace(workspace, { padding: 0 });
25
+ ```
26
+
27
+ 显式调用不受`WorkspaceOption.fit`或`WorkspaceOption.fitOnResize`限制;传入的focus options会按原引用
28
+ 直接交给Workspace所属Root的Viewport。用户触发的fit需要动画时由调用者显式传入`animate`。
29
+
30
+ `Line`、`Polygon` 和 `VectorPath` 都只有一份 live canonical authored owner:
31
+
32
+ | 元素 | 普通创建输入 | live getter | topology |
33
+ | --- | --- | --- | --- |
34
+ | `Line` | `path: PointView[]` | `line.path` | 一个 open、line-only subpath |
35
+ | `Polygon` | `contour: PointView[]` | `polygon.contour` | 一个 closed、line-only subpath |
36
+ | `VectorPath` | `path: VectorPathCommand[]` | `vector.path.subpaths` | ordered open/closed line/cubic subpaths |
37
+
38
+ 普通输入只在入口解释一次。每个 canonical anchor record 直接保存 `anchorId`、原 `point` 引用,
39
+ 并在存在 outgoing segment 时共置 `segmentId` 与 `line | cubic` 数据;普通 line segment 没有
40
+ 独立 wrapper。Geometry resolver `vertices` `segmentShapes` 直接复用这些 records。
41
+
42
+ ```ts
43
+ const line = new Line({
44
+ path: [{ x: 0, y: 0 }, { x: 80, y: 30 }]
45
+ });
46
+
47
+ const anchorId = line.headAnchor.anchorId;
48
+ line.setLocalPoint(anchorId, { x: 10, y: 5 });
49
+ ```
50
+
51
+ 坐标更新、transform、History restore 保留既有 local IDs;insert 只创建新增 IDs,delete 保留
52
+ 未受影响 IDs。传入 canonical whole value 时按引用 identity 判断:同一引用是 noop,不同引用
53
+ 即使内容相同也会被采用。point/control 等结构化值不做 caller-isolation clone;需要隔离时由
54
+ 调用者在传入前复制。调用者在所有权移交后原地修改同一对象不会自动产生 commit、dirty、
55
+ History frame。
56
+
57
+ ## Connection、Port 与 Line endpoints
58
+
59
+ Path authored `anchorId` target owner-local `portId` 是两个概念。Line 首尾 endpoint 与
60
+ LineTree root/leaf endpoint只保存source-owned relation:
61
+
62
+ ```ts
63
+ interface EndpointRelation {
64
+ readonly kind: "endpoint-binding";
65
+ readonly target: {
66
+ readonly elementKey: string;
67
+ readonly portId: string;
68
+ };
69
+ }
70
+ ```
71
+
72
+ relation不保存坐标。`Line.path`与`LineTree.topology.points`保存authored fallback;paint、hit、bounds、
73
+ query和controls从当前target Port解析effective geometry。target变化只通过Root唯一
74
+ `EndpointRelationIndex`精确dirty dependents,不反写source authored值或History。
75
+
76
+ Line的`relations` patch省略时两端保持;对象中省略一端也表示保持,own `undefined`清除该端,
77
+ `EndpointRelation`建立或替换。程序化连接使用同步`connectEndpoint(root, source, target)`与
78
+ `disconnectEndpoint(root, source)`;普通noop返回`void`且不创建结果状态机。
79
+
80
+ Line首端/root endpoint的连接role是`output`,尾端/leaf是`input`;装饰不决定连接role。同步
81
+ `connectEndpoint()`从live source与target Port读取role、`direction`和对应capacity;方向不兼容、容量
82
+ 已满或target Port不存在时保持noop。Tools picker复用同一规则,受阻Port不能降级成自由落点。
83
+
84
+ `Element.ports`是`false | true | readonly ConnectionPortDefinition[]`的唯一authored owner。构造时
85
+ 省略等同`false`;`false`没有Port,`true`使用元素类型的默认schema,数组作为custom whole-value按
86
+ 原引用采用,`[]`表示当前custom配置为空。patch省略`ports`保持当前值;不支持`null`。数组同引用
87
+ noop,不clone、freeze、normalize或deep-equal。
88
+ `Root.enablePorts`默认`false`并可通过`setEnablePorts()`切换;关闭时不绘制、发现或Snap Port,也不
89
+ 允许`connectEndpoint()`新建relation。按已知Port ID解析和已有relation的target observer始终有效,
90
+ 因此Line/LineTree继续跟随目标;显式Port删除/替换仍物化当前fallback并detach。完整开关边界见
91
+ [`path-line-core.md`](../../docs/specs/path-line-core.md#10-transformpointbinding-与-routing-边界)
92
+
93
+ JSON、clipboard和History的独立输出复制所需数据;restore直接安装canonical path/topology、IDs和
94
+ source-owned relations。source与target一起复制时只重映射element key;只复制source时使用当前
95
+ resolved source-local fallback并删除外部relation;完整owner的subpath/anchor/segment/Port IDs保留。
96
+
97
+ ## LineTree
98
+
99
+ `LineTree`是一整个场景元素,不包含隐藏的`Line` child。`topology.points`唯一拥有坐标和可选
100
+ EndpointRelation,`topology.branches`只通过稳定`SubpathId/AnchorId/
101
+ SegmentId`引用这些points;非root branch用`parentSubpathId`表达同一owner内的唯一父分支。
102
+ 当前branch只有straight/polyline,不保存kind或Orthogonal/cubic预留variant。
103
+
104
+ ```ts
105
+ const topology = createLineTreeTopology([
106
+ { x: 0, y: 0 },
107
+ { x: 120, y: 0 }
108
+ ]);
109
+ const tree = new LineTree({ topology });
110
+ const root = topology.branches[0];
111
+
112
+ tree.replaceTopology(addLineTreeBranchAtTail(
113
+ tree.topology,
114
+ root.subpathId,
115
+ [{ x: 120, y: 80 }]
116
+ ).topology);
117
+ ```
118
+
119
+ 普通选择、hover、copy、delete、Transform、RBush和History owner始终只有`tree`一个。双击精确
120
+ branch后Point projection只请求该subpath;删除父branch由`removeLineTreeBranch()`在一个owner-local
121
+ delta中删除全部descendants和孤儿points。外部topology输入按原引用采用;domain edit只复制实际
122
+ changed records及必要外层数组。新增branch只复用parent branch的尾点;Editor交互允许任意branch
123
+ tail成为source,同一junction tail可重复产生sibling branches,但junction不绘制tail三角形。树干segment和中间anchor都不是branch source,也
124
+ 不会因扩展操作被插入junction。
125
+
126
+ Line与LineTree的stroke和端点decoration在world空间按固定宽度绘制;自身visual bounds与render
127
+ coverage覆盖同一完整绘制范围,反向近零Transform也不会缩掉dirty coverage。固定world paint padding
128
+ 不贡献ancestor content bounds;Group selection、resize与snap只消费Line/LineTree的effective path
129
+ geometry。hover与active branch highlight复用同一polyline paint,箭头和线段保持同色。
130
+
131
+ Rectangle、Triangle及其他Shape省略`backgroundColor`/`borderColor`时读取当前Root的
132
+ `skin.shapeFill`/`skin.shapeStroke`;Line和LineTree branch省略`strokeColor`时读取
133
+ `skin.lineStroke`。显式值始终优先,Shape的显式`null`关闭绘制,显式字段清回`undefined`后立即重新
134
+ 继承Skin。Skin改变只触发现有Root/Layer重绘,不改写element、branch topology或History。
135
+
136
+ LineTree整体resize继续使用O(1) pose。随后Point移动或插入anchor时在同一owner change内保留当前
137
+ world pose;包括反向scale在内,只有目标anchor改变world位置,其他points保持不动。
138
+
139
+ ## Text 尺寸与显示
140
+
141
+ `Text` 未提供 `width`/`height` 时使用当前文字的 intrinsic 尺寸;提供尺寸后,该尺寸成为布局盒。
142
+ `wordWrap` 只控制是否按布局宽度换行,`ellipsis` 只控制是否把被截断内容绘制为 `…`,`overflow`
143
+ 只控制是否裁剪绘制内容,三个选项可以独立组合。Text 默认使用 intrinsic 尺寸、`wordWrap=false`、
144
+ `overflow="visible"` 且不启用省略号;组件若需要 Web 控件式的填满、裁剪或省略,应显式传入对应属性。
145
+
146
+ Editor Text selection/resize frame 使用布局盒,不使用可见溢出 glyph 的 visual bounds。因此
147
+ `wordWrap={false}`、`overflow="visible"` 的文本被缩放后,取消选择再重新选择仍保持上一次 authored
148
+ 尺寸,下一次缩放也从该尺寸继续。
149
+
150
+ ### 原生 Canvas 文本 run
151
+
152
+ 组合型原生 Shape 可以直接传入 live resolved Skin,按 `Text` 相同的字体、行高、Canvas baseline
153
+ 和字符间距语义测量一段文本,不需要复制或整理 style:
154
+
155
+ ```ts
156
+ import { measureTextRun } from "@fulate/ui";
157
+
158
+ const metrics = measureTextRun(ctx, text, root.skin.text, 14, 500);
159
+ ```
160
+
161
+ 每次调用只执行一次 `ctx.measureText()`,返回 `font`、`width`、`lineHeight`、`drawY` 和
162
+ `alphabeticBaseline`。空文本的 `width` 为 `0`,但仍测量一个空格以取得稳定基线。函数会把本次
163
+ 测量所需的文字状态写入 `ctx`,不会调用 `save()` `restore()`;Canvas 生命周期以及业务特有的
164
+ 文字顺序、对齐和绘制仍由 Shape 自己拥有。
165
+
166
+ ## Editor capabilities
167
+
168
+ UI 元素通过对象 identity token 直接提供 Selection、Transform、Snap、Point 与 Content capability;
169
+ 没有 registry、字符串 key、implicit default、layout writer 或 Tools duck fields。
170
+ Selection 的闭集策略使用公开枚举:
171
+
172
+ ```ts
173
+ import {
174
+ SelectionBehaviorMode,
175
+ SelectionDiveMode,
176
+ SelectionSnapMode
177
+ } from "@fulate/ui";
178
+
179
+ const behavior = {
180
+ mode: SelectionBehaviorMode.OwnerDirect,
181
+ dive: SelectionDiveMode.None,
182
+ snap: SelectionSnapMode.Disabled
183
+ };
184
+ ```
185
+
186
+ `OwnerDirect` 用于不绘制单选 frame、首次位移可直接提升 owner drag 的自定义对象;Group 使用
187
+ `DirectChild` dive,普通 Shape/Line 使用 `Standard`。Transform provider 在 gesture start 捕获 frozen
188
+ reference 与领域 owned state,每帧只纯解析最终 owner change;frame-authored Shape、pose-authored
189
+ Group authored-geometry Line/Polygon/VectorPath 共用 Core reference-transform primitive,结构化
190
+ authored value 不为 caller isolation clone。Group 的稳定 reference 由创建时的 width/height/origin 与
191
+ pose 拥有;当前 content bounds 是只读 local derived view。Line/LineTree 的
192
+ 固定world paint padding不贡献ancestor content bounds,但仍进入各自render coveragegroup/ungroup
193
+ 只转换 local pose,保留 width/path/contour/topology、effect relation 的值和引用。
194
+
195
+ `selectable:false`只限制Editor交互选择,并对该owner分支生效:普通点击、marqueeSelect All
196
+ Group DirectChild下钻都不能进入该分支。公开`Select.select(elements)`和History selection replay由
197
+ 调用者直接控制,不增加过滤;把已选owner改为`selectable:false`也不会自动清除当前selection。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fulate/ui",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",