@rxflow/base 0.0.3 → 0.0.4-alpha.1

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 (131) hide show
  1. package/cjs/Flow.d.ts +1 -1
  2. package/cjs/Flow.d.ts.map +1 -1
  3. package/cjs/Flow.js +28 -10
  4. package/cjs/components/Legend/index.d.ts.map +1 -1
  5. package/cjs/components/Legend/index.js +2 -1
  6. package/cjs/components/Popover/index.d.ts +1 -9
  7. package/cjs/components/Popover/index.d.ts.map +1 -1
  8. package/cjs/components/Popover/index.js +14 -75
  9. package/cjs/components/Tooltip/index.d.ts +1 -10
  10. package/cjs/components/Tooltip/index.d.ts.map +1 -1
  11. package/cjs/components/Tooltip/index.js +11 -83
  12. package/cjs/edges/manhattan.d.ts.map +1 -1
  13. package/cjs/edges/manhattan.js +100 -30
  14. package/cjs/hoc/createFlow.d.ts +30 -4
  15. package/cjs/hoc/createFlow.d.ts.map +1 -1
  16. package/cjs/hoc/createFlow.js +45 -18
  17. package/cjs/hooks/index.d.ts +5 -2
  18. package/cjs/hooks/index.d.ts.map +1 -1
  19. package/cjs/hooks/index.js +44 -22
  20. package/cjs/hooks/props/index.d.ts +12 -0
  21. package/cjs/hooks/props/index.d.ts.map +1 -0
  22. package/cjs/hooks/props/index.js +49 -0
  23. package/cjs/hooks/props/useFlowProps.d.ts +23 -0
  24. package/cjs/hooks/props/useFlowProps.d.ts.map +1 -0
  25. package/cjs/hooks/props/useFlowProps.js +34 -0
  26. package/cjs/hooks/props/useGetFlowProps.d.ts +19 -0
  27. package/cjs/hooks/props/useGetFlowProps.d.ts.map +1 -0
  28. package/cjs/hooks/props/useGetFlowProps.js +38 -0
  29. package/cjs/hooks/props/useGetInputProps.d.ts +18 -0
  30. package/cjs/hooks/props/useGetInputProps.d.ts.map +1 -0
  31. package/cjs/hooks/props/useGetInputProps.js +38 -0
  32. package/cjs/hooks/props/useInputProps.d.ts +14 -0
  33. package/cjs/hooks/props/useInputProps.d.ts.map +1 -0
  34. package/cjs/hooks/props/useInputProps.js +33 -0
  35. package/cjs/hooks/useListenRender.js +4 -4
  36. package/cjs/hooks/useTheme.d.ts.map +1 -1
  37. package/cjs/hooks/useTheme.js +3 -2
  38. package/cjs/index.d.ts +6 -3
  39. package/cjs/index.d.ts.map +1 -1
  40. package/cjs/index.js +46 -14
  41. package/cjs/providers/FlowProvider.d.ts +7 -1
  42. package/cjs/providers/FlowProvider.d.ts.map +1 -1
  43. package/cjs/providers/FlowProvider.js +33 -14
  44. package/cjs/store/PropsStore.d.ts +11 -6
  45. package/cjs/store/PropsStore.d.ts.map +1 -1
  46. package/cjs/store/PropsStore.js +55 -39
  47. package/cjs/types/props.d.ts +83 -0
  48. package/cjs/types/props.d.ts.map +1 -0
  49. package/cjs/types/props.js +5 -0
  50. package/cjs/types.d.ts +5 -1
  51. package/cjs/types.d.ts.map +1 -1
  52. package/cjs/utils/wrapNodeTypes.d.ts +30 -0
  53. package/cjs/utils/wrapNodeTypes.d.ts.map +1 -0
  54. package/cjs/utils/wrapNodeTypes.js +56 -0
  55. package/cjs/workers/manhattan.worker.js +12534 -31
  56. package/cjs/workers/manhattan.worker.js.map +7 -0
  57. package/esm/Flow.d.ts +1 -1
  58. package/esm/Flow.d.ts.map +1 -1
  59. package/esm/Flow.js +30 -16
  60. package/esm/components/Legend/index.d.ts.map +1 -1
  61. package/esm/components/Legend/index.js +3 -2
  62. package/esm/components/Popover/index.d.ts +1 -9
  63. package/esm/components/Popover/index.d.ts.map +1 -1
  64. package/esm/components/Popover/index.js +16 -87
  65. package/esm/components/Tooltip/index.d.ts +1 -10
  66. package/esm/components/Tooltip/index.d.ts.map +1 -1
  67. package/esm/components/Tooltip/index.js +14 -97
  68. package/esm/edges/manhattan.d.ts.map +1 -1
  69. package/esm/edges/manhattan.js +95 -23
  70. package/esm/hoc/createFlow.d.ts +30 -4
  71. package/esm/hoc/createFlow.d.ts.map +1 -1
  72. package/esm/hoc/createFlow.js +48 -20
  73. package/esm/hooks/index.d.ts +5 -2
  74. package/esm/hooks/index.d.ts.map +1 -1
  75. package/esm/hooks/index.js +8 -3
  76. package/esm/hooks/props/index.d.ts +12 -0
  77. package/esm/hooks/props/index.d.ts.map +1 -0
  78. package/esm/hooks/props/index.js +12 -0
  79. package/esm/hooks/props/useFlowProps.d.ts +23 -0
  80. package/esm/hooks/props/useFlowProps.d.ts.map +1 -0
  81. package/esm/hooks/props/useFlowProps.js +29 -0
  82. package/esm/hooks/props/useGetFlowProps.d.ts +19 -0
  83. package/esm/hooks/props/useGetFlowProps.d.ts.map +1 -0
  84. package/esm/hooks/props/useGetFlowProps.js +31 -0
  85. package/esm/hooks/props/useGetInputProps.d.ts +18 -0
  86. package/esm/hooks/props/useGetInputProps.d.ts.map +1 -0
  87. package/esm/hooks/props/useGetInputProps.js +31 -0
  88. package/esm/hooks/props/useInputProps.d.ts +14 -0
  89. package/esm/hooks/props/useInputProps.d.ts.map +1 -0
  90. package/esm/hooks/props/useInputProps.js +27 -0
  91. package/esm/hooks/useListenRender.js +4 -4
  92. package/esm/hooks/useTheme.d.ts.map +1 -1
  93. package/esm/hooks/useTheme.js +3 -2
  94. package/esm/index.d.ts +6 -3
  95. package/esm/index.d.ts.map +1 -1
  96. package/esm/index.js +22 -3
  97. package/esm/providers/FlowProvider.d.ts +7 -1
  98. package/esm/providers/FlowProvider.d.ts.map +1 -1
  99. package/esm/providers/FlowProvider.js +36 -15
  100. package/esm/store/PropsStore.d.ts +11 -6
  101. package/esm/store/PropsStore.d.ts.map +1 -1
  102. package/esm/store/PropsStore.js +75 -34
  103. package/esm/types/props.d.ts +83 -0
  104. package/esm/types/props.d.ts.map +1 -0
  105. package/esm/types/props.js +1 -0
  106. package/esm/types.d.ts +5 -1
  107. package/esm/types.d.ts.map +1 -1
  108. package/esm/utils/wrapNodeTypes.d.ts +30 -0
  109. package/esm/utils/wrapNodeTypes.d.ts.map +1 -0
  110. package/esm/utils/wrapNodeTypes.js +55 -0
  111. package/esm/workers/manhattan.worker.js +1 -1
  112. package/esm/workers/manhattan.worker.js.map +7 -0
  113. package/package.json +5 -3
  114. package/cjs/hooks/props/useGetProps.d.ts +0 -6
  115. package/cjs/hooks/props/useGetProps.d.ts.map +0 -1
  116. package/cjs/hooks/props/useGetProps.js +0 -29
  117. package/cjs/hooks/props/useProps.d.ts +0 -2
  118. package/cjs/hooks/props/useProps.d.ts.map +0 -1
  119. package/cjs/hooks/props/useProps.js +0 -20
  120. package/cjs/hooks/props/usePropsSelector.d.ts +0 -13
  121. package/cjs/hooks/props/usePropsSelector.d.ts.map +0 -1
  122. package/cjs/hooks/props/usePropsSelector.js +0 -37
  123. package/esm/hooks/props/useGetProps.d.ts +0 -6
  124. package/esm/hooks/props/useGetProps.d.ts.map +0 -1
  125. package/esm/hooks/props/useGetProps.js +0 -21
  126. package/esm/hooks/props/useProps.d.ts +0 -2
  127. package/esm/hooks/props/useProps.d.ts.map +0 -1
  128. package/esm/hooks/props/useProps.js +0 -14
  129. package/esm/hooks/props/usePropsSelector.d.ts +0 -13
  130. package/esm/hooks/props/usePropsSelector.d.ts.map +0 -1
  131. package/esm/hooks/props/usePropsSelector.js +0 -31
