@pisell/materials 1.8.54 → 1.8.56

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 (151) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/async/view.js +1 -1
  5. package/build/lowcode/index.js +1 -1
  6. package/build/lowcode/meta.js +3 -3
  7. package/build/lowcode/preview.js +1 -1
  8. package/build/lowcode/render/default/async/view.js +1 -1
  9. package/build/lowcode/render/default/view.css +1 -1
  10. package/build/lowcode/render/default/view.js +37 -37
  11. package/build/lowcode/view.css +1 -1
  12. package/build/lowcode/view.js +37 -37
  13. package/es/components/buttonGroupPreview/index.js +8 -4
  14. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.js +207 -49
  15. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.less +33 -2
  16. package/es/components/pisellFloorMapLayout/appearance/floorMapAppearance.js +50 -2
  17. package/es/components/pisellFloorMapLayout/components/EdgeLayer.js +252 -0
  18. package/es/components/pisellFloorMapLayout/components/EdgeLayer.less +11 -0
  19. package/es/components/pisellFloorMapLayout/components/EditableItemLayer.js +179 -29
  20. package/es/components/pisellFloorMapLayout/components/EditableItemLayer.less +0 -28
  21. package/es/components/pisellFloorMapLayout/components/FloorMapEdgeEditPanel.js +131 -0
  22. package/es/components/pisellFloorMapLayout/components/FloorMapEdgeEditPanel.less +65 -0
  23. package/es/components/pisellFloorMapLayout/components/FloorMapEditPanel.js +5 -4
  24. package/es/components/pisellFloorMapLayout/components/FloorMapEditPanel.less +12 -1
  25. package/es/components/pisellFloorMapLayout/components/FloorMapEditQuickActions.js +8 -1
  26. package/es/components/pisellFloorMapLayout/components/FloorMapOverview.js +16 -8
  27. package/es/components/pisellFloorMapLayout/components/FloorMapOverview.less +69 -17
  28. package/es/components/pisellFloorMapLayout/components/FloorMapToolbar.js +290 -147
  29. package/es/components/pisellFloorMapLayout/components/FloorMapToolbar.less +210 -11
  30. package/es/components/pisellFloorMapLayout/components/FloorMapToolbarViewAllModal.js +81 -0
  31. package/es/components/pisellFloorMapLayout/components/FloorMapZoneElement.d.ts +8 -0
  32. package/es/components/pisellFloorMapLayout/components/FloorMapZoneElement.js +21 -0
  33. package/es/components/pisellFloorMapLayout/components/FloorMapZoneElement.less +74 -0
  34. package/es/components/pisellFloorMapLayout/components/ItemLayer.less +3 -1
  35. package/es/components/pisellFloorMapLayout/components/NodePortMarkers.js +70 -0
  36. package/es/components/pisellFloorMapLayout/components/NodePortMarkers.less +33 -0
  37. package/es/components/pisellFloorMapLayout/components/ViewControls.js +13 -5
  38. package/es/components/pisellFloorMapLayout/components/ViewControlsWithZoom.js +2 -0
  39. package/es/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.js +2 -1
  40. package/es/components/pisellFloorMapLayout/floorMapLayoutConstants.js +1 -1
  41. package/es/components/pisellFloorMapLayout/hooks/useFloorMapEdgeEditing.js +340 -0
  42. package/es/components/pisellFloorMapLayout/hooks/useFloorMapEdgeViewModel.js +102 -0
  43. package/es/components/pisellFloorMapLayout/hooks/useFloorMapEditState.js +244 -84
  44. package/es/components/pisellFloorMapLayout/hooks/useFloorMapTransformMetrics.js +54 -0
  45. package/es/components/pisellFloorMapLayout/hooks/useShopFloorPlanSubscription.js +7 -4
  46. package/es/components/pisellFloorMapLayout/index.d.ts +5 -1
  47. package/es/components/pisellFloorMapLayout/locales-ja.js +14 -2
  48. package/es/components/pisellFloorMapLayout/locales-pt.js +14 -2
  49. package/es/components/pisellFloorMapLayout/locales.js +161 -8
  50. package/es/components/pisellFloorMapLayout/types.d.ts +86 -4
  51. package/es/components/pisellFloorMapLayout/types.js +5 -1
  52. package/es/components/pisellFloorMapLayout/utils/alignSnap.js +170 -0
  53. package/es/components/pisellFloorMapLayout/utils/batchScenePlacementLayout.js +86 -0
  54. package/es/components/pisellFloorMapLayout/utils/edgeRouting.js +942 -0
  55. package/es/components/pisellFloorMapLayout/utils/floorMapCanvasDisplay.d.ts +7 -0
  56. package/es/components/pisellFloorMapLayout/utils/floorMapCanvasStage.js +23 -1
  57. package/es/components/pisellFloorMapLayout/utils/floorMapConfigMerge.js +11 -2
  58. package/es/components/pisellFloorMapLayout/utils/floorMapElementKindUtils.js +20 -3
  59. package/es/components/pisellFloorMapLayout/utils/floorMapFallbackRender.js +11 -5
  60. package/es/components/pisellFloorMapLayout/utils/floorMapOverviewLayout.js +5 -3
  61. package/es/components/pisellFloorMapLayout/utils/floorMapResourcePickerDisplay.d.ts +20 -0
  62. package/es/components/pisellFloorMapLayout/utils/floorMapResourcePickerDisplay.js +62 -0
  63. package/es/components/pisellFloorMapLayout/utils/floorMapResourcePickerTypes.d.ts +83 -0
  64. package/es/components/pisellFloorMapLayout/utils/floorMapResourcePickerTypes.js +29 -0
  65. package/es/components/pisellFloorMapLayout/utils/floorMapToolbarPalette.js +51 -0
  66. package/es/components/productCard/cartSkuCard/components/BookingItem/index.js +14 -0
  67. package/es/components/productCard/cartSkuCard/components/BookingItem/index.less +32 -0
  68. package/es/components/productCard/cartSkuCard/components/resources/index.less +4 -0
  69. package/es/components/productCard/cartSkuCard/components/timeRange/index.js +1 -2
  70. package/es/components/productCard/cartSkuCard/index.js +17 -11
  71. package/es/components/productCard/lineItem/BookingLineItem.js +17 -6
  72. package/es/components/productCard/lineItem/components/Holders/index.js +51 -0
  73. package/es/components/productCard/lineItem/components/Holders/index.less +39 -0
  74. package/es/components/productCard/lineItem/components/Resources/index.js +45 -0
  75. package/es/components/productCard/lineItem/components/TimeRange/index.js +64 -0
  76. package/es/components/productCard/lineItem/index.js +5 -2
  77. package/es/components/productCard/lineItem/index.less +21 -10
  78. package/es/components/productCard/types.d.ts +1 -0
  79. package/es/index.d.ts +6 -2
  80. package/es/index.js +6 -2
  81. package/es/pisell-materials.tw.css +3 -0
  82. package/lib/components/buttonGroupPreview/index.js +8 -4
  83. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.js +206 -48
  84. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.less +33 -2
  85. package/lib/components/pisellFloorMapLayout/appearance/floorMapAppearance.js +50 -2
  86. package/lib/components/pisellFloorMapLayout/components/EdgeLayer.js +255 -0
  87. package/lib/components/pisellFloorMapLayout/components/EdgeLayer.less +11 -0
  88. package/lib/components/pisellFloorMapLayout/components/EditableItemLayer.js +179 -29
  89. package/lib/components/pisellFloorMapLayout/components/EditableItemLayer.less +0 -28
  90. package/lib/components/pisellFloorMapLayout/components/FloorMapEdgeEditPanel.js +134 -0
  91. package/lib/components/pisellFloorMapLayout/components/FloorMapEdgeEditPanel.less +65 -0
  92. package/lib/components/pisellFloorMapLayout/components/FloorMapEditPanel.js +4 -3
  93. package/lib/components/pisellFloorMapLayout/components/FloorMapEditPanel.less +12 -1
  94. package/lib/components/pisellFloorMapLayout/components/FloorMapEditQuickActions.js +8 -1
  95. package/lib/components/pisellFloorMapLayout/components/FloorMapOverview.js +16 -8
  96. package/lib/components/pisellFloorMapLayout/components/FloorMapOverview.less +69 -17
  97. package/lib/components/pisellFloorMapLayout/components/FloorMapToolbar.js +287 -144
  98. package/lib/components/pisellFloorMapLayout/components/FloorMapToolbar.less +210 -11
  99. package/lib/components/pisellFloorMapLayout/components/FloorMapToolbarViewAllModal.js +84 -0
  100. package/lib/components/pisellFloorMapLayout/components/FloorMapZoneElement.d.ts +8 -0
  101. package/lib/components/pisellFloorMapLayout/components/FloorMapZoneElement.js +23 -0
  102. package/lib/components/pisellFloorMapLayout/components/FloorMapZoneElement.less +74 -0
  103. package/lib/components/pisellFloorMapLayout/components/ItemLayer.less +3 -1
  104. package/lib/components/pisellFloorMapLayout/components/NodePortMarkers.js +73 -0
  105. package/lib/components/pisellFloorMapLayout/components/NodePortMarkers.less +33 -0
  106. package/lib/components/pisellFloorMapLayout/components/ViewControls.js +12 -4
  107. package/lib/components/pisellFloorMapLayout/components/ViewControlsWithZoom.js +2 -0
  108. package/lib/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.js +2 -1
  109. package/lib/components/pisellFloorMapLayout/floorMapLayoutConstants.js +1 -1
  110. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapEdgeEditing.js +341 -0
  111. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapEdgeViewModel.js +103 -0
  112. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapEditState.js +242 -82
  113. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapTransformMetrics.js +54 -0
  114. package/lib/components/pisellFloorMapLayout/hooks/useShopFloorPlanSubscription.js +7 -4
  115. package/lib/components/pisellFloorMapLayout/index.d.ts +5 -1
  116. package/lib/components/pisellFloorMapLayout/locales-ja.js +14 -2
  117. package/lib/components/pisellFloorMapLayout/locales-pt.js +14 -2
  118. package/lib/components/pisellFloorMapLayout/locales.js +161 -8
  119. package/lib/components/pisellFloorMapLayout/types.d.ts +86 -4
  120. package/lib/components/pisellFloorMapLayout/types.js +5 -0
  121. package/lib/components/pisellFloorMapLayout/utils/alignSnap.js +170 -0
  122. package/lib/components/pisellFloorMapLayout/utils/batchScenePlacementLayout.js +87 -0
  123. package/lib/components/pisellFloorMapLayout/utils/edgeRouting.js +956 -0
  124. package/lib/components/pisellFloorMapLayout/utils/floorMapCanvasDisplay.d.ts +7 -0
  125. package/lib/components/pisellFloorMapLayout/utils/floorMapCanvasStage.js +23 -0
  126. package/lib/components/pisellFloorMapLayout/utils/floorMapConfigMerge.js +11 -2
  127. package/lib/components/pisellFloorMapLayout/utils/floorMapElementKindUtils.js +21 -2
  128. package/lib/components/pisellFloorMapLayout/utils/floorMapFallbackRender.js +11 -5
  129. package/lib/components/pisellFloorMapLayout/utils/floorMapOverviewLayout.js +5 -3
  130. package/lib/components/pisellFloorMapLayout/utils/floorMapResourcePickerDisplay.d.ts +20 -0
  131. package/lib/components/pisellFloorMapLayout/utils/floorMapResourcePickerDisplay.js +64 -0
  132. package/lib/components/pisellFloorMapLayout/utils/floorMapResourcePickerTypes.d.ts +83 -0
  133. package/lib/components/pisellFloorMapLayout/utils/floorMapResourcePickerTypes.js +29 -0
  134. package/lib/components/pisellFloorMapLayout/utils/floorMapToolbarPalette.js +54 -0
  135. package/lib/components/productCard/cartSkuCard/components/BookingItem/index.js +17 -0
  136. package/lib/components/productCard/cartSkuCard/components/BookingItem/index.less +32 -0
  137. package/lib/components/productCard/cartSkuCard/components/resources/index.less +4 -0
  138. package/lib/components/productCard/cartSkuCard/components/timeRange/index.js +1 -2
  139. package/lib/components/productCard/cartSkuCard/index.js +17 -11
  140. package/lib/components/productCard/lineItem/BookingLineItem.js +17 -6
  141. package/lib/components/productCard/lineItem/components/Holders/index.js +53 -0
  142. package/lib/components/productCard/lineItem/components/Holders/index.less +39 -0
  143. package/lib/components/productCard/lineItem/components/Resources/index.js +47 -0
  144. package/lib/components/productCard/lineItem/components/TimeRange/index.js +67 -0
  145. package/lib/components/productCard/lineItem/index.js +5 -2
  146. package/lib/components/productCard/lineItem/index.less +21 -10
  147. package/lib/components/productCard/types.d.ts +1 -0
  148. package/lib/index.d.ts +6 -2
  149. package/lib/index.js +11 -0
  150. package/lib/pisell-materials.tw.css +3 -0
  151. package/package.json +6 -3
