v-nuxt-ui 0.1.35 → 0.2.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.
Files changed (109) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +1 -0
  3. package/dist/runtime/components/Watermark.d.vue.ts +3 -3
  4. package/dist/runtime/components/Watermark.vue.d.ts +3 -3
  5. package/dist/runtime/components/button/CircleColor.d.vue.ts +17 -0
  6. package/dist/runtime/components/button/CircleColor.vue +37 -0
  7. package/dist/runtime/components/button/CircleColor.vue.d.ts +17 -0
  8. package/dist/runtime/components/button/Dropdown.vue +5 -1
  9. package/dist/runtime/components/date-picker/Input.d.vue.ts +9 -1
  10. package/dist/runtime/components/date-picker/Input.vue +55 -11
  11. package/dist/runtime/components/date-picker/Input.vue.d.ts +9 -1
  12. package/dist/runtime/components/date-picker/index.vue +3 -3
  13. package/dist/runtime/components/flow/FlowEdge.client.vue +170 -41
  14. package/dist/runtime/components/flow/FlowEditor.client.d.vue.ts +51 -0
  15. package/dist/runtime/components/flow/FlowEditor.client.vue +287 -0
  16. package/dist/runtime/components/flow/FlowEditor.client.vue.d.ts +51 -0
  17. package/dist/runtime/components/flow/FlowNode.client.d.vue.ts +13 -2
  18. package/dist/runtime/components/flow/FlowNode.client.vue +44 -48
  19. package/dist/runtime/components/flow/FlowNode.client.vue.d.ts +13 -2
  20. package/dist/runtime/components/flow/FlowToolbar.d.vue.ts +41 -5
  21. package/dist/runtime/components/flow/FlowToolbar.vue +554 -88
  22. package/dist/runtime/components/flow/FlowToolbar.vue.d.ts +41 -5
  23. package/dist/runtime/components/flow/FlowToolbarItemWrapper.d.vue.ts +17 -0
  24. package/dist/runtime/components/flow/FlowToolbarItemWrapper.vue +16 -0
  25. package/dist/runtime/components/flow/FlowToolbarItemWrapper.vue.d.ts +17 -0
  26. package/dist/runtime/components/form/field/DatePicker.vue +1 -1
  27. package/dist/runtime/components/sys/flow/CreateModal.d.vue.ts +13 -0
  28. package/dist/runtime/components/sys/flow/CreateModal.vue +32 -0
  29. package/dist/runtime/components/sys/flow/CreateModal.vue.d.ts +13 -0
  30. package/dist/runtime/components/sys/flow/EditNodeModal.d.vue.ts +13 -0
  31. package/dist/runtime/components/sys/flow/EditNodeModal.vue +30 -0
  32. package/dist/runtime/components/sys/flow/EditNodeModal.vue.d.ts +13 -0
  33. package/dist/runtime/components/sys/flow/Table.d.vue.ts +3 -0
  34. package/dist/runtime/components/sys/flow/Table.vue +103 -0
  35. package/dist/runtime/components/sys/flow/Table.vue.d.ts +3 -0
  36. package/dist/runtime/components/sys/table/CreateModal.vue +9 -193
  37. package/dist/runtime/components/sys/table/Table.vue +6 -15
  38. package/dist/runtime/components/sys/table/TableColumnList.d.vue.ts +54 -0
  39. package/dist/runtime/components/sys/table/TableColumnList.vue +196 -0
  40. package/dist/runtime/components/sys/table/TableColumnList.vue.d.ts +54 -0
  41. package/dist/runtime/components/sys/table/TableColumnModal.d.vue.ts +3 -13
  42. package/dist/runtime/components/sys/table/TableColumnModal.vue +32 -100
  43. package/dist/runtime/components/sys/table/TableColumnModal.vue.d.ts +3 -13
  44. package/dist/runtime/components/sys/user/Table.vue +44 -27
  45. package/dist/runtime/components/table/permission/TablePermissionConfig.d.vue.ts +2 -2
  46. package/dist/runtime/components/table/permission/TablePermissionConfig.vue +3 -3
  47. package/dist/runtime/components/table/permission/TablePermissionConfig.vue.d.ts +2 -2
  48. package/dist/runtime/components/table/permission/TablePermissionTab.vue +7 -4
  49. package/dist/runtime/components/table/query/order/Item.d.vue.ts +2 -2
  50. package/dist/runtime/components/table/query/order/Item.vue.d.ts +2 -2
  51. package/dist/runtime/components/table/query/where/Newer.vue +2 -0
  52. package/dist/runtime/components/table/query/where/index.vue +46 -15
  53. package/dist/runtime/components/table/query/where/simple/item/ColumnPicker.vue +9 -4
  54. package/dist/runtime/components/table/query/where/simple/item/OprPicker.vue +3 -3
  55. package/dist/runtime/components/table/query/where/simple/item/opr/AsyncSelect.vue +45 -48
  56. package/dist/runtime/components/table/query/where/simple/item/opr/DatePicker.vue +137 -131
  57. package/dist/runtime/components/table/query/where/simple/item/opr/Select.d.vue.ts +4 -2
  58. package/dist/runtime/components/table/query/where/simple/item/opr/Select.vue +40 -40
  59. package/dist/runtime/components/table/query/where/simple/item/opr/Select.vue.d.ts +4 -2
  60. package/dist/runtime/components/table/query/where/simple/item/opr/index.vue +2 -0
  61. package/dist/runtime/components/table/settings/TableSettings.d.vue.ts +1 -1
  62. package/dist/runtime/components/table/settings/TableSettings.vue +0 -3
  63. package/dist/runtime/components/table/settings/TableSettings.vue.d.ts +1 -1
  64. package/dist/runtime/composables/api/sys/index.d.ts +3 -0
  65. package/dist/runtime/composables/api/sys/index.js +3 -0
  66. package/dist/runtime/composables/api/sys/useFlowApi.d.ts +2 -0
  67. package/dist/runtime/composables/api/sys/useFlowApi.js +5 -0
  68. package/dist/runtime/composables/api/sys/useFlowEdgeApi.d.ts +2 -0
  69. package/dist/runtime/composables/api/sys/useFlowEdgeApi.js +3 -0
  70. package/dist/runtime/composables/api/sys/useFlowNodeApi.d.ts +2 -0
  71. package/dist/runtime/composables/api/sys/useFlowNodeApi.js +3 -0
  72. package/dist/runtime/composables/api/sys/useRoleApi.js +3 -1
  73. package/dist/runtime/composables/api/sys/useUserApi.js +3 -1
  74. package/dist/runtime/composables/flow/index.d.ts +3 -0
  75. package/dist/runtime/composables/flow/index.js +3 -0
  76. package/dist/runtime/composables/flow/useFlow.d.ts +33 -0
  77. package/dist/runtime/composables/flow/useFlow.js +401 -0
  78. package/dist/runtime/composables/flow/useFlowNode.d.ts +17 -0
  79. package/dist/runtime/composables/flow/useFlowNode.js +106 -0
  80. package/dist/runtime/composables/flow/useFlowResize.d.ts +21 -0
  81. package/dist/runtime/composables/flow/useFlowResize.js +84 -0
  82. package/dist/runtime/composables/flow/useFlowStyles.d.ts +62 -9
  83. package/dist/runtime/composables/flow/useFlowStyles.js +127 -23
  84. package/dist/runtime/composables/table/useTableColumnPermission.d.ts +36 -0
  85. package/dist/runtime/composables/useDate.js +8 -8
  86. package/dist/runtime/composables/useSidebarMenu.js +0 -2
  87. package/dist/runtime/composables/useTheme.d.ts +1 -1
  88. package/dist/runtime/composables/useTheme.js +0 -1
  89. package/dist/runtime/constants/flow.d.ts +166 -0
  90. package/dist/runtime/constants/flow.js +171 -0
  91. package/dist/runtime/constants/index.d.ts +1 -0
  92. package/dist/runtime/constants/index.js +1 -0
  93. package/dist/runtime/constants/options.js +2 -3
  94. package/dist/runtime/constants/table.d.ts +2 -0
  95. package/dist/runtime/constants/table.js +8 -0
  96. package/dist/runtime/index.css +1 -1
  97. package/dist/runtime/types/components/table/column.d.ts +4 -3
  98. package/dist/runtime/types/components/table/query/where.d.ts +1 -5
  99. package/dist/runtime/types/models/flow.d.ts +61 -0
  100. package/dist/runtime/types/models/flow.js +0 -0
  101. package/dist/runtime/types/models/index.d.ts +1 -0
  102. package/dist/runtime/types/models/index.js +1 -0
  103. package/dist/runtime/types/models/table.d.ts +1 -0
  104. package/dist/runtime/types/storage.d.ts +3 -4
  105. package/dist/runtime/types/storage.js +3 -4
  106. package/package.json +3 -2
  107. package/dist/runtime/components/table/query/where/simple/index.d.vue.ts +0 -21
  108. package/dist/runtime/components/table/query/where/simple/index.vue +0 -52
  109. package/dist/runtime/components/table/query/where/simple/index.vue.d.ts +0 -21