package/cjs/Flow.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @author: yanxianliang
3
3
  * @date: 2025-07-27 16:33
4
- * @modified:2025/7/27 16:33 by yanxianliang
4
+ * @modified:2025/1/17 by yanxianliang
5
5
  * @desc: Flow
6
6
  *
7
7
  * Copyright (c) 2025 by yanxianliang, All Rights Reserved.
package/cjs/Flow.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Flow.d.ts","sourceRoot":"","sources":["Flow.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,8BAA8B,CAAC;AACtC,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAQvC,OAAO,EAGL,IAAI,EAGJ,IAAI,EAOL,MAAM,eAAe,CAAC;AAavB,OAAO,cAAc,CAAC;AAMtB,wBAAgB,IAAI,CAAC,QAAQ,SAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,SAAS,IAAI,GAAG,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,2CAuPzH"}
1
+ {"version":3,"file":"Flow.d.ts","sourceRoot":"","sources":["Flow.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,8BAA8B,CAAC;AACtC,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAQvC,OAAO,EAGL,IAAI,EAGJ,IAAI,EAOL,MAAM,eAAe,CAAC;AAavB,OAAO,cAAc,CAAC;AA0HtB,wBAAgB,IAAI,CAAC,QAAQ,SAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,SAAS,IAAI,GAAG,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,2CAwNzH"}
package/cjs/Flow.js CHANGED
@@ -29,12 +29,26 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
29
29
  /**
30
30
  * @author: yanxianliang
31
31
  * @date: 2025-07-27 16:33
32
- * @modified:2025/7/27 16:33 by yanxianliang
32
+ * @modified:2025/1/17 by yanxianliang
33
33
  * @desc: Flow
34
34
  *
35
35
  * Copyright (c) 2025 by yanxianliang, All Rights Reserved.
36
36
  */
37
37
 
38
+ /**
39
+ * ReactFlow 原生支持的属性列表
40
+ * 这些属性会透传给 ReactFlow
41
+ */const REACT_FLOW_PROPS = [
42
+ // 核心数据
43
+ 'defaultNodes', 'defaultEdges', 'defaultEdgeOptions',
44
+ // 视图控制
45
+ 'fitView', 'fitViewOptions', 'minZoom', 'maxZoom', 'defaultViewport', 'snapToGrid', 'snapGrid', 'onlyRenderVisibleElements',
46
+ // 交互控制
47
+ 'nodesDraggable', 'nodesConnectable', 'nodesFocusable', 'edgesFocusable', 'elementsSelectable', 'selectNodesOnDrag', 'panOnDrag', 'panOnScroll', 'panOnScrollSpeed', 'panOnScrollMode', 'zoomOnScroll', 'zoomOnPinch', 'zoomOnDoubleClick', 'preventScrolling', 'connectionMode', 'connectionLineType', 'connectionLineStyle', 'connectionLineComponent', 'connectionLineContainerStyle', 'connectionRadius', 'isValidConnection', 'nodeDragThreshold', 'autoPanOnConnect', 'autoPanOnNodeDrag', 'autoPanSpeed', 'selectionOnDrag', 'selectionMode', 'selectionKeyCode', 'multiSelectionKeyCode', 'zoomActivationKeyCode', 'panActivationKeyCode', 'deleteKeyCode', 'nodeExtent', 'translateExtent', 'elevateNodesOnSelect', 'elevateEdgesOnSelect', 'disableKeyboardA11y', 'noDragClassName', 'noWheelClassName', 'noPanClassName',
48
+ // 事件回调
49
+ 'onNodeClick', 'onNodeDoubleClick', 'onNodeMouseEnter', 'onNodeMouseMove', 'onNodeMouseLeave', 'onNodeContextMenu', 'onNodeDragStart', 'onNodeDrag', 'onNodeDragStop', 'onNodesDelete', 'onEdgeClick', 'onEdgeDoubleClick', 'onEdgeMouseEnter', 'onEdgeMouseMove', 'onEdgeMouseLeave', 'onEdgeContextMenu', 'onEdgeUpdate', 'onEdgeUpdateStart', 'onEdgeUpdateEnd', 'onEdgesDelete', 'onConnect', 'onConnectStart', 'onConnectEnd', 'onClickConnectStart', 'onClickConnectEnd', 'onMove', 'onMoveStart', 'onMoveEnd', 'onSelectionChange', 'onSelectionDragStart', 'onSelectionDrag', 'onSelectionDragStop', 'onSelectionContextMenu', 'onSelectionStart', 'onSelectionEnd', 'onPaneClick', 'onPaneContextMenu', 'onPaneScroll', 'onPaneMouseEnter', 'onPaneMouseMove', 'onPaneMouseLeave', 'onInit', 'onError', 'onDelete', 'onBeforeDelete',
50
+ // 样式
51
+ 'style', 'className', 'id', 'colorMode'];
38
52
  const proOptions = {
39
53
  hideAttribution: true
40
54
  }; // 默认隐藏水印
@@ -64,8 +78,6 @@ function Flow(props) {
64
78
  edges,
65
79
  layout = _base.baseLayout,
66
80
  autoCenter = false,
67
- omitProps = [],
68
- // 不向下透传的属性
69
81
  forceLayout = !!props.layout,
70
82
  // 是否强制布局,如果强制布局会监控节点的dimension改变事件,自动触发布局计算
71
83
  getMiniMapNodeColor,
@@ -121,8 +133,17 @@ function Flow(props) {
121
133
  flowProps: props
122
134
  });
123
135
  }, [nodes, edges, forceUpdateTimes]);