@@ -0,0 +1,341 @@
1
+ require("../../../_virtual/_rolldown/runtime.js");
2
+ const require_objectSpread2 = require("../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js");
3
+ const require_edgeRouting = require("../utils/edgeRouting.js");
4
+ const require_useFloorMapEdgeViewModel = require("./useFloorMapEdgeViewModel.js");
5
+ let react = require("react");
6
+ //#region src/components/pisellFloorMapLayout/hooks/useFloorMapEdgeEditing.ts
7
+ /**
8
+ * 平面图编辑态:连线选中、拉线、草稿 edges 更新
9
+ */
10
+ function newEdgeId() {
11
+ return `edge_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
12
+ }
13
+ function useFloorMapEdgeEditing(params) {
14
+ var _config$edges, _rectsById$get;
15
+ const { enabled, config, items, mergedItems, cellSize, itemUnit, itemGap, contentOffsetRef, selectedId, setSelectedId, commitDraft, mapContentRef, scale = 1 } = params;
16
+ const [selectedEdgeId, setSelectedEdgeId] = (0, react.useState)(null);
17
+ const [drawing, setDrawing] = (0, react.useState)(null);
18
+ const [ghostEnd, setGhostEnd] = (0, react.useState)(null);
19
+ /** 拉线时当前悬停的目标图元与吸附端口 */
20
+ const [drawingTarget, setDrawingTarget] = (0, react.useState)(null);
21
+ const [pendingRectsById, setPendingRectsById] = (0, react.useState)({});
22
+ /** 拖动中段手柄时的临时 routing 覆盖(pointerup 后写入 edge.routing) */
23
+ const [pendingRoutingByEdge, setPendingRoutingByEdge] = (0, react.useState)({});
24
+ const edges = (_config$edges = config === null || config === void 0 ? void 0 : config.edges) !== null && _config$edges !== void 0 ? _config$edges : [];
25
+ const { routes, rectsById } = require_useFloorMapEdgeViewModel.useFloorMapEdgeViewModel({
26
+ edges,
27
+ items,
28
+ cellSize,
29
+ itemUnit,
30
+ itemGap,
31
+ pendingRectsById,
32
+ pendingRoutingByEdge
33
+ });
34
+ const clearEdgeSelection = (0, react.useCallback)(() => {
35
+ setSelectedEdgeId(null);
36
+ }, []);
37
+ const selectEdge = (0, react.useCallback)((edgeId) => {
38
+ if (drawing) return;
39
+ setSelectedEdgeId(edgeId);
40
+ if (edgeId) setSelectedId(null);
41
+ }, [drawing, setSelectedId]);
42
+ const selectNode = (0, react.useCallback)((id) => {
43
+ if (drawing) return;
44
+ setSelectedId(id);
45
+ if (id) setSelectedEdgeId(null);
46
+ }, [drawing, setSelectedId]);
47
+ const clientToContent = (0, react.useCallback)((clientX, clientY) => {
48
+ const el = mapContentRef.current;
49
+ if (!el) return null;
50
+ const rect = el.getBoundingClientRect();
51
+ const off = contentOffsetRef.current;
52
+ return {
53
+ x: (clientX - rect.left) / scale - off.x,
54
+ y: (clientY - rect.top) / scale - off.y
55
+ };
56
+ }, [
57
+ mapContentRef,
58
+ contentOffsetRef,
59
+ scale
60
+ ]);
61
+ const ghostPathD = (0, react.useMemo)(() => {
62
+ var _drawingTarget$anchor;
63
+ if (!drawing || !ghostEnd) return null;
64
+ const srcRect = rectsById.get(drawing.fromInstanceId);
65
+ if (!srcRect) return null;
66
+ const sourcePt = require_edgeRouting.getAnchorPoint(srcRect, drawing.fromAnchor);
67
+ const tgtRect = drawingTarget ? rectsById.get(drawingTarget.instanceId) : null;
68
+ const targetSide = (_drawingTarget$anchor = drawingTarget === null || drawingTarget === void 0 ? void 0 : drawingTarget.anchor) !== null && _drawingTarget$anchor !== void 0 ? _drawingTarget$anchor : "left";
69
+ const targetPt = tgtRect ? require_edgeRouting.getAnchorPoint(tgtRect, targetSide) : ghostEnd;
70
+ return require_edgeRouting.pathFromPoints(require_edgeRouting.routeOrthogonal(sourcePt, drawing.fromAnchor, targetPt, targetSide, void 0, srcRect && tgtRect ? {
71
+ sourceRect: srcRect,
72
+ targetRect: tgtRect
73
+ } : void 0));
74
+ }, [
75
+ drawing,
76
+ ghostEnd,
77
+ drawingTarget,
78
+ rectsById
79
+ ]);
80
+ const drawingTargetPreview = (0, react.useMemo)(() => {
81
+ if (!drawing || !drawingTarget) return null;
82
+ const rect = rectsById.get(drawingTarget.instanceId);
83
+ if (!rect) return null;
84
+ return {
85
+ instanceId: drawingTarget.instanceId,
86
+ rect,
87
+ anchor: drawingTarget.anchor
88
+ };
89
+ }, [
90
+ drawing,
91
+ drawingTarget,
92
+ rectsById
93
+ ]);
94
+ const startDrawingFromAnchor = (0, react.useCallback)((instanceId, anchor) => {
95
+ setDrawing({
96
+ fromInstanceId: instanceId,
97
+ fromAnchor: anchor
98
+ });
99
+ setDrawingTarget(null);
100
+ setGhostEnd(null);
101
+ setSelectedEdgeId(null);
102
+ setSelectedId(instanceId);
103
+ }, [setSelectedId]);
104
+ const finishDrawing = (0, react.useCallback)((clientX, clientY) => {
105
+ var _resolved$instanceId;
106
+ if (!drawing || !config) {
107
+ setDrawing(null);
108
+ setGhostEnd(null);
109
+ setDrawingTarget(null);
110
+ return;
111
+ }
112
+ const pt = clientToContent(clientX, clientY);
113
+ if (!pt) {
114
+ setDrawing(null);
115
+ setGhostEnd(null);
116
+ setDrawingTarget(null);
117
+ return;
118
+ }
119
+ const resolved = drawingTarget !== null && drawingTarget !== void 0 ? drawingTarget : require_edgeRouting.resolveDrawingTargetAtPoint(pt, mergedItems.map((m) => m.id), rectsById, drawing.fromInstanceId);
120
+ const targetId = (_resolved$instanceId = resolved === null || resolved === void 0 ? void 0 : resolved.instanceId) !== null && _resolved$instanceId !== void 0 ? _resolved$instanceId : null;
121
+ const targetAnchor = resolved === null || resolved === void 0 ? void 0 : resolved.anchor;
122
+ if (targetId && targetId !== drawing.fromInstanceId) {
123
+ const edge = {
124
+ id: newEdgeId(),
125
+ sourceId: drawing.fromInstanceId,
126
+ targetId,
127
+ sourceAnchor: drawing.fromAnchor,
128
+ targetAnchor,
129
+ status: "online"
130
+ };
131
+ commitDraft((prev) => {
132
+ var _prev$edges;
133
+ return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { edges: [...(_prev$edges = prev.edges) !== null && _prev$edges !== void 0 ? _prev$edges : [], edge] });
134
+ });
135
+ setSelectedEdgeId(edge.id);
136
+ setSelectedId(null);
137
+ }
138
+ setDrawing(null);
139
+ setGhostEnd(null);
140
+ setDrawingTarget(null);
141
+ }, [
142
+ drawing,
143
+ drawingTarget,
144
+ config,
145
+ clientToContent,
146
+ mergedItems,
147
+ rectsById,
148
+ commitDraft,
149
+ setSelectedId
150
+ ]);
151
+ (0, react.useEffect)(() => {
152
+ if (!drawing) return;
153
+ const onMove = (ev) => {
154
+ const pt = clientToContent(ev.clientX, ev.clientY);
155
+ if (!pt) return;
156
+ const hit = require_edgeRouting.resolveDrawingTargetAtPoint(pt, mergedItems.map((m) => m.id), rectsById, drawing.fromInstanceId);
157
+ setDrawingTarget(hit);
158
+ if (hit) {
159
+ const rect = rectsById.get(hit.instanceId);
160
+ if (rect) {
161
+ setGhostEnd(require_edgeRouting.getAnchorPoint(rect, hit.anchor));
162
+ return;
163
+ }
164
+ }
165
+ setGhostEnd(pt);
166
+ };
167
+ const onUp = (ev) => {
168
+ finishDrawing(ev.clientX, ev.clientY);
169
+ };
170
+ window.addEventListener("pointermove", onMove);
171
+ window.addEventListener("pointerup", onUp);
172
+ return () => {
173
+ window.removeEventListener("pointermove", onMove);
174
+ window.removeEventListener("pointerup", onUp);
175
+ };
176
+ }, [
177
+ drawing,
178
+ clientToContent,
179
+ finishDrawing,
180
+ mergedItems,
181
+ rectsById
182
+ ]);
183
+ const updateEdge = (0, react.useCallback)((edgeId, patch) => {
184
+ commitDraft((prev) => {
185
+ var _prev$edges2;
186
+ return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { edges: ((_prev$edges2 = prev.edges) !== null && _prev$edges2 !== void 0 ? _prev$edges2 : []).map((e) => e.id === edgeId ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, e), patch) : e) });
187
+ });
188
+ }, [commitDraft]);
189
+ /**
190
+ * 拖动连线段手柄:所有拖动都直接对「path snapshot」做形变。
191
+ * - `role='inner'`:把指定 segmentIndex 的主轴坐标平移到鼠标位置。
192
+ * - `role='first'`:在 snapshot 前面插入一对新点(短 stub + 新被拖动段),
193
+ * 随后拖动改新被拖动段的主轴。即「拖首段 = 新增一个角」,可以无限叠加。
194
+ * - `role='last'`:对称地在末尾追加一对新点。
195
+ * 释放后把「working snapshot」一次性写入 edge.routing.pathSnapshot。
196
+ */
197
+ const draggingSegmentRef = (0, react.useRef)(null);
198
+ const startDraggingSegment = (0, react.useCallback)((params) => {
199
+ const edge = edges.find((e) => e.id === params.edgeId);
200
+ if (!edge) return;
201
+ const currentRoute = routes.find((r) => r.edgeId === params.edgeId);
202
+ if (!currentRoute) return;
203
+ /** 始终用「当前 view-model 渲染的 path」(已对齐到最新图元锚点)作为 working 起点。
204
+ * 再做一次共线化简,确保 applySourceStub/Target 不会被冗余共线点干扰
205
+ * (否则插入 stub 后改 y/x,后续共线点未跟随会出斜段)。 */
206
+ const baseSnapshot = require_edgeRouting.simplifyCollinearPath(currentRoute.points);
207
+ let workingSnapshot = baseSnapshot;
208
+ let targetSegIndex;
209
+ if (params.role === "first") {
210
+ var _edge$sourceAnchor, _params$segmentLength;
211
+ const srcRect = rectsById.get(edge.sourceId);
212
+ const tgtRect = rectsById.get(edge.targetId);
213
+ const sourceAnchor = (_edge$sourceAnchor = edge.sourceAnchor) !== null && _edge$sourceAnchor !== void 0 ? _edge$sourceAnchor : srcRect && tgtRect ? require_edgeRouting.pickAutoAnchor(srcRect, tgtRect) : "right";
214
+ const segLen = (_params$segmentLength = params.segmentLength) !== null && _params$segmentLength !== void 0 ? _params$segmentLength : 48;
215
+ workingSnapshot = require_edgeRouting.applySourceStub(baseSnapshot, Math.min(24, segLen / 2), sourceAnchor);
216
+ /** stub 后被拖动段 = path 的 segment 2(即 snapshot[2]→snapshot[3]) */
217
+ targetSegIndex = 2;
218
+ } else if (params.role === "last") {
219
+ var _edge$targetAnchor, _params$segmentLength2;
220
+ const srcRect = rectsById.get(edge.sourceId);
221
+ const tgtRect = rectsById.get(edge.targetId);
222
+ const targetAnchor = (_edge$targetAnchor = edge.targetAnchor) !== null && _edge$targetAnchor !== void 0 ? _edge$targetAnchor : srcRect && tgtRect ? require_edgeRouting.pickAutoAnchor(tgtRect, srcRect) : "left";
223
+ const segLen = (_params$segmentLength2 = params.segmentLength) !== null && _params$segmentLength2 !== void 0 ? _params$segmentLength2 : 48;
224
+ workingSnapshot = require_edgeRouting.applyTargetStub(baseSnapshot, Math.min(24, segLen / 2), targetAnchor);
225
+ /** stub 后被拖动段 = path 的 segment (n-3)(即 snapshot[n-4]→snapshot[n-3]) */
226
+ targetSegIndex = workingSnapshot.length - 4;
227
+ } else targetSegIndex = params.segmentIndex;
228
+ draggingSegmentRef.current = {
229
+ edgeId: params.edgeId,
230
+ workingSnapshot,
231
+ targetSegIndex,
232
+ axis: params.axis,
233
+ startClientX: params.clientX,
234
+ startClientY: params.clientY,
235
+ startPosition: params.startPosition
236
+ };
237
+ setPendingRoutingByEdge((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [params.edgeId]: { pathSnapshot: workingSnapshot } }));
238
+ setSelectedEdgeId(params.edgeId);
239
+ }, [
240
+ edges,
241
+ routes,
242
+ rectsById
243
+ ]);
244
+ (0, react.useEffect)(() => {
245
+ const onMove = (ev) => {
246
+ const drag = draggingSegmentRef.current;
247
+ if (!drag) return;
248
+ const dx = (ev.clientX - drag.startClientX) / scale;
249
+ const dy = (ev.clientY - drag.startClientY) / scale;
250
+ const delta = drag.axis === "h" ? dy : dx;
251
+ const nextPos = drag.startPosition + delta;
252
+ const snap = drag.workingSnapshot.map((p) => [p[0], p[1]]);
253
+ const i = drag.targetSegIndex;
254
+ if (i < 0 || i + 1 >= snap.length) return;
255
+ if (drag.axis === "h") {
256
+ snap[i] = [snap[i][0], nextPos];
257
+ snap[i + 1] = [snap[i + 1][0], nextPos];
258
+ } else {
259
+ snap[i] = [nextPos, snap[i][1]];
260
+ snap[i + 1] = [nextPos, snap[i + 1][1]];
261
+ }
262
+ setPendingRoutingByEdge((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [drag.edgeId]: { pathSnapshot: snap } }));
263
+ };
264
+ const onUp = () => {
265
+ const drag = draggingSegmentRef.current;
266
+ draggingSegmentRef.current = null;
267
+ if (!drag) return;
268
+ setPendingRoutingByEdge((prev) => {
269
+ const next = require_objectSpread2._objectSpread2({}, prev);
270
+ const finalRouting = next[drag.edgeId];
271
+ delete next[drag.edgeId];
272
+ if (finalRouting) updateEdge(drag.edgeId, { routing: finalRouting });
273
+ return next;
274
+ });
275
+ };
276
+ window.addEventListener("pointermove", onMove);
277
+ window.addEventListener("pointerup", onUp);
278
+ return () => {
279
+ window.removeEventListener("pointermove", onMove);
280
+ window.removeEventListener("pointerup", onUp);
281
+ };
282
+ }, [scale, updateEdge]);
283
+ const deleteEdge = (0, react.useCallback)((edgeId) => {
284
+ commitDraft((prev) => {
285
+ var _prev$edges3;
286
+ return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { edges: ((_prev$edges3 = prev.edges) !== null && _prev$edges3 !== void 0 ? _prev$edges3 : []).filter((e) => e.id !== edgeId) });
287
+ });
288
+ setSelectedEdgeId((id) => id === edgeId ? null : id);
289
+ }, [commitDraft]);
290
+ const handleEdgeClick = (0, react.useCallback)((edgeId) => {
291
+ selectEdge(edgeId);
292
+ }, [selectEdge]);
293
+ const handleMapBackgroundClick = (0, react.useCallback)(() => {
294
+ if (drawing) return;
295
+ setSelectedEdgeId(null);
296
+ setSelectedId(null);
297
+ }, [drawing, setSelectedId]);
298
+ (0, react.useEffect)(() => {
299
+ if (!enabled) return;
300
+ const onKey = (ev) => {
301
+ if (ev.key !== "Delete" && ev.key !== "Backspace") return;
302
+ if (!selectedEdgeId) return;
303
+ const t = ev.target;
304
+ if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;
305
+ ev.preventDefault();
306
+ deleteEdge(selectedEdgeId);
307
+ };
308
+ window.addEventListener("keydown", onKey);
309
+ return () => window.removeEventListener("keydown", onKey);
310
+ }, [
311
+ enabled,
312
+ selectedEdgeId,
313
+ deleteEdge
314
+ ]);
315
+ return {
316
+ edges,
317
+ routes,
318
+ rectsById,
319
+ selectedEdgeId,
320
+ selectedEdge: (0, react.useMemo)(() => {
321
+ var _edges$find;
322
+ return (_edges$find = edges.find((e) => e.id === selectedEdgeId)) !== null && _edges$find !== void 0 ? _edges$find : null;
323
+ }, [edges, selectedEdgeId]),
324
+ selectedNodeRect: selectedId ? (_rectsById$get = rectsById.get(selectedId)) !== null && _rectsById$get !== void 0 ? _rectsById$get : null : null,
325
+ drawing,
326
+ drawingTargetPreview,
327
+ ghostPathD,
328
+ selectNode,
329
+ selectEdge,
330
+ clearEdgeSelection,
331
+ startDrawingFromAnchor,
332
+ handleEdgeClick,
333
+ handleMapBackgroundClick,
334
+ updateEdge,
335
+ deleteEdge,
336
+ setPendingRectsById,
337
+ startDraggingSegment
338
+ };
339
+ }
340
+ //#endregion
341
+ exports.useFloorMapEdgeEditing = useFloorMapEdgeEditing;
@@ -0,0 +1,103 @@
1
+ require("../../../_virtual/_rolldown/runtime.js");
2
+ const require_edgeRouting = require("../utils/edgeRouting.js");
3
+ let react = require("react");
4
+ //#region src/components/pisellFloorMapLayout/hooks/useFloorMapEdgeViewModel.ts
5
+ /**
6
+ * 根据 edges + 图元矩形计算连线路由
7
+ */
8
+ function extractRouteSegments(points) {
9
+ const segs = [];
10
+ for (let i = 0; i < points.length - 1; i++) {
11
+ const [x1, y1] = points[i];
12
+ const [x2, y2] = points[i + 1];
13
+ if (y1 === y2 && x1 !== x2) segs.push({
14
+ orientation: "h",
15
+ key: y1,
16
+ a: Math.min(x1, x2),
17
+ b: Math.max(x1, x2)
18
+ });
19
+ else if (x1 === x2 && y1 !== y2) segs.push({
20
+ orientation: "v",
21
+ key: x1,
22
+ a: Math.min(y1, y2),
23
+ b: Math.max(y1, y2)
24
+ });
25
+ }
26
+ return segs;
27
+ }
28
+ function segmentsOverlap(a, b) {
29
+ if (a.orientation !== b.orientation) return false;
30
+ if (a.key !== b.key) return false;
31
+ return Math.max(a.a, b.a) < Math.min(a.b, b.b);
32
+ }
33
+ function routesShareChannel(a, b) {
34
+ const segsA = extractRouteSegments(a);
35
+ const segsB = extractRouteSegments(b);
36
+ for (const sa of segsA) for (const sb of segsB) if (segmentsOverlap(sa, sb)) return true;
37
+ return false;
38
+ }
39
+ /** 同一目标的多条边在末段竖线处必然共线,需主动分配通道错位 */
40
+ function edgesShareTarget(a, b) {
41
+ return a.targetId === b.targetId || a.sourceId === b.sourceId;
42
+ }
43
+ function useFloorMapEdgeViewModel(params) {
44
+ const { edges = [], items, cellSize, itemUnit, itemGap, pendingRectsById, pendingRoutingByEdge } = params;
45
+ return (0, react.useMemo)(() => {
46
+ const rectsById = /* @__PURE__ */ new Map();
47
+ for (const item of items) rectsById.set(item.id, require_edgeRouting.getItemPixelRect(item, {
48
+ cellSize,
49
+ itemUnit,
50
+ itemGap,
51
+ override: pendingRectsById === null || pendingRectsById === void 0 ? void 0 : pendingRectsById[item.id]
52
+ }));
53
+ /** Pass 1:所有 edge 用默认通道(offset = 0)计算一次 */
54
+ const naive = edges.map((edge) => ({
55
+ edge,
56
+ route: require_edgeRouting.buildEdgeRoute(edge, rectsById, { routingOverride: pendingRoutingByEdge === null || pendingRoutingByEdge === void 0 ? void 0 : pendingRoutingByEdge[edge.id] })
57
+ }));
58
+ /**
59
+ * Pass 2:对共享通道的 edges 分配错位 offset。
60
+ * 用 union-find 风格:按 edges 出现顺序遍历,与已选 routes 比对,若冲突则用下一个 offset。
61
+ */
62
+ const routes = [];
63
+ const accepted = [];
64
+ const acceptedEdges = [];
65
+ for (let i = 0; i < naive.length; i++) {
66
+ const { edge, route } = naive[i];
67
+ if (!route) continue;
68
+ let chosen = route;
69
+ let attempt = 0;
70
+ const maxAttempts = 10;
71
+ while (attempt < maxAttempts) {
72
+ if (!accepted.some((r, idx) => {
73
+ const other = acceptedEdges[idx];
74
+ return routesShareChannel(chosen.points, r.points) || other != null && edgesShareTarget(edge, other);
75
+ })) break;
76
+ attempt += 1;
77
+ const re = require_edgeRouting.buildEdgeRoute(edge, rectsById, {
78
+ channelOffset: require_edgeRouting.getEdgeChannelOffset(attempt),
79
+ routingOverride: pendingRoutingByEdge === null || pendingRoutingByEdge === void 0 ? void 0 : pendingRoutingByEdge[edge.id]
80
+ });
81
+ if (!re) break;
82
+ chosen = re;
83
+ }
84
+ accepted.push(chosen);
85
+ acceptedEdges.push(edge);
86
+ routes.push(chosen);
87
+ }
88
+ return {
89
+ routes,
90
+ rectsById
91
+ };
92
+ }, [
93
+ edges,
94
+ items,
95
+ cellSize,
96
+ itemUnit,
97
+ itemGap,
98
+ pendingRectsById,
99
+ pendingRoutingByEdge
100
+ ]);
101
+ }
102
+ //#endregion
103
+ exports.useFloorMapEdgeViewModel = useFloorMapEdgeViewModel;