@@ -0,0 +1,287 @@
1
+ <script setup>
2
+ import { ref, computed, provide, watchEffect, onMounted, onBeforeUnmount } from "vue";
3
+ import { VueFlow, useVueFlow, Panel } from "@vue-flow/core";
4
+ import { Background } from "@vue-flow/background";
5
+ import { FLOW_MOUSE_POSITION_KEY, FLOW_EDGE_STROKE_TYPES } from "#v/constants";
6
+ import FlowNode from "./FlowNode.client.vue";
7
+ import FlowEdge from "./FlowEdge.client.vue";
8
+ import FlowToolbar from "./FlowToolbar.vue";
9
+ import FlowStats from "./FlowStats.vue";
10
+ import { useFlow, useFlowResize, useFlowStyles } from "#v/composables";
11
+ const props = defineProps({
12
+ modelValue: { type: Object, required: false, default: () => ({ id: 0, nodes: [], edges: [] }) },
13
+ api: { type: Object, required: false, default: void 0 },
14
+ showBackground: { type: Boolean, required: false, default: true },
15
+ showToolbar: { type: Boolean, required: false, default: true },
16
+ showStats: { type: Boolean, required: false, default: true },
17
+ minZoom: { type: Number, required: false, default: 0.2 },
18
+ maxZoom: { type: Number, required: false, default: 4 },
19
+ defaultZoom: { type: Number, required: false, default: 1 }
20
+ });
21
+ const emit = defineEmits(["update:modelValue", "edit-node"]);
22
+ const handleUpdateModel = (model) => {
23
+ emit("update:modelValue", model);
24
+ };
25
+ const flowLogic = useFlow({
26
+ flow: computed(() => props.modelValue),
27
+ onUpdateModel: computed(() => handleUpdateModel),
28
+ api: computed(() => props.api)
29
+ });
30
+ const {
31
+ nodes,
32
+ edges,
33
+ GRID_SIZE,
34
+ loading,
35
+ deleteNode,
36
+ deleteEdge,
37
+ createEdge,
38
+ reconnectEdge,
39
+ updateNodePosition,
40
+ updateNodeDimensions,
41
+ createNode,
42
+ updateEdgeLabel
43
+ } = flowLogic;
44
+ const {
45
+ edgeStrokeWidth,
46
+ edgeMarkerStart,
47
+ edgeMarkerEnd,
48
+ edgeAnimated,
49
+ edgeStrokeType,
50
+ edgePathType,
51
+ edgeColor,
52
+ edgeLabelColor,
53
+ nodeBorderWidth,
54
+ nodeBorderRadius,
55
+ nodeBorderColor,
56
+ nodeBgColor,
57
+ nodeFontColor,
58
+ nodeFontSize,
59
+ nodeHandleSize,
60
+ nodeHandleColor,
61
+ colorMode,
62
+ unifiedColor,
63
+ isUnifiedMode,
64
+ effectiveNodeBorderColor,
65
+ effectiveNodeBgColor,
66
+ effectiveNodeFontColor,
67
+ effectiveNodeHandleColor,
68
+ effectiveEdgeColor
69
+ } = useFlowStyles();
70
+ const { onConnect, onNodeDragStop, onEdgeUpdate, getSelectedNodes, getSelectedEdges, getViewport } = useVueFlow();
71
+ const handleResizeEnd = async (nodeId, dimensions) => {
72
+ await updateNodeDimensions(nodeId, dimensions);
73
+ };
74
+ const resizeLogic = useFlowResize({
75
+ gridSize: GRID_SIZE,
76
+ nodes,
77
+ getViewport,
78
+ onResizeEnd: handleResizeEnd
79
+ });
80
+ const {
81
+ startResize,
82
+ handleMouseMove,
83
+ handleMouseUp
84
+ } = resizeLogic;
85
+ const mousePosition = ref({ x: 0, y: 0 });
86
+ provide(FLOW_MOUSE_POSITION_KEY, mousePosition);
87
+ const handleEditNode = (nodeId) => {
88
+ const flowNode = props.modelValue?.nodes?.find((n) => String(n.id) === nodeId);
89
+ if (flowNode) {
90
+ emit("edit-node", flowNode);
91
+ }
92
+ };
93
+ watchEffect(() => {
94
+ flowLogic.syncNodes((nodeId) => ({
95
+ onEdit: () => handleEditNode(nodeId),
96
+ onDelete: () => deleteNode(nodeId),
97
+ borderWidth: nodeBorderWidth.value,
98
+ borderRadius: nodeBorderRadius.value,
99
+ borderColor: effectiveNodeBorderColor.value,
100
+ bgColor: effectiveNodeBgColor.value,
101
+ fontColor: effectiveNodeFontColor.value,
102
+ fontSize: nodeFontSize.value,
103
+ handleSize: nodeHandleSize.value,
104
+ handleColor: effectiveNodeHandleColor.value,
105
+ onResizeStart: (event, edge) => {
106
+ const node = props.modelValue?.nodes?.find((n) => String(n.id) === nodeId);
107
+ if (node) {
108
+ startResize(event, nodeId, node, edge);
109
+ }
110
+ }
111
+ }));
112
+ });
113
+ watchEffect(() => {
114
+ const dasharray = FLOW_EDGE_STROKE_TYPES.find((t) => t.type === edgeStrokeType.value)?.dasharray || "";
115
+ edges.value.forEach((edge) => {
116
+ edge.style = {
117
+ strokeWidth: edgeStrokeWidth.value,
118
+ ...dasharray ? { strokeDasharray: dasharray } : {},
119
+ ...effectiveEdgeColor.value ? { stroke: effectiveEdgeColor.value } : {}
120
+ };
121
+ edge.markerStart = void 0;
122
+ edge.markerEnd = void 0;
123
+ edge.animated = false;
124
+ });
125
+ });
126
+ watchEffect(() => {
127
+ flowLogic.syncEdges((edgeId) => ({
128
+ onUpdateLabel: (newLabel) => updateEdgeLabel(edgeId, newLabel)
129
+ }));
130
+ });
131
+ const isDeleteKey = (event) => {
132
+ return event.key === "Delete" || event.key === "Backspace" || event.code === "Backspace";
133
+ };
134
+ const handleKeyDown = async (event) => {
135
+ if (!isDeleteKey(event)) return;
136
+ event.preventDefault();
137
+ event.stopPropagation();
138
+ event.stopImmediatePropagation();
139
+ const selectedNodes = getSelectedNodes.value;
140
+ const selectedEdges = getSelectedEdges.value;
141
+ if (selectedNodes.length === 0 && selectedEdges.length === 0) return;
142
+ await Promise.all([
143
+ ...selectedNodes.map((node) => deleteNode(node.id)),
144
+ ...selectedEdges.map((edge) => deleteEdge(edge.id))
145
+ ]);
146
+ };
147
+ onMounted(() => {
148
+ const handleGlobalMouseMove = (event) => {
149
+ mousePosition.value = { x: event.clientX, y: event.clientY };
150
+ handleMouseMove(event);
151
+ };
152
+ document.addEventListener("keydown", handleKeyDown, true);
153
+ window.addEventListener("mousemove", handleGlobalMouseMove);
154
+ window.addEventListener("mouseup", handleMouseUp);
155
+ onBeforeUnmount(() => {
156
+ document.removeEventListener("keydown", handleKeyDown, true);
157
+ window.removeEventListener("mousemove", handleGlobalMouseMove);
158
+ window.removeEventListener("mouseup", handleMouseUp);
159
+ });
160
+ });
161
+ onNodeDragStop(async (event) => {
162
+ const { node } = event;
163
+ await updateNodePosition(node.id, node.position.x, node.position.y);
164
+ });
165
+ onConnect(async (params) => {
166
+ await createEdge(params);
167
+ });
168
+ onEdgeUpdate(({ edge, connection }) => {
169
+ if (connection.source && connection.target) {
170
+ reconnectEdge(edge.id, connection);
171
+ }
172
+ });
173
+ const defaultEdgeOptions = computed(() => {
174
+ const dasharray = FLOW_EDGE_STROKE_TYPES.find((t) => t.type === edgeStrokeType.value)?.dasharray || "";
175
+ return {
176
+ style: {
177
+ strokeWidth: edgeStrokeWidth.value,
178
+ ...dasharray ? { strokeDasharray: dasharray } : {},
179
+ ...effectiveEdgeColor.value ? { stroke: effectiveEdgeColor.value } : {}
180
+ },
181
+ // Markers are handled by FlowEdge custom SVG markers
182
+ markerStart: void 0,
183
+ markerEnd: void 0,
184
+ animated: false
185
+ };
186
+ });
187
+ const isValidConnection = () => true;
188
+ </script>
189
+
190
+ <template>
191
+ <VueFlow
192
+ v-model:nodes="nodes"
193
+ v-model:edges="edges"
194
+ :default-zoom="defaultZoom"
195
+ :min-zoom="minZoom"
196
+ :max-zoom="maxZoom"
197
+ :snap-to-grid="true"
198
+ :snap-grid="[GRID_SIZE, GRID_SIZE]"
199
+ :default-edge-options="defaultEdgeOptions"
200
+ :is-valid-connection="isValidConnection"
201
+ :edges-updatable="true"
202
+ >
203
+ <Background
204
+ v-if="showBackground"
205
+ pattern-color="var(--ui-bg-elevated)"
206
+ :gap="GRID_SIZE"
207
+ variant="lines"
208
+ />
209
+
210
+ <template #node-custom="nodeProps">
211
+ <FlowNode v-bind="nodeProps">
212
+ <template v-if="$slots.node" #default="{ data }">
213
+ <slot name="node" :data="data" />
214
+ </template>
215
+ </FlowNode>
216
+ </template>
217
+
218
+ <template #edge-custom="edgeProps">
219
+ <FlowEdge v-bind="edgeProps" />
220
+ </template>
221
+
222
+ <Panel v-if="showToolbar" position="bottom-center">
223
+ <FlowToolbar
224
+ :on-add-node="createNode"
225
+ :loading="loading"
226
+ :edge-stroke-width="edgeStrokeWidth"
227
+ :edge-stroke-type="edgeStrokeType"
228
+ :edge-path-type="edgePathType"
229
+ :edge-marker-start="edgeMarkerStart"
230
+ :edge-marker-end="edgeMarkerEnd"
231
+ :edge-animated="edgeAnimated"
232
+ :edge-color="edgeColor"
233
+ :edge-label-color="edgeLabelColor"
234
+ :node-border-width="nodeBorderWidth"
235
+ :node-border-radius="nodeBorderRadius"
236
+ :node-border-color="nodeBorderColor"
237
+ :node-bg-color="nodeBgColor"
238
+ :node-font-color="nodeFontColor"
239
+ :node-font-size="nodeFontSize"
240
+ :node-handle-size="nodeHandleSize"
241
+ :node-handle-color="nodeHandleColor"
242
+ :on-edge-stroke-width-change="(v) => edgeStrokeWidth = v"
243
+ :on-edge-stroke-type-change="(v) => edgeStrokeType = v"
244
+ :on-edge-path-type-change="(v) => edgePathType = v"
245
+ :on-edge-marker-start-change="(v) => edgeMarkerStart = v"
246
+ :on-edge-marker-end-change="(v) => edgeMarkerEnd = v"
247
+ :on-toggle-edge-animated="() => edgeAnimated = !edgeAnimated"
248
+ :on-edge-color-change="(v) => edgeColor = v"
249
+ :on-edge-label-color-change="(v) => edgeLabelColor = v"
250
+ :on-node-border-width-change="(v) => nodeBorderWidth = v"
251
+ :on-node-border-radius-change="(v) => nodeBorderRadius = v"
252
+ :on-node-border-color-change="(v) => nodeBorderColor = v"
253
+ :on-node-bg-color-change="(v) => nodeBgColor = v"
254
+ :on-node-font-color-change="(v) => nodeFontColor = v"
255
+ :on-node-font-size-change="(v) => nodeFontSize = v"
256
+ :on-node-handle-size-change="(v) => nodeHandleSize = v"
257
+ :on-node-handle-color-change="(v) => nodeHandleColor = v"
258
+ :color-mode="colorMode"
259
+ :unified-color="unifiedColor"
260
+ :is-unified-mode="isUnifiedMode"
261
+ :on-color-mode-change="(v) => colorMode = v"
262
+ :on-unified-color-change="(v) => unifiedColor = v"
263
+ />
264
+ </Panel>
265
+
266
+ <Panel v-if="showStats" position="top-right">
267
+ <div class="flex items-center gap-2">
268
+ <Transition name="fade">
269
+ <UIcon
270
+ v-if="loading"
271
+ name="i-lucide-loader-2"
272
+ class="text-primary animate-spin"
273
+ size="18"
274
+ />
275
+ </Transition>
276
+ <FlowStats :node-count="nodes.length" :edge-count="edges.length" />
277
+ </div>
278
+ </Panel>
279
+
280
+ <!-- 透传额外的 Panel 插槽 -->
281
+ <slot />
282
+ </VueFlow>
283
+ </template>
284
+
285
+ <style>
286
+ @import "@vue-flow/core/dist/style.css";@import "@vue-flow/core/dist/theme-default.css";.fade-enter-active,.fade-leave-active{transition:opacity .2s ease}.fade-enter-from,.fade-leave-to{opacity:0}
287
+ </style>
@@ -0,0 +1,51 @@
1
+ import type { Flow, FlowNode as FlowNodeType, FlowApi } from '#v/types';
2
+ type __VLS_Props = {
3
+ /** Flow 数据模型 (v-model) */
4
+ modelValue?: Flow;
5
+ /** CRUD API 回调,节点/边增删改时调用 */
6
+ api?: FlowApi;
7
+ /** 是否显示背景网格 */
8
+ showBackground?: boolean;
9
+ /** 是否显示工具栏 */
10
+ showToolbar?: boolean;
11
+ /** 是否显示统计面板 */
12
+ showStats?: boolean;
13
+ /** 最小缩放 */
14
+ minZoom?: number;
15
+ /** 最大缩放 */
16
+ maxZoom?: number;
17
+ /** 默认缩放 */
18
+ defaultZoom?: number;
19
+ };
20
+ declare var __VLS_21: {
21
+ data: any;
22
+ }, __VLS_62: {};
23
+ type __VLS_Slots = {} & {
24
+ node?: (props: typeof __VLS_21) => any;
25
+ } & {
26
+ default?: (props: typeof __VLS_62) => any;
27
+ };
28
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
29
+ "update:modelValue": (value: Flow) => any;
30
+ "edit-node": (node: FlowNodeType) => any;
31
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
32
+ "onUpdate:modelValue"?: ((value: Flow) => any) | undefined;
33
+ "onEdit-node"?: ((node: FlowNodeType) => any) | undefined;
34
+ }>, {
35
+ modelValue: Flow;
36
+ api: FlowApi;
37
+ showBackground: boolean;
38
+ showToolbar: boolean;
39
+ showStats: boolean;
40
+ minZoom: number;
41
+ maxZoom: number;
42
+ defaultZoom: number;
43
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
44
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
45
+ declare const _default: typeof __VLS_export;
46
+ export default _default;
47
+ type __VLS_WithSlots<T, S> = T & {
48
+ new (): {
49
+ $slots: S;
50
+ };
51
+ };
@@ -1,8 +1,19 @@
1
1
  type __VLS_Props = {
2
2
  data: any;
3
- hoveredNodeId: string | null;
4
3
  selected?: boolean;
5
4
  };
6
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
+ declare var __VLS_8: {
6
+ data: any;
7
+ };
8
+ type __VLS_Slots = {} & {
9
+ default?: (props: typeof __VLS_8) => any;
10
+ };
11
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
13
  declare const _default: typeof __VLS_export;
8
14
  export default _default;
15
+ type __VLS_WithSlots<T, S> = T & {
16
+ new (): {
17
+ $slots: S;
18
+ };
19
+ };
@@ -1,79 +1,75 @@
1
1
  <script setup>
2
- import { ref, computed, onMounted, onBeforeUnmount } from "vue";
2
+ import { computed } from "vue";
3
3
  import { Handle } from "@vue-flow/core";
4
- import { FLOW_HANDLES } from "#v/constants";
4
+ import { FLOW_RESIZE_HANDLES, GRID_SIZE } from "#v/constants";
5
+ import { useFlowNode } from "#v/composables";
5
6
  const props = defineProps({
6
7
  data: { type: null, required: true },
7
- hoveredNodeId: { type: [String, null], required: true },
8
8
  selected: { type: Boolean, required: false }
9
9
  });
10
- const nodeRef = ref(null);
11
- const mousePosition = ref({ x: 0, y: 0 });
12
- const PROXIMITY_THRESHOLD = 50;
13
- const borderColor = computed(
14
- () => props.selected ? "var(--ui-primary)" : "var(--ui-border-default)"
15
- );
16
- const isNearby = computed(() => {
17
- if (!nodeRef.value) return false;
18
- const rect = nodeRef.value.getBoundingClientRect();
19
- const mouseX = mousePosition.value.x;
20
- const mouseY = mousePosition.value.y;
21
- const dx = Math.max(rect.left - mouseX, 0, mouseX - rect.right);
22
- const dy = Math.max(rect.top - mouseY, 0, mouseY - rect.bottom);
23
- const distance = Math.sqrt(dx * dx + dy * dy);
24
- return distance <= PROXIMITY_THRESHOLD;
10
+ const {
11
+ nodeRef,
12
+ isHoveredLocal,
13
+ borderColor,
14
+ activeHandles,
15
+ handleStyle
16
+ } = useFlowNode({
17
+ data: computed(() => props.data),
18
+ selected: computed(() => props.selected ?? false)
25
19
  });
26
- const isHovered = computed(() => props.hoveredNodeId === String(props.data.id));
27
- const showHandles = computed(() => isHovered.value || isNearby.value);
28
- const handleGlobalMouseMove = (e) => {
29
- mousePosition.value = { x: e.clientX, y: e.clientY };
20
+ const setNodeRef = (el) => {
21
+ nodeRef.value = el instanceof HTMLElement ? el : null;
30
22
  };
31
- onMounted(() => {
32
- window.addEventListener("mousemove", handleGlobalMouseMove);
33
- });
34
- onBeforeUnmount(() => {
35
- window.removeEventListener("mousemove", handleGlobalMouseMove);
36
- });
37
23
  </script>
38
24
 
39
25
  <template>
40
26
  <div
41
- ref="nodeRef"
42
- class="bg-background border rounded-md px-3 py-2 relative flex"
27
+ :ref="setNodeRef"
28
+ class="bg-background border relative flex"
43
29
  :style="{
44
- width: data.width ? `${data.width}px` : '128px',
30
+ boxSizing: 'border-box',
31
+ width: data.width ? `${data.width}px` : GRID_SIZE * 6 + 'px',
45
32
  height: data.height ? `${data.height}px` : 'auto',
46
- minWidth: '128px',
33
+ minWidth: GRID_SIZE * 2 + 'px',
34
+ minHeight: GRID_SIZE * 2 + 'px',
47
35
  borderWidth: data.borderWidth ? `${data.borderWidth}px` : '2px',
48
36
  borderStyle: 'solid',
49
- borderColor
37
+ borderColor,
38
+ borderRadius: data.borderRadius !== void 0 ? `${data.borderRadius}px` : '6px',
39
+ ...data.bgColor ? { backgroundColor: data.bgColor } : {},
40
+ ...data.fontColor ? { color: data.fontColor } : {},
41
+ fontSize: data.fontSize ? `${data.fontSize}px` : '14px'
50
42
  }"
51
- @mouseenter="data.onMouseEnter?.()"
52
- @mouseleave="data.onMouseLeave?.()"
53
- @mousemove="(e) => data.onMouseMove?.(e, e.currentTarget)"
43
+ @mouseenter="isHoveredLocal = true"
44
+ @mouseleave="isHoveredLocal = false"
54
45
  @dblclick="data.onEdit?.()"
55
46
  >
56
- <!-- 连接点 - 可以作为 source target -->
47
+ <!-- Connection handles (z-index 高于 resize handles,优先响应连线拖拽) -->
57
48
  <Handle
58
- v-for="handle in FLOW_HANDLES"
49
+ v-for="handle in activeHandles"
59
50
  :id="`${handle.id}`"
60
51
  :key="`${handle.id}`"
61
52
  type="source"
62
53
  :position="handle.position"
63
- :style="{
64
- left: handle.offsetPercent?.x !== void 0 ? `${handle.offsetPercent.x}%` : void 0,
65
- top: handle.offsetPercent?.y !== void 0 ? `${handle.offsetPercent.y}%` : void 0,
66
- pointerEvents: 'all',
67
- opacity: showHandles ? 1 : 0,
68
- transition: 'opacity 0.2s',
69
- width: '6px',
70
- height: '6px'
71
- }"
54
+ :style="handleStyle(handle)"
72
55
  @mousedown.stop
73
56
  />
74
57
 
58
+ <!-- content -->
75
59
  <div class="flex items-center justify-center gap-2 w-full">
76
- <span class="text-sm font-medium">{{ data.name }}</span>
60
+ <slot :data="data">
61
+ <span class="font-medium">{{ data.name }}</span>
62
+ </slot>
77
63
  </div>
64
+
65
+ <!-- Resize handles (z-index 低于 connection handles,连线优先) -->
66
+ <div
67
+ v-for="rh in FLOW_RESIZE_HANDLES"
68
+ :key="rh.edge"
69
+ class="absolute nodrag"
70
+ :class="rh.class"
71
+ :style="{ zIndex: rh.zIndex, cursor: rh.cursor }"
72
+ @mousedown.stop.prevent="data.onResizeStart?.($event, rh.edge)"
73
+ />
78
74
  </div>
79
75
  </template>
@@ -1,8 +1,19 @@
1
1
  type __VLS_Props = {
2
2
  data: any;
3
- hoveredNodeId: string | null;
4
3
  selected?: boolean;
5
4
  };
6
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
+ declare var __VLS_8: {
6
+ data: any;
7
+ };
8
+ type __VLS_Slots = {} & {
9
+ default?: (props: typeof __VLS_8) => any;
10
+ };
11
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
13
  declare const _default: typeof __VLS_export;
8
14
  export default _default;
15
+ type __VLS_WithSlots<T, S> = T & {
16
+ new (): {
17
+ $slots: S;
18
+ };
19
+ };
@@ -1,13 +1,49 @@
1
+ import type { FlowEdgeStrokeType, FlowEdgePathType, FlowArrowType } from '#v/constants';
2
+ import type { FlowColorMode } from '#v/composables/flow/useFlowStyles';
1
3
  type __VLS_Props = {
2
4
  onAddNode?: () => void;
5
+ /** 是否有 API 操作正在进行,用于禁用交互 */
6
+ loading?: boolean;
3
7
  edgeStrokeWidth?: number;
4
- edgeMarkerStart?: boolean;
5
- edgeMarkerEnd?: boolean;
8
+ edgeStrokeType?: FlowEdgeStrokeType;
9
+ edgePathType?: FlowEdgePathType;
10
+ edgeMarkerStart?: FlowArrowType;
11
+ edgeMarkerEnd?: FlowArrowType;
12
+ edgeAnimated?: boolean;
13
+ edgeColor?: string;
14
+ edgeLabelColor?: string;
6
15
  nodeBorderWidth?: number;
7
- onEdgeStrokeWidthChange?: (width: number) => void;
8
- onToggleEdgeMarkerStart?: () => void;
9
- onToggleEdgeMarkerEnd?: () => void;
16
+ nodeBorderRadius?: number;
17
+ nodeBorderColor?: string;
18
+ nodeBgColor?: string;
19
+ nodeFontColor?: string;
20
+ nodeFontSize?: number;
21
+ nodeHandleSize?: number;
22
+ nodeHandleColor?: string;
23
+ /** 颜色模式 */
24
+ colorMode?: FlowColorMode;
25
+ /** 统一颜色名称 */
26
+ unifiedColor?: string;
27
+ /** 是否统一模式 */
28
+ isUnifiedMode?: boolean;
29
+ onEdgeStrokeWidthChange: (width: number) => void;
30
+ onEdgeStrokeTypeChange?: (type: FlowEdgeStrokeType) => void;
31
+ onEdgePathTypeChange?: (type: FlowEdgePathType) => void;
32
+ onEdgeMarkerStartChange?: (type: FlowArrowType) => void;
33
+ onEdgeMarkerEndChange?: (type: FlowArrowType) => void;
34
+ onToggleEdgeAnimated?: () => void;
35
+ onEdgeColorChange?: (color: string) => void;
36
+ onEdgeLabelColorChange?: (color: string) => void;
10
37
  onNodeBorderWidthChange?: (width: number) => void;
38
+ onNodeBorderRadiusChange?: (radius: number) => void;
39
+ onNodeBorderColorChange?: (color: string) => void;
40
+ onNodeBgColorChange?: (color: string) => void;
41
+ onNodeFontColorChange?: (color: string) => void;
42
+ onNodeFontSizeChange?: (size: number) => void;
43
+ onNodeHandleSizeChange?: (size: number) => void;
44
+ onNodeHandleColorChange?: (color: string) => void;
45
+ onColorModeChange?: (mode: FlowColorMode) => void;
46
+ onUnifiedColorChange?: (name: string) => void;
11
47
  };
12
48
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
49
  declare const _default: typeof __VLS_export;