136
+ const edgeTypes = (0, _react2.useMemo)(() => {
137
+ return {
138
+ manhattan: _manhattan.ManhattanEdge,
139
+ ...(props.edgeTypes || {})
140
+ };
141
+ }, [props.edgeTypes]);
124
142
  const flowProps = (0, _react2.useMemo)(() => {
143
+ // 使用 pick 选择需要透传的属性,而不是 omit 排除
144
+ const passthroughProps = (0, _lodash.pick)(props, REACT_FLOW_PROPS);
125
145
  const options = {
146
+ // 默认配置
126
147
  selectNodesOnDrag: false,
127
148
  preventScrolling: true,
128
149
  panOnScroll: false,
@@ -135,14 +156,10 @@ function Flow(props) {
135
156
  },
136
157
  fitView: true,
137
158
  onlyRenderVisibleElements,
138
- ...(0, _lodash.omit)(props, ['flowInstanceRef', 'width', 'height', 'nodes', 'edges', 'fitViewOptions', 'theme', 'background', 'nodeTypes', 'showControls', 'showMiniMap', 'autoCenter', 'rootStyle', 'layout', 'onNodesChange', 'omitProps', 'forceLayout', 'controlsPosition', 'getMiniMapNodeColor', 'markers', 'onBeforeLayout', 'onLayout', 'onAfterLayout', 'plugins', 'readOnly', 'showFitView', 'showFullscreen', 'showInteractive', 'showZoom', 'showForceLayout', 'onInteractiveChange', 'onZoomOut', 'onZoomIn', 'onFitView', 'customControls', 'controlsOrientation', ...omitProps]),
139
- edgeTypes: {
140
- manhattan: _manhattan.ManhattanEdge,
141
- ...(props.edgeTypes || {})
142
- }
159
+ // 透传 ReactFlow 原生属性
160
+ ...passthroughProps
143
161
  };
144
162
  if (plugins?.scroller) {
145
- // 只读模式也需要
146
163
  options.zoomOnScroll = false;
147
164
  options.panOnScroll = true;
148
165
  options.panOnDrag = options.panOnDrag ?? [1, 2];
@@ -155,7 +172,7 @@ function Flow(props) {
155
172
  options.elementsSelectable = false;
156
173
  }
157
174
  return options;
158
- }, [props, _nodes, readOnly, onlyRenderVisibleElements]);
175
+ }, [props, _nodes, readOnly, onlyRenderVisibleElements, autoCenter, plugins?.scroller]);
159
176
  const onNodesChange = (0, _ahooks.useMemoizedFn)(changes => {
160
177
  if (forceLayout && (0, _hasDimensionsChange.hasDimensionsChange)(changes)) {
161
178
  // 强制布局
@@ -194,6 +211,7 @@ function Flow(props) {
194
211
  }) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_react.ReactFlow, {
195
212
  nodeTypes: nodeTypes,
196
213
  ...flowProps,
214
+ edgeTypes: edgeTypes,
197
215
  nodes: _nodes,
198
216
  edges: _edges,
199
217
  onNodesChange: onNodesChange,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AAWA,OAAO,cAAc,CAAC;AAKtB,OAAO,EAAC,cAAc,EAAkB,MAAM,aAAa,CAAC;AAE5D,eAAO,MAAM,MAAM;gBAIH,cAAc,CAAC,YAAY,CAAC;oDAkD3C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AAYA,OAAO,cAAc,CAAC;AAKtB,OAAO,EAAC,cAAc,EAAkB,MAAM,aAAa,CAAC;AAE5D,eAAO,MAAM,MAAM;gBAIH,cAAc,CAAC,YAAY,CAAC;oDAkD3C,CAAA"}
@@ -15,6 +15,7 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
15
15
  /*
16
16
  * @author: yanxianliang
17
17
  * @date: 2025-06-03 19:33
18
+ * @modified:2025/1/17 by yanxianliang
18
19
  * @desc: 图例标准组件。按照节点类型进行分类展示。
19
20
  *
20
21
  * 遍历当前的nodes 列表,根据类型定义解析出图例列表。
@@ -29,7 +30,7 @@ const Legend = ({
29
30
  const showAll = typeof showLegend === "boolean" ? true : showLegend?.showAll ?? true; // 默认值为 true
30
31
 
31
32
  // 节点定义列表
32
- const nodeTypeList = (0, _hooks.usePropsSelector)(state => state.nodeTypes);
33
+ const nodeTypeList = (0, _hooks.useFlowProps)(state => state.nodeTypes);
33
34
  const legendList = (0, _react2.useMemo)(() => {
34
35
  const showTypeList = [];
35
36
  const nodeTypeSet = new Set();
@@ -1,11 +1,3 @@
1
1
  import { PopoverProps } from "antd/es/popover";
2
- import React from "react";
3
- export declare function Popover(props: PopoverProps & {
4
- children: React.ReactElement<{
5
- onMouseEnter?: (event: React.MouseEvent<HTMLElement>) => void;
6
- onMouseLeave?: (event: React.MouseEvent<HTMLElement>) => void;
7
- onPointerEnter?: (event: React.MouseEvent<HTMLElement>) => void;
8
- onClick?: (event: React.MouseEvent<HTMLElement>) => void;
9
- }>;
10
- }): import("react/jsx-runtime").JSX.Element;
2
+ export declare function Popover(props: PopoverProps): import("react/jsx-runtime").JSX.Element;
11
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAE7C,OAAO,KAAmC,MAAM,OAAO,CAAC;AAKxD,wBAAgB,OAAO,CACrB,KAAK,EAAE,YAAY,GAAG;IACpB,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC;QAC3B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAC9D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAC9D,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;KAC1D,CAAC,CAAC;CACJ,2CA4FF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AASA,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAO7C,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,2CAqB1C"}
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.Popover = Popover;
7
7
  var _react = require("@xyflow/react");
8
- var _ahooks = require("ahooks");
9
8
  var _antd = require("antd");
10
9
  var _react2 = _interopRequireWildcard(require("react"));
11
10
  var _useNodeDragging = require("../../hooks/node/useNodeDragging");
@@ -23,83 +22,23 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
23
22
 
24
23
  function Popover(props) {
25
24
  const isNodeDragging = (0, _useNodeDragging.useNodeDragging)();
26
- const [open, setOpen] = (0, _ahooks.useControllableValue)(props, {
27
- valuePropName: 'open',
28
- defaultValue: false,
29
- trigger: 'onOpenChange'
30
- });
31
- const showFirstRef = (0, _react2.useRef)(false); // 是否首次渲染过
32
-
25
+ const {
26
+ x,
27
+ y
28
+ } = (0, _react.useViewport)();
33
29
  const {
34
30
  children,
35
- trigger = 'hover',
36
31
  ...rest
37
32
  } = props;
38
- (0, _react2.useMemo)(() => {
39
- if (open) {
40
- showFirstRef.current = true; // 初始化之后就不销毁了
41
- }
42
- }, [open]);
43
- const _onMouseEnter = (0, _ahooks.useMemoizedFn)(event => {
44
- if (!showFirstRef.current) {
45
- setOpen(true);
46
- }
47
- children?.props?.onMouseEnter?.(event);
48
- });
49
- const _onMouseLeave = (0, _ahooks.useMemoizedFn)(event => {
50
- setOpen(false);
51
- children?.props?.onMouseLeave?.(event);
52
- });
53
- const _onClick = (0, _ahooks.useMemoizedFn)(event => {
54
- if (!showFirstRef.current) {
55
- setOpen(beforeOpen => !beforeOpen);
56
- }
57
- children?.props?.onClick?.(event);
58
- });
59
- const triggerActions = (0, _react2.useMemo)(() => {
60
- return {
61
- click: trigger === 'click' || trigger && Array.from(trigger) && trigger.indexOf('click') !== -1,
62
- hover: trigger === 'hover' || trigger && Array.from(trigger) && trigger.indexOf('hover') !== -1
63
- };
64
- }, []);
65
33
  const tooltipRef = (0, _react2.useRef)(null);
66
- const {
67
- x,
68
- y
69
- } = (0, _react.useViewport)();
70
- (0, _react2.useEffect)(() => {
71
- if (triggerActions.hover) {
72
- setOpen(false); // viewport 移动, 自动关闭,fix
73
- }
74
- }, [x, y]);
75
- (0, _react2.useEffect)(() => {
76
- if (open) {
77
- setOpen(false);
78
- }
79
- }, [isNodeDragging]);
80
- const cloneChildren = (0, _react2.useMemo)(() => {
81
- return /*#__PURE__*/_react2.default.cloneElement(children, {
82
- ...children.props,
83
- ...(triggerActions.hover ? {
84
- onMouseEnter: _onMouseEnter,
85
- onMouseLeave: _onMouseLeave
86
- } : {}),
87
- ...(triggerActions.click ? {
88
- onClick: _onClick
89
- } : {})
90
- });
91
- }, [children]);
92
- if (open || showFirstRef.current) {
93
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Popover, {
94
- ref: tooltipRef,
95
- destroyOnHidden: true,
96
- getPopupContainer: _getPopupContainer.getPopupContainer,
97
- ...rest,
98
- trigger: trigger,
99
- open: open,
100
- onOpenChange: setOpen,
101
- children: children
102
- });
103
- }
104
- return cloneChildren;
34
+ (0, _react2.useLayoutEffect)(() => {
35
+ tooltipRef.current?.forceAlign();
36
+ }, [isNodeDragging, x, y]);
37
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Popover, {
38
+ ref: tooltipRef,
39
+ destroyOnHidden: true,
40
+ getPopupContainer: _getPopupContainer.getPopupContainer,
41
+ ...rest,
42
+ children: children
43
+ });
105
44
  }
