@wzyjs/uis 0.3.29 → 0.3.31

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 (222) hide show
  1. package/dist/advanced/Com2Canvas/index.d.ts +8 -0
  2. package/dist/advanced/Com2Canvas/index.js +39 -0
  3. package/dist/advanced/Crud/components/CardList/index.d.ts +2 -0
  4. package/dist/advanced/Crud/components/CardList/index.js +90 -0
  5. package/dist/advanced/Crud/components/CreateUpdate/index.d.ts +2 -0
  6. package/dist/advanced/Crud/components/CreateUpdate/index.js +78 -0
  7. package/dist/advanced/Crud/components/ListTabs/index.d.ts +8 -0
  8. package/dist/advanced/Crud/components/ListTabs/index.js +7 -0
  9. package/dist/advanced/Crud/components/Provider/index.d.ts +7 -0
  10. package/dist/advanced/Crud/components/Provider/index.js +42 -0
  11. package/dist/advanced/Crud/components/QuickFilters/index.d.ts +8 -0
  12. package/dist/advanced/Crud/components/QuickFilters/index.js +20 -0
  13. package/dist/advanced/Crud/components/Remove/index.d.ts +2 -0
  14. package/dist/advanced/Crud/components/Remove/index.js +18 -0
  15. package/dist/advanced/Crud/components/index.d.ts +6 -0
  16. package/dist/advanced/Crud/components/index.js +6 -0
  17. package/dist/advanced/Crud/hooks/index.d.ts +5 -0
  18. package/dist/advanced/Crud/hooks/index.js +5 -0
  19. package/dist/advanced/Crud/hooks/useColumns.d.ts +11 -0
  20. package/dist/advanced/Crud/hooks/useColumns.js +111 -0
  21. package/dist/advanced/Crud/hooks/useList.d.ts +12 -0
  22. package/dist/advanced/Crud/hooks/useList.js +53 -0
  23. package/dist/advanced/Crud/hooks/useListFilters.d.ts +11 -0
  24. package/dist/advanced/Crud/hooks/useListFilters.js +159 -0
  25. package/dist/advanced/Crud/hooks/useOrderable.d.ts +15 -0
  26. package/dist/advanced/Crud/hooks/useOrderable.js +75 -0
  27. package/dist/advanced/Crud/hooks/useRequest.d.ts +13 -0
  28. package/dist/advanced/Crud/hooks/useRequest.js +27 -0
  29. package/dist/advanced/Crud/index.d.ts +3 -0
  30. package/dist/advanced/Crud/index.js +46 -0
  31. package/dist/advanced/Crud/types/index.d.ts +176 -0
  32. package/dist/advanced/Crud/types/index.js +1 -0
  33. package/dist/advanced/Crud/utils/index.d.ts +7 -0
  34. package/dist/advanced/Crud/utils/index.js +80 -0
  35. package/dist/advanced/Crud/utils/query.d.ts +3 -0
  36. package/dist/advanced/Crud/utils/query.js +34 -0
  37. package/dist/advanced/MindMap/context.d.ts +12 -0
  38. package/dist/advanced/MindMap/context.js +12 -0
  39. package/dist/advanced/MindMap/hooks/useAlignmentSnap.d.ts +15 -0
  40. package/dist/advanced/MindMap/hooks/useAlignmentSnap.js +164 -0
  41. package/dist/advanced/MindMap/hooks/useCopyPaste.d.ts +11 -0
  42. package/dist/advanced/MindMap/hooks/useCopyPaste.js +209 -0
  43. package/dist/advanced/MindMap/hooks/useDropToReparent.d.ts +21 -0
  44. package/dist/advanced/MindMap/hooks/useDropToReparent.js +216 -0
  45. package/dist/advanced/MindMap/hooks/useExpandCollapse.d.ts +18 -0
  46. package/dist/advanced/MindMap/hooks/useExpandCollapse.js +108 -0
  47. package/dist/advanced/MindMap/hooks/useMoveDescendants.d.ts +12 -0
  48. package/dist/advanced/MindMap/hooks/useMoveDescendants.js +98 -0
  49. package/dist/advanced/MindMap/hooks/useUndoRedo.d.ts +14 -0
  50. package/dist/advanced/MindMap/hooks/useUndoRedo.js +181 -0
  51. package/dist/advanced/MindMap/index.d.ts +29 -0
  52. package/dist/advanced/MindMap/index.js +52 -0
  53. package/dist/advanced/index.d.ts +5 -0
  54. package/dist/advanced/index.js +5 -0
  55. package/dist/antd/index.d.ts +6 -0
  56. package/dist/antd/index.js +5 -0
  57. package/dist/buttons/ButtonGroup/index.d.ts +8 -0
  58. package/dist/buttons/ButtonGroup/index.js +13 -0
  59. package/dist/buttons/ConfirmButton/index.d.ts +5 -0
  60. package/dist/buttons/ConfirmButton/index.js +9 -0
  61. package/dist/buttons/CopyButton/index.d.ts +6 -0
  62. package/dist/buttons/CopyButton/index.js +26 -0
  63. package/dist/buttons/DrawerButton/index.d.ts +6 -0
  64. package/dist/buttons/DrawerButton/index.js +13 -0
  65. package/dist/buttons/ProgressButton/index.css +63 -0
  66. package/dist/buttons/ProgressButton/index.d.ts +17 -0
  67. package/dist/buttons/ProgressButton/index.js +31 -0
  68. package/dist/buttons/SectorButton/index.d.ts +20 -0
  69. package/dist/buttons/SectorButton/index.js +130 -0
  70. package/dist/buttons/index.d.ts +6 -0
  71. package/dist/buttons/index.js +6 -0
  72. package/dist/display/CodeView/index.d.ts +26 -0
  73. package/dist/display/CodeView/index.js +60 -0
  74. package/dist/display/EnumTag/index.d.ts +12 -0
  75. package/dist/display/EnumTag/index.js +10 -0
  76. package/dist/display/HtmlDataRenderer/index.d.ts +6 -0
  77. package/dist/display/HtmlDataRenderer/index.js +15 -0
  78. package/dist/display/HtmlView/index.d.ts +6 -0
  79. package/dist/display/HtmlView/index.js +6 -0
  80. package/dist/display/IframePro/index.d.ts +8 -0
  81. package/dist/display/IframePro/index.js +24 -0
  82. package/dist/display/JsonSchemaRenderer/index.d.ts +11 -0
  83. package/dist/display/JsonSchemaRenderer/index.js +62 -0
  84. package/dist/display/JsonView/index.d.ts +3 -0
  85. package/dist/display/JsonView/index.js +7 -0
  86. package/dist/display/MarkdownView/index.d.ts +7 -0
  87. package/dist/display/MarkdownView/index.js +80 -0
  88. package/dist/display/MarkdownView/style.d.ts +1 -0
  89. package/{src/components/Markdown/style.ts → dist/display/MarkdownView/style.js} +1 -1
  90. package/dist/display/VideoPro/index.d.ts +9 -0
  91. package/dist/display/VideoPro/index.js +15 -0
  92. package/dist/display/index.d.ts +9 -0
  93. package/dist/display/index.js +9 -0
  94. package/dist/inputs/CheckboxButton/index.css +22 -0
  95. package/dist/inputs/CheckboxButton/index.d.ts +12 -0
  96. package/dist/inputs/CheckboxButton/index.js +9 -0
  97. package/dist/inputs/DateSwitcher/index.css +10 -0
  98. package/dist/inputs/DateSwitcher/index.d.ts +8 -0
  99. package/dist/inputs/DateSwitcher/index.js +29 -0
  100. package/dist/inputs/FetchSelect/index.d.ts +3 -0
  101. package/dist/inputs/FetchSelect/index.js +121 -0
  102. package/dist/inputs/FetchSelect/types.d.ts +33 -0
  103. package/dist/inputs/FetchSelect/types.js +1 -0
  104. package/dist/inputs/FetchSelect/utils.d.ts +21 -0
  105. package/dist/inputs/FetchSelect/utils.js +67 -0
  106. package/dist/inputs/FileUploader/index.d.ts +22 -0
  107. package/dist/inputs/FileUploader/index.js +79 -0
  108. package/dist/inputs/IconSelect/index.d.ts +89 -0
  109. package/dist/inputs/IconSelect/index.js +54 -0
  110. package/dist/inputs/ImageUploader/index.d.ts +12 -0
  111. package/dist/inputs/ImageUploader/index.js +192 -0
  112. package/dist/inputs/RadioButton/index.d.ts +15 -0
  113. package/dist/inputs/RadioButton/index.js +11 -0
  114. package/dist/inputs/RangeInput/index.d.ts +8 -0
  115. package/dist/inputs/RangeInput/index.js +17 -0
  116. package/dist/inputs/TextInput/index.d.ts +6 -0
  117. package/dist/inputs/TextInput/index.js +30 -0
  118. package/dist/inputs/index.d.ts +9 -0
  119. package/dist/inputs/index.js +9 -0
  120. package/dist/layout/DragSort/index.d.ts +16 -0
  121. package/dist/layout/DragSort/index.js +12 -0
  122. package/dist/layout/FoldCard/index.d.ts +9 -0
  123. package/dist/layout/FoldCard/index.js +69 -0
  124. package/dist/layout/PageBase/index.d.ts +6 -0
  125. package/dist/layout/PageBase/index.js +6 -0
  126. package/dist/layout/ResizableGridLayout/index.d.ts +11 -0
  127. package/dist/layout/ResizableGridLayout/index.js +13 -0
  128. package/dist/layout/SideMenu/index.d.ts +27 -0
  129. package/dist/layout/SideMenu/index.js +40 -0
  130. package/dist/layout/TabsPro/index.d.ts +9 -0
  131. package/dist/layout/TabsPro/index.js +87 -0
  132. package/dist/layout/index.d.ts +6 -0
  133. package/dist/layout/index.js +6 -0
  134. package/dist/web.css +363 -0
  135. package/dist/web.d.ts +7 -0
  136. package/dist/web.js +7 -0
  137. package/package.json +34 -12
  138. package/src/antd/form/CheckboxButton/index.module.scss +0 -24
  139. package/src/antd/form/CheckboxButton/index.tsx +0 -31
  140. package/src/antd/form/FileUploader/index.tsx +0 -163
  141. package/src/antd/form/RadioButton/index.tsx +0 -32
  142. package/src/antd/form/Upload/index.tsx +0 -65
  143. package/src/antd/form/UploadImage/index.tsx +0 -338
  144. package/src/antd/form/index.ts +0 -6
  145. package/src/antd/index.ts +0 -46
  146. package/src/antd/pro/FoldCard/index.tsx +0 -131
  147. package/src/antd/pro/RangeInput/index.tsx +0 -46
  148. package/src/antd/pro/Tabs/index.tsx +0 -135
  149. package/src/antd/pro/Typography/components/String.tsx +0 -72
  150. package/src/antd/pro/Typography/index.tsx +0 -9
  151. package/src/antd/pro/buttons/ButtonGroup.tsx +0 -26
  152. package/src/antd/pro/buttons/ConfirmButton.tsx +0 -24
  153. package/src/antd/pro/buttons/CopyButton.tsx +0 -47
  154. package/src/antd/pro/buttons/DrawerButton.tsx +0 -37
  155. package/src/antd/pro/buttons/index.tsx +0 -4
  156. package/src/antd/pro/index.ts +0 -5
  157. package/src/components/BottomBar/index.tsx +0 -28
  158. package/src/components/CodeView/index.tsx +0 -85
  159. package/src/components/Collapse/index.tsx +0 -26
  160. package/src/components/Com2Canvas/index.tsx +0 -60
  161. package/src/components/CompileHtml/index.tsx +0 -26
  162. package/src/components/Crud/components/CardList/index.tsx +0 -174
  163. package/src/components/Crud/components/CreateUpdate/index.tsx +0 -179
  164. package/src/components/Crud/components/Provider/index.tsx +0 -83
  165. package/src/components/Crud/components/Remove/index.tsx +0 -56
  166. package/src/components/Crud/components/index.ts +0 -4
  167. package/src/components/Crud/hooks/index.ts +0 -4
  168. package/src/components/Crud/hooks/useColumns.tsx +0 -169
  169. package/src/components/Crud/hooks/useList.ts +0 -65
  170. package/src/components/Crud/hooks/useOrderable.tsx +0 -107
  171. package/src/components/Crud/hooks/useRequest.ts +0 -41
  172. package/src/components/Crud/index.tsx +0 -91
  173. package/src/components/Crud/types/index.ts +0 -188
  174. package/src/components/Crud/utils/index.ts +0 -87
  175. package/src/components/DateSwitcher/index.module.scss +0 -10
  176. package/src/components/DateSwitcher/index.tsx +0 -75
  177. package/src/components/DownloadLink/index.tsx +0 -36
  178. package/src/components/DragSort/index.tsx +0 -77
  179. package/src/components/DynamicSelect/index.tsx +0 -76
  180. package/src/components/DynamicSelect/types.ts +0 -8
  181. package/src/components/DynamicSelect/utils.ts +0 -47
  182. package/src/components/EnumTag/index.tsx +0 -24
  183. package/src/components/FetchSelect/index.tsx +0 -57
  184. package/src/components/FormPro/index.tsx +0 -28
  185. package/src/components/GroupLayout/index.tsx +0 -45
  186. package/src/components/HtmlPro/index.tsx +0 -18
  187. package/src/components/IframePro/index.tsx +0 -52
  188. package/src/components/JsonRenderer/index.tsx +0 -114
  189. package/src/components/JsonView/index.tsx +0 -21
  190. package/src/components/Markdown/index.tsx +0 -152
  191. package/src/components/MindMap/context.tsx +0 -29
  192. package/src/components/MindMap/hooks/useAlignmentSnap.ts +0 -220
  193. package/src/components/MindMap/hooks/useCopyPaste.ts +0 -272
  194. package/src/components/MindMap/hooks/useDropToReparent.ts +0 -288
  195. package/src/components/MindMap/hooks/useExpandCollapse.ts +0 -146
  196. package/src/components/MindMap/hooks/useMoveDescendants.ts +0 -136
  197. package/src/components/MindMap/hooks/useUndoRedo.ts +0 -232
  198. package/src/components/MindMap/index.tsx +0 -117
  199. package/src/components/MultiImageDisplay/index.tsx +0 -63
  200. package/src/components/ProgressButton/index.module.scss +0 -65
  201. package/src/components/ProgressButton/index.tsx +0 -96
  202. package/src/components/SectorButton/index.tsx +0 -247
  203. package/src/components/TextInput/index.tsx +0 -61
  204. package/src/components/TimelineBar/components/CurrentWeekHighlight/index.tsx +0 -64
  205. package/src/components/TimelineBar/components/Guides/index.tsx +0 -61
  206. package/src/components/TimelineBar/components/Ticks/index.tsx +0 -56
  207. package/src/components/TimelineBar/components/TodayIndicator/index.tsx +0 -54
  208. package/src/components/TimelineBar/components/index.ts +0 -4
  209. package/src/components/TimelineBar/const.ts +0 -3
  210. package/src/components/TimelineBar/hooks/index.ts +0 -5
  211. package/src/components/TimelineBar/hooks/useHighlightRange.ts +0 -21
  212. package/src/components/TimelineBar/hooks/useMonthGuides.ts +0 -40
  213. package/src/components/TimelineBar/hooks/useTickValues.ts +0 -18
  214. package/src/components/TimelineBar/hooks/useVisibleRange.ts +0 -43
  215. package/src/components/TimelineBar/hooks/useWeekGuides.ts +0 -39
  216. package/src/components/TimelineBar/index.tsx +0 -63
  217. package/src/components/TimelineBar/utils.ts +0 -27
  218. package/src/components/Video/index.tsx +0 -37
  219. package/src/components/index.ts +0 -26
  220. package/src/rn.ts +0 -1
  221. package/src/rns/index.ts +0 -0
  222. package/src/web.ts +0 -2
