@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,114 +0,0 @@
1
- import React from 'react'
2
- import {
3
- Divider,
4
- Flex,
5
- Space,
6
- Typography,
7
- Steps,
8
- Tabs,
9
- Collapse,
10
- Descriptions,
11
- Image,
12
- List,
13
- Popover,
14
- Tooltip,
15
- Card,
16
- QRCode,
17
- Segmented,
18
- Table,
19
- Tag,
20
- Timeline,
21
- Tree,
22
- Alert,
23
- Progress,
24
- } from 'antd'
25
-
26
- const ComponentMap = {
27
- // 布局结构类
28
- Divider,
29
- Flex,
30
- Space,
31
-
32
- // 信息展示类
33
- Typography,
34
- 'Typography.Title': Typography.Title,
35
- 'Typography.Text': Typography.Text,
36
- 'Typography.Paragraph': Typography.Paragraph,
37
- 'Typography.Link': Typography.Link,
38
- Steps,
39
- Tabs,
40
- Collapse,
41
- 'Collapse.Panel': Collapse.Panel,
42
- Description: Descriptions,
43
- Image,
44
- List,
45
- Popover,
46
- Tooltip,
47
- Card,
48
- QRCode,
49
- Segmented,
50
- Table,
51
- Tag,
52
- Timeline,
53
- Tree,
54
- Alert,
55
- Progress,
56
- }
57
-
58
- export interface Content {
59
- component: keyof typeof ComponentMap // 对应 Ant Design 组件的枚举值
60
- props?: Record<string, any> // 对应组件的 props 配置
61
- children?: Content[] | string // 子节点,可递归嵌套,或直接是字符串
62
- }
63
-
64
- interface JsonRendererProps {
65
- content: Content[]
66
- }
67
-
68
- export const JsonRenderer = (props: JsonRendererProps) => {
69
- const { content } = props
70
-
71
- // 递归渲染组件的函数
72
- const renderContent = (item: Content | string) => {
73
- // 如果是字符串,直接返回
74
- if (typeof item === 'string') {
75
- return item
76
- }
77
-
78
- const { component, props = {}, children } = item
79
-
80
- // 获取对应的组件
81
- const Component = ComponentMap[component] as React.ComponentType<any>
82
-
83
- if (!Component) {
84
- return <Alert type='error' message={`未找到组件: ${component}`} />
85
- }
86
-
87
- // 处理子节点
88
- let childrenContent
89
- if (children) {
90
- if (Array.isArray(children)) {
91
- childrenContent = children.map((child, index) => (
92
- <React.Fragment key={index}>
93
- {renderContent(child)}
94
- </React.Fragment>
95
- ))
96
- } else {
97
- childrenContent = renderContent(children)
98
- }
99
- }
100
-
101
- // 渲染组件,传递 props 和 children
102
- return <Component {...props}>{childrenContent}</Component>
103
- }
104
-
105
- return (
106
- <>
107
- {content.map((item, index) => (
108
- <React.Fragment key={index}>
109
- {renderContent(item)}
110
- </React.Fragment>
111
- ))}
112
- </>
113
- )
114
- }
@@ -1,21 +0,0 @@
1
- 'use client'
2
-
3
- import React from 'react'
4
- import ReactJson, { ReactJsonViewProps } from 'react-json-view'
5
-
6
- export type JsonViewProps = ReactJsonViewProps
7
-
8
- export const JsonView = (props: JsonViewProps) => {
9
- const { style } = props
10
-
11
- return (
12
- <ReactJson
13
- enableClipboard={false}
14
- collapsed={true}
15
- displayObjectSize={false}
16
- displayDataTypes={false}
17
- {...props}
18
- style={{ overflow: 'auto', ...style }}
19
- />
20
- )
21
- }
@@ -1,152 +0,0 @@
1
- 'use client'
2
-
3
- import { useMemo } from 'react'
4
- import ReactMarkdown from 'react-markdown'
5
- import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
6
- import { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism'
7
- import remarkGfm from 'remark-gfm'
8
- import rehypeSlug from 'rehype-slug'
9
- import rehypeAutolinkHeadings from 'rehype-autolink-headings'
10
-
11
- import 'github-markdown-css/github-markdown-light.css'
12
- import { style } from './style'
13
-
14
- interface MarkdownProps {
15
- content: string
16
- showToc?: boolean // 是否显示目录
17
- }
18
-
19
- interface TocItem {
20
- id: string
21
- text: string
22
- level: number
23
- }
24
-
25
- export const Markdown = (props: MarkdownProps) => {
26
- const { content = '', showToc = true } = props
27
-
28
- // 提取标题生成目录
29
- const tocItems = useMemo(() => {
30
- if (!showToc) {
31
- return []
32
- }
33
-
34
- const lines = content.split('\n')
35
- const items: TocItem[] = []
36
-
37
- lines.forEach((line) => {
38
- const match = line.match(/^(#{2,4})\s+(.+)$/)
39
- if (match && match[1] && match[2]) {
40
- const level = match[1].length
41
- const text = match[2].trim()
42
- const id = text
43
- .toLowerCase()
44
- .replace(/[^\w\u4e00-\u9fa5\s-]/g, '') // 保留中文、英文、数字、空格和连字符
45
- .replace(/\s+/g, '-') // 空格替换为连字符
46
-
47
- items.push({ id, text, level })
48
- }
49
- })
50
-
51
- return items
52
- }, [content, showToc])
53
-
54
- // 渲染目录
55
- const renderToc = () => {
56
- if (!showToc || tocItems.length === 0) {
57
- return null
58
- }
59
-
60
- return (
61
- <div
62
- className='markdown-toc-container'
63
- style={{
64
- padding: '10px 20px 10px 0',
65
- backgroundColor: '#f8f9fa',
66
- borderLeft: '4px solid #1890ff',
67
- borderRadius: '4px',
68
- overflowY: 'auto',
69
- height: '100%'
70
- }}
71
- >
72
- <ul style={{ margin: 0, padding: 0 }}>
73
- {tocItems.map((item, index) => (
74
- <li
75
- key={index}
76
- style={{
77
- marginBottom: '4px',
78
- marginLeft: `${(item.level - 1) * 16}px`,
79
- listStyle: 'none',
80
- position: 'relative',
81
- }}
82
- >
83
- <a
84
- href={`#${item.id}`}
85
- style={{
86
- textDecoration: 'none',
87
- color: '#1890ff',
88
- fontSize: item.level <= 2 ? '14px' : '13px',
89
- fontWeight: item.level === 1 ? 600 : 400,
90
- }}
91
- onClick={(e) => {
92
- e.preventDefault()
93
- const element = document.getElementById(item.id)
94
- if (element) {
95
- element.scrollIntoView({ behavior: 'smooth' })
96
- }
97
- }}
98
- >
99
- {item.text}
100
- </a>
101
- </li>
102
- ))}
103
- </ul>
104
- </div>
105
- )
106
- }
107
-
108
- return (
109
- <div style={{ height: '100%' }}>
110
- <style>{style}</style>
111
- <div className='markdown-body markdown-toc' style={{ height: '100%', display: 'flex' }}>
112
- <div style={{ marginRight: 14 }}>
113
- {renderToc()}
114
- </div>
115
- <div style={{ overflow: 'auto', flex: 1 }}>
116
- <ReactMarkdown
117
- remarkPlugins={[remarkGfm]}
118
- rehypePlugins={[
119
- rehypeSlug,
120
- [rehypeAutolinkHeadings, {
121
- behavior: 'wrap',
122
- properties: {
123
- className: ['anchor'],
124
- },
125
- }],
126
- ]}
127
- components={{
128
- code(props) {
129
- const { children, className } = props
130
- const match = /language-(\w+)/.exec(className || '')
131
- return match ? (
132
- <SyntaxHighlighter
133
- PreTag='div'
134
- children={String(children).replace(/\n$/, '')}
135
- language={match[1]}
136
- style={oneLight}
137
- />
138
- ) : (
139
- <code className={className}>
140
- {children}
141
- </code>
142
- )
143
- },
144
- }}
145
- >
146
- {content}
147
- </ReactMarkdown>
148
- </div>
149
- </div>
150
- </div>
151
- )
152
- }
@@ -1,29 +0,0 @@
1
- 'use client'
2
-
3
- import { createContext, useContext, type ReactNode } from 'react'
4
-
5
- export interface MindMapDndState {
6
- draggingNodeId: string | null
7
- dropTargetNodeId: string | null
8
- }
9
-
10
- const MindMapDndContext = createContext<MindMapDndState | null>(null)
11
-
12
- interface MindMapDndProviderProps {
13
- value: MindMapDndState
14
- children: ReactNode
15
- }
16
-
17
- export const MindMapDndProvider = (props: MindMapDndProviderProps) => {
18
- const { value, children } = props
19
- return (
20
- <MindMapDndContext.Provider value={value}>
21
- {children}
22
- </MindMapDndContext.Provider>
23
- )
24
- }
25
-
26
- export const useMindMapDndState = (): MindMapDndState => {
27
- const value = useContext(MindMapDndContext)
28
- return value ?? { draggingNodeId: null, dropTargetNodeId: null }
29
- }
@@ -1,220 +0,0 @@
1
- 'use client'
2
-
3
- import { Fragment, createElement, useCallback, useMemo, useState, type ReactElement } from 'react'
4
-
5
- import type { NodeChange, Node, Viewport } from '@xyflow/react'
6
-
7
- interface HelperLines {
8
- x: number | null
9
- y: number | null
10
- }
11
-
12
- interface UseAlignmentSnapParams<TNodeData extends Record<string, unknown>> {
13
- // 开关:关闭时只透传回调,不做任何吸附与对齐线计算
14
- enabled?: boolean
15
- // 当前节点列表(用于计算对齐点)
16
- nodes: Array<Node<TNodeData>>
17
- // 透传给 ReactFlow 的 onNodesChange(通常来自 useNodesState)
18
- onNodesChange?: (changes: Array<NodeChange<Node<TNodeData>>>) => void
19
- // 吸附阈值(单位:画布坐标 px)
20
- snapThreshold?: number
21
- }
22
-
23
- interface UseAlignmentSnapResult<TNodeData extends Record<string, unknown>> {
24
- // hook 直接产出的对齐线元素,主组件可直接渲染
25
- helperLines: ReactElement | null
26
- // 用于同步 viewport,保证对齐线在屏幕坐标下位置正确
27
- onMove: (_event: unknown, viewport: Viewport) => void
28
- // 包装后的 onNodesChange:在 position change 上做吸附与对齐线更新
29
- onNodesChange: (changes: Array<NodeChange<Node<TNodeData>>>) => void
30
- }
31
-
32
- const getNodeSize = <TNodeData extends Record<string, unknown>,>(node: Node<TNodeData>): { width: number, height: number } => {
33
- const width = node.measured?.width ?? node.width ?? 0
34
- const height = node.measured?.height ?? node.height ?? 0
35
- return { width, height }
36
- }
37
-
38
- export const useAlignmentSnap = <TNodeData extends Record<string, unknown>,>(params: UseAlignmentSnapParams<TNodeData>): UseAlignmentSnapResult<TNodeData> => {
39
- const { enabled = false, nodes, onNodesChange: onNodesChangeExternal, snapThreshold = 6 } = params
40
-
41
- const [viewport, setViewport] = useState<Viewport>({ x: 0, y: 0, zoom: 1 })
42
- // 保存对齐线在画布坐标下的位置(未做 viewport 变换)
43
- const [helperLines, setHelperLines] = useState<HelperLines>({ x: null, y: null })
44
-
45
- const onMove = useCallback((_event: unknown, nextViewport: Viewport): void => {
46
- setViewport(nextViewport)
47
- }, [])
48
-
49
- const onNodesChange = useCallback((changes: Array<NodeChange<Node<TNodeData>>>): void => {
50
- if (!onNodesChangeExternal) {
51
- return
52
- }
53
-
54
- if (!enabled) {
55
- setHelperLines({ x: null, y: null })
56
- onNodesChangeExternal(changes)
57
- return
58
- }
59
-
60
- // 只在 position change 上参与吸附,避免对 selection 等变更产生副作用
61
- const positionChange = changes.find(change => change.type === 'position')
62
- if (positionChange?.type !== 'position' || !positionChange.position) {
63
- onNodesChangeExternal(changes)
64
- return
65
- }
66
-
67
- const dragging = positionChange.dragging === true
68
- if (!dragging) {
69
- setHelperLines({ x: null, y: null })
70
- }
71
-
72
- const baseNode = nodes.find(item => item.id === positionChange.id)
73
- if (!baseNode) {
74
- onNodesChangeExternal(changes)
75
- return
76
- }
77
-
78
- const selfSize = getNodeSize(baseNode)
79
- if (!selfSize.width || !selfSize.height) {
80
- onNodesChangeExternal(changes)
81
- return
82
- }
83
-
84
- // 以“边/中/边”作为候选锚点,计算与其他节点锚点的最小距离
85
- const selfX = positionChange.position.x
86
- const selfY = positionChange.position.y
87
- const selfXAnchors: Array<{ point: number, shift: number }> = [
88
- { point: selfX, shift: 0 },
89
- { point: selfX + selfSize.width / 2, shift: selfSize.width / 2 },
90
- { point: selfX + selfSize.width, shift: selfSize.width },
91
- ]
92
- const selfYAnchors: Array<{ point: number, shift: number }> = [
93
- { point: selfY, shift: 0 },
94
- { point: selfY + selfSize.height / 2, shift: selfSize.height / 2 },
95
- { point: selfY + selfSize.height, shift: selfSize.height },
96
- ]
97
-
98
- let bestXDiff: number = Number.POSITIVE_INFINITY
99
- let bestYDiff: number = Number.POSITIVE_INFINITY
100
- let bestXLine: number | null = null
101
- let bestYLine: number | null = null
102
- let bestXOffset: number = 0
103
- let bestYOffset: number = 0
104
-
105
- nodes.forEach(other => {
106
- if (other.id === positionChange.id) {
107
- return
108
- }
109
- const otherSize = getNodeSize(other)
110
- if (!otherSize.width || !otherSize.height) {
111
- return
112
- }
113
-
114
- const otherX = other.position.x
115
- const otherY = other.position.y
116
- const otherXAnchors: Array<number> = [otherX, otherX + otherSize.width / 2, otherX + otherSize.width]
117
- const otherYAnchors: Array<number> = [otherY, otherY + otherSize.height / 2, otherY + otherSize.height]
118
-
119
- for (const selfAnchor of selfXAnchors) {
120
- for (const otherAnchor of otherXAnchors) {
121
- const diffX = Math.abs(selfAnchor.point - otherAnchor)
122
- if (diffX <= snapThreshold && diffX < bestXDiff) {
123
- bestXDiff = diffX
124
- bestXLine = otherAnchor
125
- bestXOffset = otherAnchor - selfAnchor.point
126
- }
127
- }
128
- }
129
-
130
- for (const selfAnchor of selfYAnchors) {
131
- for (const otherAnchor of otherYAnchors) {
132
- const diffY = Math.abs(selfAnchor.point - otherAnchor)
133
- if (diffY <= snapThreshold && diffY < bestYDiff) {
134
- bestYDiff = diffY
135
- bestYLine = otherAnchor
136
- bestYOffset = otherAnchor - selfAnchor.point
137
- }
138
- }
139
- }
140
- })
141
-
142
- if (dragging) {
143
- setHelperLines({ x: bestXLine, y: bestYLine })
144
- }
145
-
146
- // 没命中阈值则完全透传,避免抖动
147
- if (bestXLine === null && bestYLine === null) {
148
- onNodesChangeExternal(changes)
149
- return
150
- }
151
-
152
- const nextX = bestXLine === null ? selfX : selfX + bestXOffset
153
- const nextY = bestYLine === null ? selfY : selfY + bestYOffset
154
-
155
- // 通过“改写 position change”的方式实现吸附,避免与外部受控状态冲突
156
- const nextChanges: Array<NodeChange<Node<TNodeData>>> = changes.map(change => {
157
- if (change.type !== 'position' || change.id !== positionChange.id || !change.position) {
158
- return change
159
- }
160
- if (change.position.x === nextX && change.position.y === nextY) {
161
- return change
162
- }
163
- return {
164
- ...change,
165
- position: { x: nextX, y: nextY },
166
- }
167
- })
168
-
169
- onNodesChangeExternal(nextChanges)
170
- }, [enabled, nodes, onNodesChangeExternal, snapThreshold])
171
-
172
- // 将画布坐标转换为屏幕坐标,用于 absolute 定位对齐线
173
- const helperLineX = useMemo((): number | null => {
174
- if (helperLines.x === null) {
175
- return null
176
- }
177
- return helperLines.x * viewport.zoom + viewport.x
178
- }, [helperLines.x, viewport.x, viewport.zoom])
179
-
180
- const helperLineY = useMemo((): number | null => {
181
- if (helperLines.y === null) {
182
- return null
183
- }
184
- return helperLines.y * viewport.zoom + viewport.y
185
- }, [helperLines.y, viewport.y, viewport.zoom])
186
-
187
- const helperLinesElement = useMemo((): ReactElement | null => {
188
- if (!enabled) {
189
- return null
190
- }
191
-
192
- const elements: ReactElement[] = []
193
- if (helperLineX !== null) {
194
- elements.push(createElement('div', {
195
- key: 'helper-line-x',
196
- className: 'pointer-events-none absolute top-0 h-full w-px bg-sky-500',
197
- style: { left: helperLineX },
198
- }))
199
- }
200
- if (helperLineY !== null) {
201
- elements.push(createElement('div', {
202
- key: 'helper-line-y',
203
- className: 'pointer-events-none absolute left-0 w-full h-px bg-sky-500',
204
- style: { top: helperLineY },
205
- }))
206
- }
207
-
208
- if (elements.length === 0) {
209
- return null
210
- }
211
-
212
- return createElement(Fragment, null, ...elements)
213
- }, [enabled, helperLineX, helperLineY])
214
-
215
- return {
216
- helperLines: helperLinesElement,
217
- onMove,
218
- onNodesChange,
219
- }
220
- }