@@ -1,12 +1,3 @@
1
1
  import { TooltipProps } from "antd/es/tooltip";
2
- import React from "react";
3
- export declare function Tooltip({ children, canTooltipShow, title, trigger, ...rest }: TooltipProps & {
4
- children: React.ReactElement<{
5
- onMouseEnter?: (event: React.MouseEvent<HTMLElement>) => void;
6
- onMouseLeave?: (event: React.MouseEvent<HTMLElement>) => void;
7
- onPointerEnter?: (event: React.MouseEvent<HTMLElement>) => void;
8
- onClick?: (event: React.MouseEvent<HTMLElement>) => void;
9
- }>;
10
- canTooltipShow?: (e: React.MouseEvent<HTMLElement>) => void;
11
- }): import("react/jsx-runtime").JSX.Element;
2
+ export declare function Tooltip({ children, ...rest }: TooltipProps): import("react/jsx-runtime").JSX.Element;
12
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAC,YAAY,EAAa,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAmC,MAAM,OAAO,CAAC;AAIxD,wBAAgB,OAAO,CACrB,EACE,QAAQ,EACR,cAAc,EACd,KAAK,EACL,OAAiB,EACjB,GAAG,IAAI,EACR,EAAE,YAAY,GAAG;IAChB,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC;QAC3B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAC9D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAC9D,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;KAC1D,CAAC,CAAC;IACH,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;CAC5D,2CAmGF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AASA,OAAO,EAAC,YAAY,EAAa,MAAM,iBAAiB,CAAC;AAKzD,wBAAgB,OAAO,CACrB,EACE,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,YAAY,2CAmBhB"}
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.Tooltip = Tooltip;
7
7
  var _react = require("@xyflow/react");