@@ -1,136 +0,0 @@
1
- 'use client'
2
-
3
- import { useCallback, useMemo } from 'react'
4
-
5
- import type { Edge, Node, NodeChange } from '@xyflow/react'
6
-
7
- interface UseMoveDescendantsParams<TNodeData extends Record<string, unknown>> {
8
- // 开关:关闭时只透传,不联动后代
9
- enabled?: boolean
10
- // 当前节点与边(用于计算父子关系)
11
- nodes: Array<Node<TNodeData>>
12
- edges: Edge[]
13
- // 透传给 ReactFlow 的 onNodesChange(通常来自 useNodesState)
14
- onNodesChange?: (changes: Array<NodeChange<Node<TNodeData>>>) => void
15
- }
16
-
17
- interface UseMoveDescendantsResult<TNodeData extends Record<string, unknown>> {
18
- // 包装后的 onNodesChange:在 position change 上把位移叠加到后代节点
19
- onNodesChange: (changes: Array<NodeChange<Node<TNodeData>>>) => void
20
- }
21
-
22
- const getDescendants = (sourceToTargets: Map<string, string[]>, rootId: string): Set<string> => {
23
- const visited = new Set<string>([rootId])
24
- const result = new Set<string>()
25
- const queue: string[] = [rootId]
26
-
27
- while (queue.length > 0) {
28
- const currentId = queue.shift()
29
- if (!currentId) {
30
- continue
31
- }
32
- const targets = sourceToTargets.get(currentId) ?? []
33
- for (const targetId of targets) {
34
- if (visited.has(targetId)) {
35
- continue
36
- }
37
- visited.add(targetId)
38
- result.add(targetId)
39
- queue.push(targetId)
40
- }
41
- }
42
-
43
- return result
44
- }
45
-
46
- export const useMoveDescendants = <TNodeData extends Record<string, unknown>,>(
47
- params: UseMoveDescendantsParams<TNodeData>,
48
- ): UseMoveDescendantsResult<TNodeData> => {
49
- const { enabled = true, nodes, edges, onNodesChange: onNodesChangeExternal } = params
50
-
51
- // 用 edge.source -> edge.target 作为父子关系(默认把 source 当作父节点)
52
- const sourceToTargets = useMemo((): Map<string, string[]> => {
53
- const map = new Map<string, string[]>()
54
- edges.forEach(edge => {
55
- const prev = map.get(edge.source) ?? []
56
- map.set(edge.source, [...prev, edge.target])
57
- })
58
- return map
59
- }, [edges])
60
-
61
- const onNodesChange = useCallback((changes: Array<NodeChange<Node<TNodeData>>>): void => {
62
- if (!onNodesChangeExternal) {
63
- return
64
- }
65
-
66
- if (!enabled || edges.length === 0) {
67
- onNodesChangeExternal(changes)
68
- return
69
- }
70
-
71
- // 用旧节点位置计算拖拽的 dx/dy,再把位移叠加到后代节点
72
- const nodeMap = new Map<string, Node<TNodeData>>(nodes.map(node => [node.id, node]))
73
- const changedIdSet = new Set<string>(
74
- changes.filter(change => change.type === 'position').map(change => change.id),
75
- )
76
-
77
- const deltaMap = new Map<string, { dx: number, dy: number, dragging: boolean }>()
78
-
79
- changes.forEach(change => {
80
- if (change.type !== 'position' || !change.position) {
81
- return
82
- }
83
- const prev = nodeMap.get(change.id)
84
- if (!prev) {
85
- return
86
- }
87
-
88
- const dx = change.position.x - prev.position.x
89
- const dy = change.position.y - prev.position.y
90
- if (dx === 0 && dy === 0) {
91
- return
92
- }
93
-
94
- const dragging = change.dragging === true
95
- // 只影响“未被本次 change 显式更新”的节点,避免和多选拖拽冲突
96
- const descendants = getDescendants(sourceToTargets, change.id)
97
- descendants.forEach(descId => {
98
- if (changedIdSet.has(descId)) {
99
- return
100
- }
101
- const prevDelta = deltaMap.get(descId)
102
- if (!prevDelta) {
103
- deltaMap.set(descId, { dx, dy, dragging })
104
- return
105
- }
106
- deltaMap.set(descId, { dx: prevDelta.dx + dx, dy: prevDelta.dy + dy, dragging: prevDelta.dragging || dragging })
107
- })
108
- })
109
-
110
- if (deltaMap.size === 0) {
111
- onNodesChangeExternal(changes)
112
- return
113
- }
114
-
115
- const extraChanges: Array<NodeChange<Node<TNodeData>>> = []
116
- deltaMap.forEach((delta, nodeId) => {
117
- const node = nodeMap.get(nodeId)
118
- if (!node) {
119
- return
120
- }
121
- extraChanges.push({
122
- type: 'position',
123
- id: nodeId,
124
- position: {
125
- x: node.position.x + delta.dx,
126
- y: node.position.y + delta.dy,
127
- },
128
- dragging: delta.dragging,
129
- })
130
- })
131
-
132
- onNodesChangeExternal([...changes, ...extraChanges])
133
- }, [edges.length, enabled, nodes, onNodesChangeExternal, sourceToTargets])
134
-
135
- return { onNodesChange }
136
- }
@@ -1,232 +0,0 @@
1
- 'use client'
2
-
3
- import { useCallback, useEffect, useMemo, useRef } from 'react'
4
- import type { Edge, EdgeChange, Node, NodeChange } from '@xyflow/react'
5
-
6
- interface Snapshot<TNodeData extends Record<string, unknown>> {
7
- nodes: Array<Node<TNodeData>>
8
- edges: Edge[]
9
- }
10
-
11
- interface UseUndoRedoParams<TNodeData extends Record<string, unknown>> {
12
- enabled?: boolean
13
- nodes: Array<Node<TNodeData>>
14
- edges: Edge[]
15
- onNodesChange?: (changes: Array<NodeChange<Node<TNodeData>>>) => void
16
- onEdgesChange?: (changes: Array<EdgeChange<Edge>>) => void
17
- }
18
-
19
- interface UseUndoRedoResult<TNodeData extends Record<string, unknown>> {
20
- onNodesChange: (changes: Array<NodeChange<Node<TNodeData>>>) => void
21
- onEdgesChange: (changes: Array<EdgeChange<Edge>>) => void
22
- }
23
-
24
- const clone = <T,>(value: T): T => {
25
- const anyGlobal = globalThis as unknown as { structuredClone?: <V>(v: V) => V }
26
- if (typeof anyGlobal.structuredClone === 'function') {
27
- return anyGlobal.structuredClone(value)
28
- }
29
- return JSON.parse(JSON.stringify(value)) as T
30
- }
31
-
32
- const isEditableTarget = (target: EventTarget | null): boolean => {
33
- const el = target as HTMLElement | null
34
- if (!el) {
35
- return false
36
- }
37
- const tag = el.tagName?.toLowerCase()
38
- if (tag === 'input' || tag === 'textarea') {
39
- return true
40
- }
41
- return el.isContentEditable
42
- }
43
-
44
- const buildNodeChanges = <TNodeData extends Record<string, unknown>,>(
45
- current: Array<Node<TNodeData>>,
46
- next: Array<Node<TNodeData>>,
47
- ): Array<NodeChange<Node<TNodeData>>> => {
48
- const currentById = new Map(current.map(n => [n.id, n]))
49
- const nextById = new Map(next.map(n => [n.id, n]))
50
-
51
- const changes: Array<NodeChange<Node<TNodeData>>> = []
52
- current.forEach(node => {
53
- if (!nextById.has(node.id)) {
54
- changes.push({ type: 'remove', id: node.id })
55
- }
56
- })
57
- next.forEach(node => {
58
- if (!currentById.has(node.id)) {
59
- changes.push({ type: 'add', item: clone(node) })
60
- return
61
- }
62
- changes.push({ type: 'replace', id: node.id, item: clone(node) })
63
- })
64
- return changes
65
- }
66
-
67
- const buildEdgeChanges = (current: Edge[], next: Edge[]): Array<EdgeChange<Edge>> => {
68
- const currentById = new Map(current.map(e => [e.id, e]))
69
- const nextById = new Map(next.map(e => [e.id, e]))
70
-
71
- const changes: Array<EdgeChange<Edge>> = []
72
- current.forEach(edge => {
73
- if (!nextById.has(edge.id)) {
74
- changes.push({ type: 'remove', id: edge.id })
75
- }
76
- })
77
- next.forEach(edge => {
78
- if (!currentById.has(edge.id)) {
79
- changes.push({ type: 'add', item: clone(edge) })
80
- return
81
- }
82
- changes.push({ type: 'replace', id: edge.id, item: clone(edge) })
83
- })
84
- return changes
85
- }
86
-
87
- export const useUndoRedo = <TNodeData extends Record<string, unknown>,>(
88
- params: UseUndoRedoParams<TNodeData>,
89
- ): UseUndoRedoResult<TNodeData> => {
90
- const { enabled = true, nodes, edges, onNodesChange, onEdgesChange } = params
91
-
92
- const snapshot = useMemo((): Snapshot<TNodeData> => {
93
- return { nodes: clone(nodes), edges: clone(edges) }
94
- }, [edges, nodes])
95
-
96
- const pastRef = useRef<Array<Snapshot<TNodeData>>>([])
97
- const futureRef = useRef<Array<Snapshot<TNodeData>>>([])
98
- const applyingRef = useRef<boolean>(false)
99
- const commitNextRef = useRef<boolean>(false)
100
-
101
- useEffect(() => {
102
- if (!enabled) {
103
- pastRef.current = []
104
- futureRef.current = []
105
- return
106
- }
107
- if (pastRef.current.length === 0) {
108
- pastRef.current = [snapshot]
109
- futureRef.current = []
110
- return
111
- }
112
- if (applyingRef.current) {
113
- return
114
- }
115
- if (!commitNextRef.current) {
116
- return
117
- }
118
- commitNextRef.current = false
119
- pastRef.current = [...pastRef.current, snapshot]
120
- futureRef.current = []
121
- }, [enabled, snapshot])
122
-
123
- const applySnapshot = useCallback((next: Snapshot<TNodeData>): void => {
124
- applyingRef.current = true
125
- commitNextRef.current = false
126
-
127
- const nodeChanges = onNodesChange ? buildNodeChanges(nodes, next.nodes) : []
128
- const edgeChanges = onEdgesChange ? buildEdgeChanges(edges, next.edges) : []
129
-
130
- if (nodeChanges.length > 0) {
131
- onNodesChange?.(nodeChanges)
132
- }
133
- if (edgeChanges.length > 0) {
134
- onEdgesChange?.(edgeChanges)
135
- }
136
-
137
- queueMicrotask(() => {
138
- applyingRef.current = false
139
- })
140
- }, [edges, nodes, onEdgesChange, onNodesChange])
141
-
142
- const undo = useCallback((): void => {
143
- const past = pastRef.current
144
- const current = past.at(-1)
145
- const prev = past.at(-2)
146
- if (!current || !prev) {
147
- return
148
- }
149
-
150
- pastRef.current = past.slice(0, -1)
151
- futureRef.current = [current, ...futureRef.current]
152
- applySnapshot(prev)
153
- }, [applySnapshot])
154
-
155
- const redo = useCallback((): void => {
156
- const next = futureRef.current.at(0)
157
- if (!next) {
158
- return
159
- }
160
-
161
- futureRef.current = futureRef.current.slice(1)
162
- pastRef.current = [...pastRef.current, next]
163
- applySnapshot(next)
164
- }, [applySnapshot])
165
-
166
- const onNodesChangeWrapped = useCallback((changes: Array<NodeChange<Node<TNodeData>>>): void => {
167
- onNodesChange?.(changes)
168
- if (!enabled) {
169
- return
170
- }
171
- const shouldCommit = changes.some(change => {
172
- if (change.type === 'position') {
173
- return change.dragging !== true
174
- }
175
- return change.type === 'add' || change.type === 'remove'
176
- })
177
- if (shouldCommit) {
178
- commitNextRef.current = true
179
- }
180
- }, [enabled, onNodesChange])
181
-
182
- const onEdgesChangeWrapped = useCallback((changes: Array<EdgeChange<Edge>>): void => {
183
- onEdgesChange?.(changes)
184
- if (!enabled) {
185
- return
186
- }
187
- const shouldCommit = changes.some(change => {
188
- return change.type === 'add' || change.type === 'remove'
189
- })
190
- if (shouldCommit) {
191
- commitNextRef.current = true
192
- }
193
- }, [enabled, onEdgesChange])
194
-
195
- useEffect(() => {
196
- if (!enabled) {
197
- return
198
- }
199
-
200
- const onKeyDown = (event: KeyboardEvent): void => {
201
- if (isEditableTarget(event.target)) {
202
- return
203
- }
204
-
205
- const isMac = /Mac|iPhone|iPad|iPod/.test(navigator.platform)
206
- const mod = isMac ? event.metaKey : event.ctrlKey
207
- if (!mod) {
208
- return
209
- }
210
- if (event.key.toLowerCase() !== 'z') {
211
- return
212
- }
213
-
214
- event.preventDefault()
215
- if (event.shiftKey) {
216
- redo()
217
- return
218
- }
219
- undo()
220
- }
221
-
222
- document.addEventListener('keydown', onKeyDown)
223
- return () => {
224
- document.removeEventListener('keydown', onKeyDown)
225
- }
226
- }, [enabled, redo, undo])
227
-
228
- return {
229
- onNodesChange: onNodesChangeWrapped,
230
- onEdgesChange: onEdgesChangeWrapped,
231
- }
232
- }
@@ -1,117 +0,0 @@
1
- 'use client'
2
-
3
- import type { ReactElement } from 'react'
4
-
5
- import { ReactFlow, type Edge, type EdgeChange, type EdgeTypes, type Node, type NodeChange, type NodeTypes } from '@xyflow/react'
6
- import '@xyflow/react/dist/style.css'
7
-
8
- import { useAlignmentSnap } from './hooks/useAlignmentSnap'
9
- import { useMoveDescendants } from './hooks/useMoveDescendants'
10
- import { useDropToReparent } from './hooks/useDropToReparent'
11
- import { useCopyPaste } from './hooks/useCopyPaste'
12
- import { useUndoRedo } from './hooks/useUndoRedo'
13
- import { useExpandCollapse } from './hooks/useExpandCollapse'
14
- import { MindMapDndProvider, useMindMapDndState } from './context'
15
-
16
- export interface MindMapNodeData extends Record<string, unknown> {
17
- label: string
18
- }
19
-
20
- export { useMindMapDndState, useExpandCollapse }
21
-
22
- interface MindMapProps {
23
- className?: string
24
- enableSnap?: boolean // 是否开启对齐线与自动吸附
25
- moveDescendants?: boolean // 是否拖动父节点时联动后代节点一起移动
26
- enableDropToNode?: boolean // 是否允许拖拽到节点上建立父子关系
27
- enableCopyPaste?: boolean // 是否开启复制粘贴
28
- enableUndoRedo?: boolean // 是否开启撤销重做
29
- dropHighlightClassName?: string // 可放下时的高亮样式
30
- canDropOnNode?: (params: { draggingNode: Node<MindMapNodeData>, targetNode: Node<MindMapNodeData> }) => boolean // 外部控制是否可放下
31
- nodeTypes?: NodeTypes
32
- edgeTypes?: EdgeTypes
33
- nodes: Array<Node<MindMapNodeData>>
34
- edges?: Edge[]
35
- onNodesChange?: (changes: Array<NodeChange<Node<MindMapNodeData>>>) => void
36
- onEdgesChange?: (changes: Array<EdgeChange<Edge>>) => void
37
- }
38
-
39
- export const MindMap = (props: MindMapProps): ReactElement => {
40
- const {
41
- nodes,
42
- edges = [],
43
- onNodesChange,
44
- onEdgesChange,
45
- enableSnap = false,
46
- moveDescendants = true,
47
- enableDropToNode = true,
48
- enableCopyPaste = true,
49
- enableUndoRedo = true,
50
- dropHighlightClassName,
51
- canDropOnNode,
52
- nodeTypes,
53
- edgeTypes,
54
- className = 'w-full h-full',
55
- } = props
56
-
57
- // 先把“联动后代移动”合并进节点变更回调,后续其它能力(如吸附)再基于它叠加
58
- const { onNodesChange: onNodesChangeWithDescendants } = useMoveDescendants<MindMapNodeData>({
59
- enabled: moveDescendants,
60
- nodes,
61
- edges,
62
- onNodesChange,
63
- })
64
-
65
- // 在节点变更回调上叠加对齐线与吸附逻辑,并由 hook 直接给出对齐线元素
66
- const { helperLines, onMove, onNodesChange: onNodesChangeWithSnap } = useAlignmentSnap<MindMapNodeData>({
67
- enabled: enableSnap,
68
- nodes,
69
- onNodesChange: onNodesChangeWithDescendants,
70
- })
71
-
72
- const { onNodesChange: onNodesChangeWithUndoRedo, onEdgesChange: onEdgesChangeWithUndoRedo } = useUndoRedo<MindMapNodeData>({
73
- enabled: enableUndoRedo,
74
- nodes,
75
- edges,
76
- onNodesChange: onNodesChangeWithSnap,
77
- onEdgesChange,
78
- })
79
-
80
- const { onNodeDrag, onNodeDragStop, draggingNodeId, dropTargetNodeId } = useDropToReparent<MindMapNodeData>({
81
- enabled: enableDropToNode,
82
- nodes,
83
- edges,
84
- dropHighlightClassName,
85
- canDropOnNode,
86
- onNodesChange: onNodesChangeWithUndoRedo,
87
- onEdgesChange: onEdgesChangeWithUndoRedo,
88
- })
89
-
90
- useCopyPaste<MindMapNodeData>({
91
- enabled: enableCopyPaste,
92
- nodes,
93
- edges,
94
- onNodesChange: onNodesChangeWithUndoRedo,
95
- onEdgesChange: onEdgesChangeWithUndoRedo,
96
- })
97
-
98
- return (
99
- <MindMapDndProvider value={{ draggingNodeId, dropTargetNodeId }}>
100
- <div className={`relative ${className}`}>
101
- <ReactFlow
102
- fitView
103
- nodes={nodes}
104
- edges={edges}
105
- nodeTypes={nodeTypes}
106
- edgeTypes={edgeTypes}
107
- onNodesChange={onNodesChangeWithUndoRedo}
108
- onEdgesChange={onEdgesChangeWithUndoRedo}
109
- onMove={enableSnap ? onMove : undefined}
110
- onNodeDrag={onNodeDrag}
111
- onNodeDragStop={onNodeDragStop}
112
- />
113
- {helperLines}
114
- </div>
115
- </MindMapDndProvider>
116
- )
117
- }
@@ -1,63 +0,0 @@
1
- 'use client'
2
-
3
- import React from 'react'
4
- import { Row, Col, Image } from 'antd'
5
-
6
- export const MultiImageDisplay = ({ images = [], preview = false }) => {
7
- const renderImages = () => {
8
- const count = images.length
9
-
10
- if (count === 1) {
11
- return (
12
- <Image src={images[0]} preview={preview} style={{ width: '100%', height: 'auto' }} />
13
- )
14
- }
15
-
16
- if (count === 2) {
17
- return (
18
- <Row gutter={8}>
19
- {images.map((img, index) => (
20
- <Col span={12} key={index}>
21
- <Image src={img} preview={preview} style={{ width: '100%', height: 'auto' }} />
22
- </Col>
23
- ))}
24
- </Row>
25
- )
26
- }
27
-
28
- if (count === 3) {
29
- return (
30
- <div>
31
- <Row gutter={8}>
32
- {images.slice(0, 2).map((img, index) => (
33
- <Col span={12} key={index}>
34
- <Image src={img} preview={preview} style={{ width: '100%', height: 'auto' }} />
35
- </Col>
36
- ))}
37
- </Row>
38
- <Row gutter={8} style={{ marginTop: '8px' }}>
39
- <Col span={24}>
40
- <Image src={images[2]} preview={preview} style={{ width: '100%', height: 'auto' }} />
41
- </Col>
42
- </Row>
43
- </div>
44
- )
45
- }
46
-
47
- if (count >= 4) {
48
- return (
49
- <Row>
50
- {images.map((img, index) => (
51
- <Col span={12} key={index}>
52
- <Image src={img} preview={preview} style={{ width: '100%', height: 'auto' }} />
53
- </Col>
54
- ))}
55
- </Row>
56
- )
57
- }
58
-
59
- return null
60
- }
61
-
62
- return <div>{renderImages()}</div>
63
- }
@@ -1,65 +0,0 @@
1
- .progressButton {
2
- @keyframes complete {
3
- 0% {
4
- transform: scale(1) rotateY(0deg);
5
- }
6
-
7
- 20% {
8
- transform: scale(0.9) rotateY(36deg);
9
- }
10
-
11
- 40% {
12
- transform: scale(0.95) rotateY(72deg);
13
- }
14
-
15
- 60% {
16
- transform: scale(1) rotateY(108deg);
17
- }
18
-
19
- 80% {
20
- transform: scale(1.05) rotateY(144deg);
21
- }
22
-
23
- 100% {
24
- transform: scale(1) rotateY(180deg);
25
- }
26
- }
27
-
28
- @keyframes counter-rotate {
29
- 0% {
30
- transform: rotateY(0deg);
31
- }
32
-
33
- 20% {
34
- transform: rotateY(-36deg);
35
- }
36
-
37
- 40% {
38
- transform: rotateY(-72deg);
39
- }
40
-
41
- 60% {
42
- transform: rotateY(-108deg);
43
- }
44
-
45
- 80% {
46
- transform: rotateY(-144deg);
47
- }
48
-
49
- 100% {
50
- transform: rotateY(-180deg);
51
- }
52
- }
53
-
54
- .animate-complete {
55
- animation: complete 0.6s cubic-bezier(0, 0, 1, 1);
56
- }
57
-
58
- .animate-counter-rotate {
59
- animation: counter-rotate 0.6s cubic-bezier(0, 0, 1, 1);
60
- }
61
-
62
- .perspective {
63
- perspective: 1000px;
64
- }
65
- }
@@ -1,96 +0,0 @@
1
- import { type ReactNode } from 'react'
2
- import styles from './index.module.scss'
3
-
4
- interface ProgressButtonProps {
5
- colors?: { bg: string, ring: string }
6
- showRing?: boolean
7
- progress?: number
8
- padding?: number
9
- size?: number
10
- strokeWidth?: number
11
- children?: ReactNode
12
- className?: string
13
- }
14
-
15
- export const ProgressButton = (props: ProgressButtonProps) => {
16
- const {
17
- colors, // 按钮颜色配置
18
- showRing = false, // 是否显示进度环
19
- progress = 0, // 进度值(0-1)
20
- padding = 0, // 内边距
21
- strokeWidth = 5, // 进度环宽度
22
- size = 50, // 按钮大小
23
- children, // 子元素
24
- className = '', // 自定义className
25
- } = props
26
-
27
- // 计算进度环的半径
28
- const radius = (size / 2) - strokeWidth - padding + 2.5
29
- // 计算进度环的周长
30
- const circumference = 2 * Math.PI * radius
31
- // 计算进度环的偏移量,用于显示进度
32
- const offset = circumference * (1 - progress)
33
-
34
- return (
35
- <div className={styles.progressButton}>
36
- <div
37
- style={{ width: size, height: size }}
38
- className={`relative rounded-full
39
- flex items-center justify-center
40
- cursor-pointer hover:opacity-90
41
- focus:outline-none focus:ring-2 focus:ring-offset-2
42
- ${colors?.bg}
43
- ${colors?.ring}
44
- transform-gpu transition-all duration-300
45
- perspective
46
- ${className}`}
47
- >
48
- {showRing && (
49
- <>
50
- <svg
51
- className='absolute inset-0 w-full h-full'
52
- viewBox={`0 0 ${size} ${size}`}
53
- >
54
- <circle
55
- cx={size / 2}
56
- cy={size / 2}
57
- r={radius}
58
- fill='none'
59
- stroke='currentColor'
60
- strokeWidth={strokeWidth}
61
- className='opacity-30'
62
- />
63
- </svg>
64
-
65
- <svg
66
- className='absolute inset-0 w-full h-full -rotate-90'
67
- viewBox={`0 0 ${size} ${size}`}
68
- >
69
- <circle
70
- cx={size / 2}
71
- cy={size / 2}
72
- r={radius}
73
- fill='none'
74
- stroke='currentColor'
75
- strokeWidth={strokeWidth}
76
- strokeDasharray={circumference}
77
- strokeDashoffset={offset}
78
- strokeLinecap='round'
79
- className='transition-all duration-300'
80
- />
81
- </svg>
82
- </>
83
- )}
84
-
85
- <div
86
- className={`
87
- relative z-10 text-white text-xs text-center whitespace-pre select-none
88
- ${className ? 'animate-counter-rotate' : ''}
89
- `}
90
- >
91
- {children}
92
- </div>
93
- </div>
94
- </div>
95
- )
96
- }