8
- var _ahooks = require("ahooks");
9
8
  var _antd = require("antd");
10
9
  var _react2 = _interopRequireWildcard(require("react"));
11
10
  var _useNodeDragging = require("../../hooks/node/useNodeDragging");
@@ -23,93 +22,22 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
23
22
 
24
23
  function Tooltip({
25
24
  children,
26
- canTooltipShow,
27
- title,
28
- trigger = 'hover',
29
25
  ...rest
30
26
  }) {
31
- const isNodeDragging = (0, _useNodeDragging.useNodeDragging)();
32
- const [open, setOpen] = (0, _ahooks.useControllableValue)(rest, {
33
- valuePropName: 'open',
34
- defaultValue: false,
35
- trigger: 'onOpenChange'
36
- });
37
- const showFirstRef = (0, _react2.useRef)(false); // 是否首次渲染过
38
-
39
- (0, _react2.useMemo)(() => {
40
- if (open) {
41
- showFirstRef.current = true; // 初始化之后就不销毁了
42
- }
43
- }, [open]);
44
- (0, _react2.useEffect)(() => {
45
- if (!title) {
46
- setOpen(false);
47
- }
48
- }, [title]);
49
- const _onMouseEnter = (0, _ahooks.useMemoizedFn)(event => {
50
- if (!showFirstRef.current) {
51
- const canShow = canTooltipShow?.(event) ?? true;
52
- if (canShow && title) {
53
- setOpen(true);
54
- }
55
- }
56
- children?.props?.onMouseEnter?.(event);
57
- });
58
- const _onMouseLeave = (0, _ahooks.useMemoizedFn)(event => {
59
- setOpen(false);
60
- children?.props?.onMouseLeave?.(event);
61
- });
62
- const triggerActions = (0, _react2.useMemo)(() => {
63
- return {
64
- click: trigger === 'click' || trigger && Array.from(trigger) && trigger.indexOf('click') !== -1,
65
- hover: trigger === 'hover' || trigger && Array.from(trigger) && trigger.indexOf('hover') !== -1
66
- };
67
- }, []);
68
- const _onClick = (0, _ahooks.useMemoizedFn)(event => {
69
- if (!showFirstRef.current) {
70
- setOpen(beforeOpen => !beforeOpen);
71
- }
72
- children?.props?.onClick?.(event);
73
- });
74
27
  const tooltipRef = (0, _react2.useRef)(null);
28
+ const isNodeDragging = (0, _useNodeDragging.useNodeDragging)();
75
29
  const {
76
30
  x,
77
31
  y
78
32
  } = (0, _react.useViewport)();
79
- (0, _react2.useEffect)(() => {
80
- if (triggerActions.hover) {
81
- setOpen(false); // viewport 移动, 自动关闭,fix
82
- }
83
- }, [x, y]);
84
- (0, _react2.useEffect)(() => {
85
- if (open) {
86
- setOpen(false);
87
- }
88
- }, [isNodeDragging]);
89
- const cloneChildren = (0, _react2.useMemo)(() => {
90
- return /*#__PURE__*/_react2.default.cloneElement(children, {
91
- ...children.props,
92
- ...(triggerActions.hover ? {
93
- onMouseEnter: _onMouseEnter,
94
- onMouseLeave: _onMouseLeave
95
- } : {}),
96
- ...(triggerActions.click ? {
97
- onClick: _onClick
98
- } : {})
99
- });
100
- }, [children]);
101
- if (open || showFirstRef.current) {
102
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
103
- ref: tooltipRef,
104
- destroyOnHidden: true,
105
- title: title,
106
- getPopupContainer: _getPopupContainer.getPopupContainer,
107
- ...rest,
108
- trigger: trigger,
109
- open: open,
110
- onOpenChange: setOpen,
111
- children: children
112
- });
113
- }
114
- return cloneChildren;
33
+ (0, _react2.useLayoutEffect)(() => {
34
+ tooltipRef.current?.forceAlign();
35
+ }, [isNodeDragging, x, y]);
36
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_antd.Tooltip, {
37
+ ref: tooltipRef,
38
+ destroyOnHidden: true,
39
+ getPopupContainer: _getPopupContainer.getPopupContainer,
40
+ ...rest,
41
+ children: children
42
+ });
115
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"manhattan.d.ts","sourceRoot":"","sources":["manhattan.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAW,KAAK,SAAS,EAAc,MAAM,eAAe,CAAC;AACpE,OAAO,EAAC,aAAa,EAAoC,MAAM,OAAO,CAAC;AAgGvE,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,SAAS,CA0IjD,CAAA"}
1
+ {"version":3,"file":"manhattan.d.ts","sourceRoot":"","sources":["manhattan.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAW,KAAK,SAAS,EAA2C,MAAM,eAAe,CAAC;AACjG,OAAO,EAAC,aAAa,EAAoC,MAAM,OAAO,CAAC;AAmKvE,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,SAAS,CAwJjD,CAAA"}
@@ -18,22 +18,74 @@ var _jsxRuntime = require("react/jsx-runtime");
18
18
  * Copyright (c) 2025 by yanxianliang, All Rights Reserved.
19
19
  */
20
20
 
21
+ /**
22
+ * 判断是否为简单的就近连接场景
23
+ * 这些场景不需要复杂的 Manhattan 算法,直接使用 SmoothStep 即可
24
+ *
25
+ * 就近连接规则:
26
+ * - 右锚点 → 左锚点(source 在 target 左侧)
27
+ * - 左锚点 → 右锚点(source 在 target 右侧)
28
+ * - 下锚点 → 上锚点(source 在 target 上方)
29
+ * - 上锚点 → 下锚点(source 在 target 下方)
30
+ */
31
+ function isSimpleConnection(sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition) {
32
+ // 右 → 左:source 在左侧,target 在右侧
33
+ if (sourcePosition === _react.Position.Right && targetPosition === _react.Position.Left) {
34
+ return sourceX < targetX;
35
+ }
36
+
37
+ // 左 → 右:source 在右侧,target 在左侧
38
+ if (sourcePosition === _react.Position.Left && targetPosition === _react.Position.Right) {
39
+ return sourceX > targetX;
40
+ }
41
+
42
+ // 下 → 上:source 在上方,target 在下方
43
+ if (sourcePosition === _react.Position.Bottom && targetPosition === _react.Position.Top) {
44
+ return sourceY < targetY;
45
+ }
46
+
47
+ // 上 → 下:source 在下方,target 在上方
48
+ if (sourcePosition === _react.Position.Top && targetPosition === _react.Position.Bottom) {
49
+ return sourceY > targetY;
50
+ }
51
+ return false;
52
+ }
53
+
21
54
  // 全局 Worker 实例(单例)
22
55
  let workerInstance = null;
23
56
  let workerApi = null;
57
+ let workerInitFailed = false;
58
+
59
+ /**
60
+ * 创建 Worker
61
+ * 使用预编译的 .js bundle,不使用 type: 'module' 以获得更好的浏览器兼容性
62
+ */
63
+ function tryCreateWorker() {
64
+ try {
65
+ return new Worker(new URL('../workers/manhattan.worker.js', import.meta.url));
66
+ } catch (error) {
67
+ console.warn('[ManhattanEdge] Worker creation failed:', error);
68
+ return null;
69
+ }
70
+ }
24
71
 
25
72
  // 获取或创建 Worker
26
73
  function getWorker() {
27
74
  if (typeof window === 'undefined') return null; // SSR 环境
75
+ if (workerInitFailed) return null; // 之前初始化失败,不再尝试
28
76
 
29
77
  if (!workerInstance || !workerApi) {
30
78
  try {
31
- workerInstance = new Worker(new URL('../workers/manhattan.worker.ts', import.meta.url), {
32
- type: 'module'
33
- });
34
- workerApi = (0, _comlink.wrap)(workerInstance);
79
+ workerInstance = tryCreateWorker();
80
+ if (workerInstance) {
81
+ workerApi = (0, _comlink.wrap)(workerInstance);
82
+ } else {
83
+ workerInitFailed = true;
84
+ return null;
85
+ }
35
86
  } catch (error) {
36
87
  console.warn('[ManhattanEdge] Worker initialization failed, using main thread:', error);
88
+ workerInitFailed = true;
37
89
  return null;
38
90
  }
39
91
  }
@@ -51,7 +103,8 @@ const perfStats = {
51
103
  cacheHits: 0,
52
104
  cacheMisses: 0,
53
105
  workerCalculations: 0,
54
- mainThreadCalculations: 0
106
+ mainThreadCalculations: 0,
107
+ simplePathCalculations: 0 // 简单路径(使用 SmoothStep)
55
108
  };
56
109
 
57
110
  // 生成缓存 key
@@ -75,17 +128,20 @@ function resetPerfStats() {
75
128
  perfStats.cacheMisses = 0;
76
129
  perfStats.workerCalculations = 0;
77
130
  perfStats.mainThreadCalculations = 0;
131
+ perfStats.simplePathCalculations = 0;
78
132
  }
79
133
 
80
134
  // 打印统计
81
135
  function logPerfStats() {
82
136
  const totalDuration = performance.now() - perfStats.startTime;
83
137
  const cacheHitRate = perfStats.totalEdges > 0 ? (perfStats.cacheHits / perfStats.totalEdges * 100).toFixed(1) : '0';
138
+ const simplePathRate = perfStats.totalEdges > 0 ? (perfStats.simplePathCalculations / perfStats.totalEdges * 100).toFixed(1) : '0';
84
139
  console.log('=== Manhattan Edge Performance Stats ===');
85
140
  console.log(`Total edges: ${perfStats.totalEdges}`);
86
141
  console.log(`Completed: ${perfStats.completedEdges}`);
87
142
  console.log(`Cache hits: ${perfStats.cacheHits} (${cacheHitRate}%)`);
88
143
  console.log(`Cache misses: ${perfStats.cacheMisses}`);
144
+ console.log(`Simple paths (SmoothStep): ${perfStats.simplePathCalculations} (${simplePathRate}%)`);
89
145
  console.log(`Worker calculations: ${perfStats.workerCalculations}`);
90
146
  console.log(`Main thread calculations: ${perfStats.mainThreadCalculations}`);
91
147
  console.log(`Total calculation time: ${perfStats.totalTime.toFixed(2)}ms`);
@@ -147,32 +203,48 @@ const ManhattanEdge = exports.ManhattanEdge = /*#__PURE__*/(0, _react2.memo)(({
147
203
  if (!isMountedRef.current) return;
148
204
  const startTime = performance.now();
149
205
  let calculatedPath;
150
- const params = {
151
- sourceNodeId: source,
152
- targetNodeId: target,
153
- sourceX,
154
- sourceY,
155
- sourcePosition,
156
- targetX,
157
- targetY,
158
- targetPosition,
159
- nodeLookup: nodeLookup
160
- };
161
-
162
- // 尝试使用 Worker,失败则回退到主线程
163
- const worker = getWorker();
164
- try {
165
- if (worker) {
166
- perfStats.workerCalculations++;
167
- calculatedPath = await worker.calculatePath(params);
168
- } else {
206
+
207
+ // 前置判断:简单的就近连接场景直接使用 SmoothStep
208
+ if (isSimpleConnection(sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition)) {
209
+ perfStats.simplePathCalculations++;
210
+ const [smoothPath] = (0, _react.getSmoothStepPath)({
211
+ sourceX,
212
+ sourceY,
213
+ sourcePosition,
214
+ targetX,
215
+ targetY,
216
+ targetPosition
217
+ });
218
+ calculatedPath = smoothPath;
219
+ } else {
220
+ // 复杂场景使用 Manhattan 算法
221
+ const params = {
222
+ sourceNodeId: source,
223
+ targetNodeId: target,
224
+ sourceX,
225
+ sourceY,
226
+ sourcePosition,
227
+ targetX,
228
+ targetY,
229
+ targetPosition,
230
+ nodeLookup: nodeLookup
231
+ };
232
+
233
+ // 尝试使用 Worker,失败则回退到主线程
234
+ const worker = getWorker();
235
+ try {
236
+ if (worker) {
237
+ perfStats.workerCalculations++;
238
+ calculatedPath = await worker.calculatePath(params);
239
+ } else {
240
+ perfStats.mainThreadCalculations++;
241
+ calculatedPath = (0, _manhattan.getManHattanPath)(params);
242
+ }
243
+ } catch (error) {
244
+ // Fallback 到主线程
169
245
  perfStats.mainThreadCalculations++;
170
246
  calculatedPath = (0, _manhattan.getManHattanPath)(params);
171
247
  }
172
- } catch (error) {
173
- // Fallback 到主线程
174
- perfStats.mainThreadCalculations++;
175
- calculatedPath = (0, _manhattan.getManHattanPath)(params);
176
248
  }
177
249
  const endTime = performance.now();
178
250
  const duration = endTime - startTime;
@@ -201,8 +273,6 @@ const ManhattanEdge = exports.ManhattanEdge = /*#__PURE__*/(0, _react2.memo)(({
201
273
  logPerfStats();
202
274
  }
203
275
  };
204
-
205
- // 直接执行异步计算(Worker 已经是异步的)
206
276
  calculatePath();
207
277
  return () => {
208
278
  isMountedRef.current = false;
@@ -1,14 +1,40 @@
1
1
  /**
2
2
  * @author: yanxianliang
3
3
  * @date: 2025-10-15 15:25
4
- * @modified:2025/10/15 15:25 by yanxianliang
4
+ * @modified:2025/1/17 by yanxianliang
5
5
  * @desc: 创建 Flow 组件
6
6
  *
7
- * 提供公众能力封装
7
+ * 提供公共能力封装,支持双层 Props 存储
8
8
  *
9
9
  * Copyright (c) 2025 by yanxianliang, All Rights Reserved.
10
10
  */
11
- import { IBaseFlowProps } from "../types";
11
+ import { Edge, Node } from "@xyflow/react";
12
12
  import React, { PropsWithChildren } from "react";
13
- export declare function createFlow<Props = IBaseFlowProps, ExtendProps = {}>(FlowComponent: React.ComponentType<IBaseFlowProps & ExtendProps>, usePropsTransform?: (props: PropsWithChildren<Props>) => PropsWithChildren<IBaseFlowProps & ExtendProps>): (props: React.PropsWithChildren<Props>) => import("react/jsx-runtime").JSX.Element;
13
+ import { IBaseFlowProps } from "../types";
14
+ /**
15
+ * 创建 Flow 组件的工厂函数
16
+ *
17
+ * @param FlowComponent - 基础 Flow 组件
18
+ * @param usePropsTransform - Props 转换 hook,将输入 props 转换为 Flow props
19
+ *
20
+ * @example
21
+ * // 基础用法
22
+ * const MyFlow = createFlow(Flow);
23
+ *
24
+ * @example
25
+ * // 带 props 转换
26
+ * const BloodlineFlow = createFlow<IBloodlineFlowProps, BloodlineExtendProps>(
27
+ * Flow,
28
+ * (props) => {
29
+ * const { root, nodeTypes } = props;
30
+ * const nodes = useMemo(() => root ? [root] : [], [root]);
31
+ * return {
32
+ * ...props,
33
+ * nodes,
34
+ * nodeTypes: wrapNodeTypes(nodeTypes, BaseNodeWrapper),
35
+ * };
36
+ * }
37
+ * );
38
+ */
39
+ export declare function createFlow<TInputProps = IBaseFlowProps, TExtendProps = {}, NodeType extends Node = Node, EdgeType extends Edge = Edge>(FlowComponent: React.ComponentType<IBaseFlowProps<NodeType, EdgeType> & TExtendProps>, usePropsTransform?: (props: PropsWithChildren<TInputProps>) => PropsWithChildren<IBaseFlowProps<NodeType, EdgeType> & TExtendProps>): (props: React.PropsWithChildren<TInputProps>) => import("react/jsx-runtime").JSX.Element;
14
40
  //# sourceMappingURL=createFlow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createFlow.d.ts","sourceRoot":"","sources":["createFlow.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,cAAc,EAAC,MAAM,UAAU,CAAC;AAGxC,OAAO,KAAK,EAAE,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AA0B/C,wBAAgB,UAAU,CAAC,KAAK,GAAG,cAAc,EAAE,WAAW,GAAG,EAAE,EACjE,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,cAAc,GAAG,WAAW,CAAC,EAChE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,iBAAiB,CAAC,cAAc,GAAG,WAAW,CAAC,sFAwBzG"}
1
+ {"version":3,"file":"createFlow.d.ts","sourceRoot":"","sources":["createFlow.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,MAAM,eAAe,CAAC;AAEzC,OAAO,KAAK,EAAE,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAG/C,OAAO,EAAC,cAAc,EAAC,MAAM,UAAU,CAAC;AAwBxC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,UAAU,CACxB,WAAW,GAAG,cAAc,EAC5B,YAAY,GAAG,EAAE,EACjB,QAAQ,SAAS,IAAI,GAAG,IAAI,EAC5B,QAAQ,SAAS,IAAI,GAAG,IAAI,EAE5B,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAC,EACrF,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,WAAW,CAAC,KAAK,iBAAiB,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAC,4FA4BpI"}