dishui 0.0.106 → 0.0.110

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 (388) hide show
  1. package/dist/.release-verified.json +3 -2
  2. package/dist/components/Accordion/index.js.map +1 -1
  3. package/dist/components/Avatar/index.js.map +1 -1
  4. package/dist/components/Badge/index.js.map +1 -1
  5. package/dist/components/Button/index.js.map +1 -1
  6. package/dist/components/ButtonMenu/index.js.map +1 -1
  7. package/dist/components/Card/Metric2.js.map +1 -1
  8. package/dist/components/Card/Ticket2.js.map +1 -1
  9. package/dist/components/Card/index.js.map +1 -1
  10. package/dist/components/Chart/Chart.js.map +1 -1
  11. package/dist/components/Checkbox/index.js.map +1 -1
  12. package/dist/components/ChoicePicker/index.js.map +1 -1
  13. package/dist/components/Column/index.js.map +1 -1
  14. package/dist/components/ConfirmDialog/index.js.map +1 -1
  15. package/dist/components/DateTimeInput/index.js.map +1 -1
  16. package/dist/components/Demo/index.js.map +1 -1
  17. package/dist/components/Demo/source.js.map +1 -1
  18. package/dist/components/Divider/index.js.map +1 -1
  19. package/dist/components/EmptyState/index.js.map +1 -1
  20. package/dist/components/Field/index.js.map +1 -1
  21. package/dist/components/FileUploader/DropZone.js.map +1 -1
  22. package/dist/components/FileUploader/FileItem.js.map +1 -1
  23. package/dist/components/FileUploader/FileUploader.js.map +1 -1
  24. package/dist/components/FileUploader/UploadQueue.js.map +1 -1
  25. package/dist/components/GroupButton/index.js.map +1 -1
  26. package/dist/components/GroupedTable/index.js.map +1 -1
  27. package/dist/components/Icon/index.js.map +1 -1
  28. package/dist/components/Image/index.js.map +1 -1
  29. package/dist/components/Input/index.js.map +1 -1
  30. package/dist/components/Label/index.js.map +1 -1
  31. package/dist/components/Layout/index.js.map +1 -1
  32. package/dist/components/LayoutSuite/DashboardSuite.js.map +1 -1
  33. package/dist/components/LayoutSuite/index.js.map +1 -1
  34. package/dist/components/List/index.js.map +1 -1
  35. package/dist/components/Markdown/Markdown.js.map +1 -1
  36. package/dist/components/Markdown/codeThemes.js.map +1 -1
  37. package/dist/components/Markdown/markdownComponents.js.map +1 -1
  38. package/dist/components/Markdown/parseCodeBlockMeta.js.map +1 -1
  39. package/dist/components/Markdown/useMarkdownSource.js.map +1 -1
  40. package/dist/components/Markdown/useMarkmapRenderer.js.map +1 -1
  41. package/dist/components/Markdown/useMermaidRenderer.js.map +1 -1
  42. package/dist/components/Modal/focusScope.js.map +1 -1
  43. package/dist/components/Modal/index.js.map +1 -1
  44. package/dist/components/MultipleChoice/index.js.map +1 -1
  45. package/dist/components/NavigationList/index.js.map +1 -1
  46. package/dist/components/Page/Float2.js.map +1 -1
  47. package/dist/components/Page/index.js.map +1 -1
  48. package/dist/components/Page/resize2.js.map +1 -1
  49. package/dist/components/PageHeader/index.js.map +1 -1
  50. package/dist/components/PagePanel/index.js.map +1 -1
  51. package/dist/components/ProtectedRoute/index.js.map +1 -1
  52. package/dist/components/Resizable/ResizeGrip.js.map +1 -1
  53. package/dist/components/Resizable/index.js.map +1 -1
  54. package/dist/components/Resizable/useResize.js.map +1 -1
  55. package/dist/components/Row/index.js.map +1 -1
  56. package/dist/components/Section/index.js.map +1 -1
  57. package/dist/components/Select/index.js.map +1 -1
  58. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  59. package/dist/components/Skeleton/index.js.map +1 -1
  60. package/dist/components/Slider/index.js.map +1 -1
  61. package/dist/components/Switch/index.js.map +1 -1
  62. package/dist/components/Tab/index.js.map +1 -1
  63. package/dist/components/Table/index.js.map +1 -1
  64. package/dist/components/Tabs/index.js.map +1 -1
  65. package/dist/components/Tabs/tabNavigation.js.map +1 -1
  66. package/dist/components/Text/index.js.map +1 -1
  67. package/dist/components/Textarea/index.js.map +1 -1
  68. package/dist/components/Tooltip/index.js.map +1 -1
  69. package/dist/components/Tree/Tree.js.map +1 -1
  70. package/dist/components/ai/AgentChat/index.js.map +1 -1
  71. package/dist/components/ai/AgentRunCard/index.js.map +1 -1
  72. package/dist/components/ai/AgentScreen/index.js.map +1 -1
  73. package/dist/components/ai/ApprovalCard/index.js.map +1 -1
  74. package/dist/components/ai/CodeView/index.js.map +1 -1
  75. package/dist/components/ai/CommandSearch/index.js.map +1 -1
  76. package/dist/components/ai/ContextCards/index.js.map +1 -1
  77. package/dist/components/ai/DiffTable/index.js.map +1 -1
  78. package/dist/components/ai/FilterTable/index.js.map +1 -1
  79. package/dist/components/ai/FineTuneCard/index.js.map +1 -1
  80. package/dist/components/ai/InsightCards/index.js.map +1 -1
  81. package/dist/components/ai/IssueCard/index.js.map +1 -1
  82. package/dist/components/ai/LoadingState/index.js.map +1 -1
  83. package/dist/components/ai/PromptBar/index.js.map +1 -1
  84. package/dist/components/ai/RecommendationCard/index.js.map +1 -1
  85. package/dist/components/ai/RecordsTable/index.js.map +1 -1
  86. package/dist/components/ai/SelectionActions/index.js.map +1 -1
  87. package/dist/components/ai/StateFlow/index.js.map +1 -1
  88. package/dist/components/ai/StreamingText/index.js.map +1 -1
  89. package/dist/components/ai/TaskRows/index.js.map +1 -1
  90. package/dist/components/ai/Thinking/index.js.map +1 -1
  91. package/dist/components/ai/ToolChips/index.js.map +1 -1
  92. package/dist/components/ai/shared.js.map +1 -1
  93. package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
  94. package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
  95. package/dist/components/pro/ArticleControl/buildHeadingTree.js.map +1 -1
  96. package/dist/components/pro/ArticleControl/useArticleToc.js.map +1 -1
  97. package/dist/components/pro/Calendar/Calendar.js +165 -160
  98. package/dist/components/pro/Calendar/Calendar.js.map +1 -1
  99. package/dist/components/pro/Calendar/hooks/useCalendarDrag.js.map +1 -1
  100. package/dist/components/pro/Calendar/hooks/useCalendarState.js +31 -31
  101. package/dist/components/pro/Calendar/hooks/useCalendarState.js.map +1 -1
  102. package/dist/components/pro/Calendar/utils.js.map +1 -1
  103. package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
  104. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
  105. package/dist/components/pro/CodeEditor/editors/markdownExtensions.js.map +1 -1
  106. package/dist/components/pro/CodeEditor/extensions/contextMenu.js.map +1 -1
  107. package/dist/components/pro/CodeEditor/extensions/index.js.map +1 -1
  108. package/dist/components/pro/CodeEditor/langs/index.js.map +1 -1
  109. package/dist/components/pro/CodeEditor/langs/javascript.js.map +1 -1
  110. package/dist/components/pro/CodeEditor/langs/python.js.map +1 -1
  111. package/dist/components/pro/CodeEditor/langs/snippets.js.map +1 -1
  112. package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
  113. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js +65 -59
  114. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
  115. package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
  116. package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
  117. package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
  118. package/dist/components/pro/CodeEditor/themes.js.map +1 -1
  119. package/dist/components/pro/CodeEditor/utils.js.map +1 -1
  120. package/dist/components/pro/DataTable/DataTable.js.map +1 -1
  121. package/dist/components/pro/DataTable/Filters.js.map +1 -1
  122. package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
  123. package/dist/components/pro/DataTable/PivotView.js.map +1 -1
  124. package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
  125. package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
  126. package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
  127. package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
  128. package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
  129. package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
  130. package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
  131. package/dist/components/pro/DataTable/extension.js.map +1 -1
  132. package/dist/components/pro/DataTable/pivotEngine.js.map +1 -1
  133. package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
  134. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  135. package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
  136. package/dist/components/pro/DataTable/treeDataUtils.js.map +1 -1
  137. package/dist/components/pro/DataTable/useColumnDragReorder.js.map +1 -1
  138. package/dist/components/pro/DataTable/useDataTableModel.js +119 -104
  139. package/dist/components/pro/DataTable/useDataTableModel.js.map +1 -1
  140. package/dist/components/pro/DataTable/utils.js.map +1 -1
  141. package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
  142. package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
  143. package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
  144. package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
  145. package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
  146. package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
  147. package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
  148. package/dist/components/pro/Flow/Flow.js.map +1 -1
  149. package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
  150. package/dist/components/pro/Flow/archify/build.js.map +1 -1
  151. package/dist/components/pro/Flow/archify/convert.js.map +1 -1
  152. package/dist/components/pro/Flow/archify/palette.js.map +1 -1
  153. package/dist/components/pro/Flow/archify/presets.js.map +1 -1
  154. package/dist/components/pro/Flow/archify/spec.js.map +1 -1
  155. package/dist/components/pro/Flow/canvas/AlignmentGuides.js.map +1 -1
  156. package/dist/components/pro/Flow/canvas/GridRenderer.js.map +1 -1
  157. package/dist/components/pro/Flow/canvas/MiniMapRenderer.js.map +1 -1
  158. package/dist/components/pro/Flow/canvas/PixiApp.js.map +1 -1
  159. package/dist/components/pro/Flow/canvas/SelectionOverlay.js.map +1 -1
  160. package/dist/components/pro/Flow/canvas/ViewportContainer.js.map +1 -1
  161. package/dist/components/pro/Flow/constants.js.map +1 -1
  162. package/dist/components/pro/Flow/context/FlowAIContext.js.map +1 -1
  163. package/dist/components/pro/Flow/context/FlowContext.js.map +1 -1
  164. package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
  165. package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
  166. package/dist/components/pro/Flow/edges/edgeMarkers.js.map +1 -1
  167. package/dist/components/pro/Flow/edges/edgePaths.js.map +1 -1
  168. package/dist/components/pro/Flow/hooks/useAlignmentGuides.js.map +1 -1
  169. package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
  170. package/dist/components/pro/Flow/hooks/useCompactMode.js.map +1 -1
  171. package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
  172. package/dist/components/pro/Flow/hooks/useDraggablePanel.js.map +1 -1
  173. package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
  174. package/dist/components/pro/Flow/hooks/useFlowImportExport.js.map +1 -1
  175. package/dist/components/pro/Flow/hooks/useKeyboardShortcuts.js.map +1 -1
  176. package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
  177. package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
  178. package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
  179. package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
  180. package/dist/components/pro/Flow/hooks/usePdfExport.js.map +1 -1
  181. package/dist/components/pro/Flow/hooks/usePixiApp.js.map +1 -1
  182. package/dist/components/pro/Flow/hooks/useResizablePanel.js.map +1 -1
  183. package/dist/components/pro/Flow/hooks/useSelection.js.map +1 -1
  184. package/dist/components/pro/Flow/hooks/useUndoRedo.js.map +1 -1
  185. package/dist/components/pro/Flow/hooks/useViewport.js.map +1 -1
  186. package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
  187. package/dist/components/pro/Flow/lines/GeometricLineTool.js.map +1 -1
  188. package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
  189. package/dist/components/pro/Flow/lines/lineSmoothing.js.map +1 -1
  190. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  191. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  192. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  193. package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
  194. package/dist/components/pro/Flow/nodes/NodeHandles.js.map +1 -1
  195. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  196. package/dist/components/pro/Flow/nodes/NodeText.js.map +1 -1
  197. package/dist/components/pro/Flow/nodes/aiClient.js.map +1 -1
  198. package/dist/components/pro/Flow/nodes/animAnchors.js.map +1 -1
  199. package/dist/components/pro/Flow/nodes/chartGeometryBudget.js.map +1 -1
  200. package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
  201. package/dist/components/pro/Flow/nodes/demandRender.js.map +1 -1
  202. package/dist/components/pro/Flow/nodes/nodeUtils.js.map +1 -1
  203. package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
  204. package/dist/components/pro/Flow/nodes/svgIconTexture.js.map +1 -1
  205. package/dist/components/pro/Flow/nodes/svgIcons.js.map +1 -1
  206. package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
  207. package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
  208. package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
  209. package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
  210. package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
  211. package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
  212. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  213. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  214. package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
  215. package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
  216. package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
  217. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  218. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  219. package/dist/components/pro/Flow/types.js.map +1 -1
  220. package/dist/components/pro/Flow/utils/dashedLine.js.map +1 -1
  221. package/dist/components/pro/Flow/utils/gradient.js.map +1 -1
  222. package/dist/components/pro/Flow/utils/pdfExport.js.map +1 -1
  223. package/dist/components/pro/Flow/utils/themeColor.js.map +1 -1
  224. package/dist/components/pro/Gantt/Gantt.js.map +1 -1
  225. package/dist/components/pro/Gantt/hooks/useGanttDrag.js.map +1 -1
  226. package/dist/components/pro/Gantt/hooks/useGanttState.js +79 -71
  227. package/dist/components/pro/Gantt/hooks/useGanttState.js.map +1 -1
  228. package/dist/components/pro/Gantt/utils.js.map +1 -1
  229. package/dist/components/pro/Kanban/Kanban.js.map +1 -1
  230. package/dist/components/pro/Kanban/Swimlanes.js.map +1 -1
  231. package/dist/components/pro/Kanban/useKanbanDrag.js.map +1 -1
  232. package/dist/components/pro/Kanban/utils.js.map +1 -1
  233. package/dist/components/pro/RichTextEditor/AIRewrite.d.ts +1 -0
  234. package/dist/components/pro/RichTextEditor/AIRewrite.js +109 -88
  235. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  236. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  237. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  238. package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
  239. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  240. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  241. package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
  242. package/dist/components/pro/RichTextEditor/RichTextEditor.js +133 -132
  243. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  244. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  245. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  246. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  247. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  248. package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
  249. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
  250. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  251. package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js.map +1 -1
  252. package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js.map +1 -1
  253. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  254. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js.map +1 -1
  255. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  256. package/dist/components/pro/RichTextEditor/extensions/FontSize.js.map +1 -1
  257. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  258. package/dist/components/pro/RichTextEditor/extensions/ResizableImage.js.map +1 -1
  259. package/dist/components/pro/RichTextEditor/extensions/legacyMermaid.js.map +1 -1
  260. package/dist/components/pro/RichTextEditor/types.d.ts +2 -0
  261. package/dist/components/pro/RichTextEditor/types.js.map +1 -1
  262. package/dist/components/pro/Sprite/Molly/animations.d.ts +6 -0
  263. package/dist/components/pro/Sprite/Molly/animations.js +52 -0
  264. package/dist/components/pro/Sprite/Molly/animations.js.map +1 -0
  265. package/dist/components/pro/Sprite/Molly/events.d.ts +2 -0
  266. package/dist/components/pro/Sprite/Molly/events.js +46 -0
  267. package/dist/components/pro/Sprite/Molly/events.js.map +1 -0
  268. package/dist/components/pro/Sprite/Molly/index.d.ts +1 -0
  269. package/dist/components/pro/Sprite/Molly/index.js +12 -0
  270. package/dist/components/pro/Sprite/Molly/index.js.map +1 -0
  271. package/dist/components/pro/Sprite/Molly/legFlexion.d.ts +3 -0
  272. package/dist/components/pro/Sprite/Molly/legFlexion.js +48 -0
  273. package/dist/components/pro/Sprite/Molly/legFlexion.js.map +1 -0
  274. package/dist/components/pro/Sprite/Molly/locomotion.d.ts +4 -0
  275. package/dist/components/pro/Sprite/Molly/locomotion.js +51 -0
  276. package/dist/components/pro/Sprite/Molly/locomotion.js.map +1 -0
  277. package/dist/components/pro/Sprite/Molly/model.d.ts +23 -0
  278. package/dist/components/pro/Sprite/Molly/model.js +614 -0
  279. package/dist/components/pro/Sprite/Molly/model.js.map +1 -0
  280. package/dist/components/pro/Sprite/Molly/rig.d.ts +25 -0
  281. package/dist/components/pro/Sprite/Molly/rig.js +102 -0
  282. package/dist/components/pro/Sprite/Molly/rig.js.map +1 -0
  283. package/dist/components/pro/Sprite/Ruby/animations.d.ts +6 -0
  284. package/dist/components/pro/Sprite/Ruby/animations.js +58 -0
  285. package/dist/components/pro/Sprite/Ruby/animations.js.map +1 -0
  286. package/dist/components/pro/Sprite/Ruby/events.d.ts +2 -0
  287. package/dist/components/pro/Sprite/Ruby/events.js +46 -0
  288. package/dist/components/pro/Sprite/Ruby/events.js.map +1 -0
  289. package/dist/components/pro/Sprite/Ruby/index.d.ts +1 -0
  290. package/dist/components/pro/Sprite/Ruby/index.js +12 -0
  291. package/dist/components/pro/Sprite/Ruby/index.js.map +1 -0
  292. package/dist/components/pro/Sprite/Ruby/locomotion.d.ts +4 -0
  293. package/dist/components/pro/Sprite/Ruby/locomotion.js +41 -0
  294. package/dist/components/pro/Sprite/Ruby/locomotion.js.map +1 -0
  295. package/dist/components/pro/Sprite/Ruby/model.d.ts +23 -0
  296. package/dist/components/pro/Sprite/Ruby/model.js +605 -0
  297. package/dist/components/pro/Sprite/Ruby/model.js.map +1 -0
  298. package/dist/components/pro/Sprite/Ruby/rig.d.ts +26 -0
  299. package/dist/components/pro/Sprite/Ruby/rig.js +112 -0
  300. package/dist/components/pro/Sprite/Ruby/rig.js.map +1 -0
  301. package/dist/components/pro/Sprite/Sprite.d.ts +23 -0
  302. package/dist/components/pro/Sprite/Sprite2.js +224 -0
  303. package/dist/components/pro/Sprite/Sprite2.js.map +1 -0
  304. package/dist/components/pro/Sprite/actions.d.ts +3 -0
  305. package/dist/components/pro/Sprite/actions.js +16 -0
  306. package/dist/components/pro/Sprite/actions.js.map +1 -0
  307. package/dist/components/pro/Sprite/createSpriteScene.d.ts +4 -0
  308. package/dist/components/pro/Sprite/createSpriteScene.js +14 -0
  309. package/dist/components/pro/Sprite/createSpriteScene.js.map +1 -0
  310. package/dist/components/pro/Sprite/index.d.ts +4 -0
  311. package/dist/components/pro/Sprite/shared/animation.d.ts +33 -0
  312. package/dist/components/pro/Sprite/shared/animation.js +39 -0
  313. package/dist/components/pro/Sprite/shared/animation.js.map +1 -0
  314. package/dist/components/pro/Sprite/shared/createSpriteStage.d.ts +14 -0
  315. package/dist/components/pro/Sprite/shared/createSpriteStage.js +127 -0
  316. package/dist/components/pro/Sprite/shared/createSpriteStage.js.map +1 -0
  317. package/dist/components/pro/Sprite/shared/events.d.ts +5 -0
  318. package/dist/components/pro/Sprite/shared/events.js +21 -0
  319. package/dist/components/pro/Sprite/shared/events.js.map +1 -0
  320. package/dist/components/pro/Sprite/shared/face.d.ts +15 -0
  321. package/dist/components/pro/Sprite/shared/face.js +33 -0
  322. package/dist/components/pro/Sprite/shared/face.js.map +1 -0
  323. package/dist/components/pro/Sprite/shared/faceSurface.d.ts +6 -0
  324. package/dist/components/pro/Sprite/shared/faceSurface.js +66 -0
  325. package/dist/components/pro/Sprite/shared/faceSurface.js.map +1 -0
  326. package/dist/components/pro/Sprite/shared/gait.d.ts +5 -0
  327. package/dist/components/pro/Sprite/shared/gait.js +19 -0
  328. package/dist/components/pro/Sprite/shared/gait.js.map +1 -0
  329. package/dist/components/pro/Sprite/shared/geometry.d.ts +8 -0
  330. package/dist/components/pro/Sprite/shared/geometry.js +59 -0
  331. package/dist/components/pro/Sprite/shared/geometry.js.map +1 -0
  332. package/dist/components/pro/Sprite/shared/magicEffect.d.ts +27 -0
  333. package/dist/components/pro/Sprite/shared/magicEffect.js +61 -0
  334. package/dist/components/pro/Sprite/shared/magicEffect.js.map +1 -0
  335. package/dist/components/pro/Sprite/shared/playback.d.ts +8 -0
  336. package/dist/components/pro/Sprite/shared/playback.js +74 -0
  337. package/dist/components/pro/Sprite/shared/playback.js.map +1 -0
  338. package/dist/components/pro/Sprite/shared/rig.d.ts +6 -0
  339. package/dist/components/pro/Sprite/shared/rig.js +48 -0
  340. package/dist/components/pro/Sprite/shared/rig.js.map +1 -0
  341. package/dist/components/pro/Sprite/shared/scene.d.ts +9 -0
  342. package/dist/components/pro/Sprite/shared/scene.js +21 -0
  343. package/dist/components/pro/Sprite/shared/scene.js.map +1 -0
  344. package/dist/components/pro/Sprite/shared/sculptor.d.ts +14 -0
  345. package/dist/components/pro/Sprite/shared/sculptor.js +78 -0
  346. package/dist/components/pro/Sprite/shared/sculptor.js.map +1 -0
  347. package/dist/components/pro/Sprite/shared/speechBubble.d.ts +15 -0
  348. package/dist/components/pro/Sprite/shared/speechBubble.js +129 -0
  349. package/dist/components/pro/Sprite/shared/speechBubble.js.map +1 -0
  350. package/dist/components/pro/Sprite/types.d.ts +40 -0
  351. package/dist/contexts/AppContext.js.map +1 -1
  352. package/dist/contexts/authentication.js.map +1 -1
  353. package/dist/data-table.js +3 -3
  354. package/dist/data-table.js.map +1 -1
  355. package/dist/dishui.css +1 -1
  356. package/dist/hooks/useClickOutside.js.map +1 -1
  357. package/dist/hooks/useContainerElement.js.map +1 -1
  358. package/dist/hooks/useControllableState.js.map +1 -1
  359. package/dist/hooks/useCopyToClipboard.js.map +1 -1
  360. package/dist/hooks/useDebounce.js.map +1 -1
  361. package/dist/hooks/useDraggable.js.map +1 -1
  362. package/dist/hooks/useTableColumns.js.map +1 -1
  363. package/dist/hooks/useTableData.js.map +1 -1
  364. package/dist/index-nostyled.d.ts +2 -0
  365. package/dist/index.d.ts +2 -0
  366. package/dist/index.js +116 -115
  367. package/dist/layouts/MainLayout.js.map +1 -1
  368. package/dist/layouts/Navbar.js.map +1 -1
  369. package/dist/layouts/Sidebar.js.map +1 -1
  370. package/dist/layouts/headbar/Headbar.js.map +1 -1
  371. package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
  372. package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
  373. package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
  374. package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
  375. package/dist/sprite.js +2 -0
  376. package/dist/styles/themeStyles.js.map +1 -1
  377. package/dist/utils/cn.js.map +1 -1
  378. package/dist/utils/flexLayout.js.map +1 -1
  379. package/dist/utils/i18n.js.map +1 -1
  380. package/dist/utils/menu.js.map +1 -1
  381. package/dist/utils/rehype-code-meta.js.map +1 -1
  382. package/dist/utils/remark-code-meta.js.map +1 -1
  383. package/dist/utils/routerBuilder.js.map +1 -1
  384. package/dist/utils/safeStorage.js.map +1 -1
  385. package/dist/utils/selection.js +29 -20
  386. package/dist/utils/selection.js.map +1 -1
  387. package/dist/utils/themes.js.map +1 -1
  388. package/package.json +15 -11
@@ -1 +1 @@
1
- {"version":3,"file":"themes.js","names":[],"sources":["../../../../src/components/pro/CodeEditor/themes.ts"],"sourcesContent":["import { Extension } from '@codemirror/state';\nimport { EditorView } from '@codemirror/view';\nimport { HighlightStyle, syntaxHighlighting } from '@codemirror/language';\nimport { tags } from '@lezer/highlight';\nimport type { EditorTheme } from './types';\n\n// ============= 主题配置类型 =============\n\ninterface ThemeColors {\n background: string;\n foreground: string;\n caret: string;\n activeLine: string;\n selectionBackground: string;\n selectionOpacity: number;\n gutterBackground: string;\n gutterForeground: string;\n // 语法高亮\n keyword: string;\n atom: string;\n number: string;\n def: string;\n variable: string;\n variable2?: string;\n type?: string;\n property: string;\n operator: string;\n comment: string;\n string: string;\n meta: string;\n builtin: string;\n bracket: string;\n tag: string;\n attribute: string;\n link: string;\n error?: string;\n}\n\n// ============= 主题配置 =============\n\nconst themeConfigs: Record<string, { colors: ThemeColors; dark?: boolean }> = {\n light: {\n colors: {\n background: '#ffffff',\n foreground: '#000000',\n caret: '#000000',\n activeLine: 'rgba(0, 0, 0, 0.03)',\n selectionBackground: '#add6ff',\n selectionOpacity: 0.9,\n gutterBackground: '#f8f8f8',\n gutterForeground: '#999',\n keyword: '#0000ff',\n atom: '#219',\n number: '#164',\n def: '#00f',\n variable: '#05a',\n property: '#05a',\n operator: '#000',\n comment: '#708090',\n string: '#a11',\n meta: '#555',\n builtin: '#30a',\n bracket: '#997',\n tag: '#170',\n attribute: '#00c',\n link: '#00e',\n },\n },\n dark: {\n colors: {\n background: '#1e1e1e',\n foreground: '#e0e0e0',\n caret: '#ffffff',\n activeLine: 'rgba(255, 255, 255, 0.08)',\n selectionBackground: '#555555',\n selectionOpacity: 0.85,\n gutterBackground: '#252526',\n gutterForeground: '#858585',\n keyword: '#ff79c6',\n atom: '#bd93f9',\n number: '#ffb86c',\n def: '#50fa7b',\n variable: '#f8f8f2',\n variable2: '#f1fa8c',\n type: '#bd93f9',\n property: '#ffd580',\n operator: '#ff79c6',\n comment: '#6a9955',\n string: '#f1fa8c',\n meta: '#f8f8f2',\n builtin: '#bd93f9',\n bracket: '#f8f8f2',\n tag: '#ff79c6',\n attribute: '#50fa7b',\n link: '#ff79c6',\n error: '#ff5555',\n },\n dark: true,\n },\n cursor: {\n // 参考 Cursor / VS Code 深色:冷调近黑背景、克制的语法配色\n colors: {\n background: '#171922',\n foreground: '#c5cad6',\n caret: '#60a5fa',\n activeLine: 'rgba(96, 165, 250, 0.08)',\n selectionBackground: '#2b3350',\n selectionOpacity: 0.9,\n gutterBackground: '#171922',\n gutterForeground: '#5a6172',\n keyword: '#8ab4f8',\n atom: '#c792ea',\n number: '#f6c177',\n def: '#82aaff',\n variable: '#c5cad6',\n variable2: '#9cdcfe',\n type: '#4ec9b0',\n property: '#9cdcfe',\n operator: '#89ddff',\n comment: '#6a7280',\n string: '#a5d6a7',\n meta: '#c5cad6',\n builtin: '#c792ea',\n bracket: '#c5cad6',\n tag: '#8ab4f8',\n attribute: '#c792ea',\n link: '#60a5fa',\n error: '#f7768e',\n },\n dark: true,\n },\n retro: {\n colors: {\n background: '#2d1b00',\n foreground: '#f5deb3',\n caret: '#ffcc66',\n activeLine: 'rgba(255, 204, 102, 0.1)',\n selectionBackground: '#663300',\n selectionOpacity: 0.8,\n gutterBackground: '#1a0f00',\n gutterForeground: '#997755',\n keyword: '#ff9966',\n atom: '#ffcc99',\n number: '#cc9966',\n def: '#ffaa55',\n variable: '#f5deb3',\n property: '#f5deb3',\n operator: '#ff9966',\n comment: '#8b7355',\n string: '#ffcc66',\n meta: '#cc9966',\n builtin: '#ff9966',\n bracket: '#cc9966',\n tag: '#ff9966',\n attribute: '#ffcc66',\n link: '#ffcc99',\n },\n dark: true,\n },\n cyberpunk: {\n colors: {\n background: '#0d0221',\n foreground: '#f72585',\n caret: '#7209b7',\n activeLine: 'rgba(114, 9, 183, 0.15)',\n selectionBackground: '#3c096c',\n selectionOpacity: 0.8,\n gutterBackground: '#0a0118',\n gutterForeground: '#7209b7',\n keyword: '#f72585',\n atom: '#b5179e',\n number: '#7209b7',\n def: '#f72585',\n variable: '#ffffff',\n property: '#ffffff',\n operator: '#f72585',\n comment: '#560bad',\n string: '#b5179e',\n meta: '#7209b7',\n builtin: '#f72585',\n bracket: '#b5179e',\n tag: '#f72585',\n attribute: '#b5179e',\n link: '#b5179e',\n },\n dark: true,\n },\n matrix: {\n colors: {\n background: '#0d1117',\n foreground: '#00ff00',\n caret: '#00ff00',\n activeLine: 'rgba(0, 255, 0, 0.08)',\n selectionBackground: '#003300',\n selectionOpacity: 0.8,\n gutterBackground: '#0a0e11',\n gutterForeground: '#00aa00',\n keyword: '#00ff00',\n atom: '#00cc00',\n number: '#00ff00',\n def: '#00ff00',\n variable: '#00ee00',\n property: '#00ee00',\n operator: '#00ff00',\n comment: '#008800',\n string: '#00cc00',\n meta: '#00ff00',\n builtin: '#00ff00',\n bracket: '#00dd00',\n tag: '#00ff00',\n attribute: '#00cc00',\n link: '#00ff00',\n },\n dark: true,\n },\n oceanblue: {\n colors: {\n background: '#f0f9ff',\n foreground: '#0c4a6e',\n caret: '#0369a1',\n activeLine: 'rgba(3, 105, 161, 0.05)',\n selectionBackground: '#bae6fd',\n selectionOpacity: 0.9,\n gutterBackground: '#e0f2fe',\n gutterForeground: '#075985',\n keyword: '#0369a1',\n atom: '#0891b2',\n number: '#0e7490',\n def: '#0369a1',\n variable: '#0c4a6e',\n property: '#0c4a6e',\n operator: '#0369a1',\n comment: '#64748b',\n string: '#0891b2',\n meta: '#475569',\n builtin: '#0369a1',\n bracket: '#334155',\n tag: '#0369a1',\n attribute: '#0891b2',\n link: '#0284c7',\n },\n },\n eyecare: {\n colors: {\n background: '#f5f8e8',\n foreground: '#2d4a2b',\n caret: '#4a7c59',\n activeLine: 'rgba(74, 124, 89, 0.06)',\n selectionBackground: '#d4e5d4',\n selectionOpacity: 0.9,\n gutterBackground: '#eef3dc',\n gutterForeground: '#5a8a5f',\n keyword: '#4a7c59',\n atom: '#5a8a5f',\n number: '#6b9b6f',\n def: '#4a7c59',\n variable: '#2d4a2b',\n property: '#2d4a2b',\n operator: '#4a7c59',\n comment: '#7a9d7e',\n string: '#5a8a5f',\n meta: '#5a7a5a',\n builtin: '#4a7c59',\n bracket: '#5a7a5a',\n tag: '#4a7c59',\n attribute: '#5a8a5f',\n link: '#4a7c59',\n },\n },\n ghibli: {\n colors: {\n background: '#fdfbf7',\n foreground: '#5c4a3c',\n caret: '#8b6f4e',\n activeLine: 'rgba(139, 111, 78, 0.05)',\n selectionBackground: '#f0e5d8',\n selectionOpacity: 0.9,\n gutterBackground: '#f7f2ea',\n gutterForeground: '#9b8b78',\n keyword: '#8b6f4e',\n atom: '#a67c52',\n number: '#7ea8a0',\n def: '#8b6f4e',\n variable: '#5c4a3c',\n property: '#5c4a3c',\n operator: '#8b6f4e',\n comment: '#9b8b78',\n string: '#a67c52',\n meta: '#7a6a58',\n builtin: '#8b6f4e',\n bracket: '#7a6a58',\n tag: '#8b6f4e',\n attribute: '#a67c52',\n link: '#7ea8a0',\n },\n },\n pinkgirl: {\n colors: {\n background: '#fff5f7',\n foreground: '#be185d',\n caret: '#db2777',\n activeLine: 'rgba(219, 39, 119, 0.05)',\n selectionBackground: '#fce7f3',\n selectionOpacity: 0.9,\n gutterBackground: '#fef1f5',\n gutterForeground: '#db2777',\n keyword: '#db2777',\n atom: '#ec4899',\n number: '#f472b6',\n def: '#db2777',\n variable: '#be185d',\n property: '#be185d',\n operator: '#db2777',\n comment: '#f9a8d4',\n string: '#ec4899',\n meta: '#be185d',\n builtin: '#db2777',\n bracket: '#be185d',\n tag: '#db2777',\n attribute: '#ec4899',\n link: '#db2777',\n },\n },\n mintgirl: {\n colors: {\n background: '#f0fdf4',\n foreground: '#065f46',\n caret: '#059669',\n activeLine: 'rgba(5, 150, 105, 0.05)',\n selectionBackground: '#d1fae5',\n selectionOpacity: 0.9,\n gutterBackground: '#ecfdf5',\n gutterForeground: '#059669',\n keyword: '#059669',\n atom: '#10b981',\n number: '#34d399',\n def: '#059669',\n variable: '#065f46',\n property: '#065f46',\n operator: '#059669',\n comment: '#6ee7b7',\n string: '#10b981',\n meta: '#047857',\n builtin: '#059669',\n bracket: '#047857',\n tag: '#059669',\n attribute: '#10b981',\n link: '#059669',\n },\n },\n // 五行主题 - 中国传统五行配色\n // 金(白/金) 木(青/绿) 水(黑/蓝) 火(赤/红) 土(黄/棕)\n wuxing: {\n colors: {\n // 背景:米黄色纸张质感(土)\n background: '#f5f0e6',\n // 前景:深棕色(土)\n foreground: '#4a3728',\n // 光标:赤红色(火)\n caret: '#c94c4c',\n // 活跃行:淡黄(土生金)\n activeLine: 'rgba(200, 170, 100, 0.12)',\n // 选中背景:淡青色(木)\n selectionBackground: '#d4e5d8',\n selectionOpacity: 0.85,\n // 行号背景:浅米黄\n gutterBackground: '#ebe5d8',\n gutterForeground: '#8b7355',\n // 关键字:赤红色(火)\n keyword: '#c94c4c',\n // 原子:金色(金)\n atom: '#b8860b',\n // 数字:深蓝(水)\n number: '#2f5496',\n // 定义:青绿色(木)\n def: '#2e7d32',\n // 变量:深棕(土)\n variable: '#5c4033',\n // 属性:棕黄(土)\n property: '#8b6914',\n // 运算符:赤色(火)\n operator: '#b5533c',\n // 注释:灰蓝(水生木)\n comment: '#6b8e8e',\n // 字符串:青绿(木)\n string: '#3d7a5a',\n // 元信息:深棕\n meta: '#6b5344',\n // 内置:金橙(金生水)\n builtin: '#cd853f',\n // 括号:深灰蓝(水)\n bracket: '#4a6670',\n // 标签:赤色(火)\n tag: '#c94c4c',\n // 属性名:青色(木)\n attribute: '#2e8b57',\n // 链接:深蓝(水)\n link: '#2f5496',\n },\n },\n};\n\n// ============= 语法高亮样式创建器 =============\n\nconst createHighlightStyle = (colors: ThemeColors): HighlightStyle => {\n const specs: { tag: any; color?: string; fontStyle?: string; fontWeight?: string; textDecoration?: string }[] = [\n { tag: tags.keyword, color: colors.keyword },\n { tag: [tags.atom, tags.bool, tags.url, tags.contentSeparator, tags.labelName], color: colors.atom },\n { tag: [tags.literal, tags.inserted], color: colors.number },\n { tag: tags.number, color: colors.number },\n { tag: [tags.string, tags.deleted], color: colors.string },\n { tag: [tags.regexp, tags.escape, tags.special(tags.string)], color: colors.string },\n { tag: tags.definition(tags.variableName), color: colors.def },\n { tag: tags.local(tags.variableName), color: colors.variable },\n { tag: tags.variableName, color: colors.variable },\n { tag: [tags.typeName, tags.namespace], color: colors.type || colors.builtin },\n { tag: tags.className, color: colors.type || colors.def },\n { tag: [tags.special(tags.variableName), tags.macroName], color: colors.builtin },\n { tag: tags.definition(tags.propertyName), color: colors.property },\n { tag: tags.propertyName, color: colors.property },\n { tag: tags.comment, color: colors.comment, fontStyle: 'italic' },\n { tag: tags.meta, color: colors.meta },\n { tag: tags.operatorKeyword, color: colors.operator },\n { tag: tags.operator, color: colors.operator },\n { tag: tags.bracket, color: colors.bracket },\n { tag: tags.angleBracket, color: colors.bracket },\n { tag: tags.squareBracket, color: colors.bracket },\n { tag: tags.paren, color: colors.bracket },\n { tag: tags.brace, color: colors.bracket },\n { tag: tags.tagName, color: colors.tag },\n { tag: tags.attributeName, color: colors.attribute },\n { tag: tags.attributeValue, color: colors.string },\n { tag: tags.link, color: colors.link, textDecoration: 'underline' },\n { tag: tags.heading, color: colors.keyword, fontWeight: 'bold' },\n { tag: tags.emphasis, fontStyle: 'italic' },\n { tag: tags.strong, fontWeight: 'bold' },\n { tag: tags.strikethrough, textDecoration: 'line-through' },\n ];\n\n if (colors.error) {\n specs.push({ tag: tags.invalid, color: colors.error });\n }\n\n if (colors.variable2) {\n specs.push({ tag: tags.special(tags.variableName), color: colors.variable2 });\n }\n\n return HighlightStyle.define(specs);\n};\n\n// ============= 编辑器外观主题创建器 =============\n\nconst createEditorTheme = (config: { colors: ThemeColors; dark?: boolean }): Extension => {\n const { colors, dark } = config;\n\n const baseStyles: Record<string, any> = {\n '&': {\n backgroundColor: colors.background,\n color: colors.foreground,\n },\n '.cm-content': {\n caretColor: colors.caret,\n },\n '.cm-cursor, .cm-dropCursor': {\n borderLeftColor: colors.caret,\n },\n '.cm-activeLine': {\n backgroundColor: colors.activeLine,\n },\n '.cm-selectionLayer': {\n mixBlendMode: 'normal',\n pointerEvents: 'none',\n zIndex: 10,\n },\n '.cm-selectionLayer .cm-selectionBackground': {\n backgroundColor: colors.selectionBackground,\n opacity: colors.selectionOpacity,\n },\n '.cm-selectionBackground': {\n backgroundColor: colors.selectionBackground,\n opacity: colors.selectionOpacity,\n },\n '&.cm-focused .cm-selectionBackground': {\n backgroundColor: colors.selectionBackground,\n },\n '.cm-gutters': {\n backgroundColor: colors.gutterBackground,\n color: colors.gutterForeground,\n border: 'none',\n },\n };\n\n if (dark) {\n baseStyles['.cm-lineNumbers .cm-gutterElement'] = { color: colors.gutterForeground };\n }\n\n return EditorView.theme(baseStyles, { dark });\n};\n\n// ============= 缓存 =============\n\nconst editorThemeCache = new Map<EditorTheme, Extension>();\nconst highlightCache = new Map<EditorTheme, Extension>();\n\n/**\n * 创建编辑器外观主题(背景色、光标色等)\n * 放入 themeCompartment\n */\nexport const createThemeExtension = (theme: EditorTheme): Extension => {\n if (editorThemeCache.has(theme)) {\n return editorThemeCache.get(theme)!;\n }\n\n const config = themeConfigs[theme] || themeConfigs.light;\n const ext = createEditorTheme(config);\n editorThemeCache.set(theme, ext);\n return ext;\n};\n\n/**\n * 创建语法高亮扩展\n * 放入 highlightCompartment\n */\nexport const createHighlightExtension = (theme: EditorTheme): Extension => {\n if (highlightCache.has(theme)) {\n return highlightCache.get(theme)!;\n }\n\n const config = themeConfigs[theme] || themeConfigs.light;\n const hl = createHighlightStyle(config.colors);\n const ext = syntaxHighlighting(hl);\n highlightCache.set(theme, ext);\n return ext;\n};\n"],"mappings":";;;;AAwCA,IAAM,IAAwE;CAC5E,OAAO,EACL,QAAQ;EACN,YAAY;EACZ,YAAY;EACZ,OAAO;EACP,YAAY;EACZ,qBAAqB;EACrB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,SAAS;EACT,MAAM;EACN,QAAQ;EACR,KAAK;EACL,UAAU;EACV,UAAU;EACV,UAAU;EACV,SAAS;EACT,QAAQ;EACR,MAAM;EACN,SAAS;EACT,SAAS;EACT,KAAK;EACL,WAAW;EACX,MAAM;CACR,EACF;CACA,MAAM;EACJ,QAAQ;GACN,YAAY;GACZ,YAAY;GACZ,OAAO;GACP,YAAY;GACZ,qBAAqB;GACrB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;GAClB,SAAS;GACT,MAAM;GACN,QAAQ;GACR,KAAK;GACL,UAAU;GACV,WAAW;GACX,MAAM;GACN,UAAU;GACV,UAAU;GACV,SAAS;GACT,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;GACT,KAAK;GACL,WAAW;GACX,MAAM;GACN,OAAO;EACT;EACA,MAAM;CACR;CACA,QAAQ;EAEN,QAAQ;GACN,YAAY;GACZ,YAAY;GACZ,OAAO;GACP,YAAY;GACZ,qBAAqB;GACrB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;GAClB,SAAS;GACT,MAAM;GACN,QAAQ;GACR,KAAK;GACL,UAAU;GACV,WAAW;GACX,MAAM;GACN,UAAU;GACV,UAAU;GACV,SAAS;GACT,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;GACT,KAAK;GACL,WAAW;GACX,MAAM;GACN,OAAO;EACT;EACA,MAAM;CACR;CACA,OAAO;EACL,QAAQ;GACN,YAAY;GACZ,YAAY;GACZ,OAAO;GACP,YAAY;GACZ,qBAAqB;GACrB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;GAClB,SAAS;GACT,MAAM;GACN,QAAQ;GACR,KAAK;GACL,UAAU;GACV,UAAU;GACV,UAAU;GACV,SAAS;GACT,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;GACT,KAAK;GACL,WAAW;GACX,MAAM;EACR;EACA,MAAM;CACR;CACA,WAAW;EACT,QAAQ;GACN,YAAY;GACZ,YAAY;GACZ,OAAO;GACP,YAAY;GACZ,qBAAqB;GACrB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;GAClB,SAAS;GACT,MAAM;GACN,QAAQ;GACR,KAAK;GACL,UAAU;GACV,UAAU;GACV,UAAU;GACV,SAAS;GACT,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;GACT,KAAK;GACL,WAAW;GACX,MAAM;EACR;EACA,MAAM;CACR;CACA,QAAQ;EACN,QAAQ;GACN,YAAY;GACZ,YAAY;GACZ,OAAO;GACP,YAAY;GACZ,qBAAqB;GACrB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;GAClB,SAAS;GACT,MAAM;GACN,QAAQ;GACR,KAAK;GACL,UAAU;GACV,UAAU;GACV,UAAU;GACV,SAAS;GACT,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;GACT,KAAK;GACL,WAAW;GACX,MAAM;EACR;EACA,MAAM;CACR;CACA,WAAW,EACT,QAAQ;EACN,YAAY;EACZ,YAAY;EACZ,OAAO;EACP,YAAY;EACZ,qBAAqB;EACrB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,SAAS;EACT,MAAM;EACN,QAAQ;EACR,KAAK;EACL,UAAU;EACV,UAAU;EACV,UAAU;EACV,SAAS;EACT,QAAQ;EACR,MAAM;EACN,SAAS;EACT,SAAS;EACT,KAAK;EACL,WAAW;EACX,MAAM;CACR,EACF;CACA,SAAS,EACP,QAAQ;EACN,YAAY;EACZ,YAAY;EACZ,OAAO;EACP,YAAY;EACZ,qBAAqB;EACrB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,SAAS;EACT,MAAM;EACN,QAAQ;EACR,KAAK;EACL,UAAU;EACV,UAAU;EACV,UAAU;EACV,SAAS;EACT,QAAQ;EACR,MAAM;EACN,SAAS;EACT,SAAS;EACT,KAAK;EACL,WAAW;EACX,MAAM;CACR,EACF;CACA,QAAQ,EACN,QAAQ;EACN,YAAY;EACZ,YAAY;EACZ,OAAO;EACP,YAAY;EACZ,qBAAqB;EACrB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,SAAS;EACT,MAAM;EACN,QAAQ;EACR,KAAK;EACL,UAAU;EACV,UAAU;EACV,UAAU;EACV,SAAS;EACT,QAAQ;EACR,MAAM;EACN,SAAS;EACT,SAAS;EACT,KAAK;EACL,WAAW;EACX,MAAM;CACR,EACF;CACA,UAAU,EACR,QAAQ;EACN,YAAY;EACZ,YAAY;EACZ,OAAO;EACP,YAAY;EACZ,qBAAqB;EACrB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,SAAS;EACT,MAAM;EACN,QAAQ;EACR,KAAK;EACL,UAAU;EACV,UAAU;EACV,UAAU;EACV,SAAS;EACT,QAAQ;EACR,MAAM;EACN,SAAS;EACT,SAAS;EACT,KAAK;EACL,WAAW;EACX,MAAM;CACR,EACF;CACA,UAAU,EACR,QAAQ;EACN,YAAY;EACZ,YAAY;EACZ,OAAO;EACP,YAAY;EACZ,qBAAqB;EACrB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,SAAS;EACT,MAAM;EACN,QAAQ;EACR,KAAK;EACL,UAAU;EACV,UAAU;EACV,UAAU;EACV,SAAS;EACT,QAAQ;EACR,MAAM;EACN,SAAS;EACT,SAAS;EACT,KAAK;EACL,WAAW;EACX,MAAM;CACR,EACF;CAGA,QAAQ,EACN,QAAQ;EAEN,YAAY;EAEZ,YAAY;EAEZ,OAAO;EAEP,YAAY;EAEZ,qBAAqB;EACrB,kBAAkB;EAElB,kBAAkB;EAClB,kBAAkB;EAElB,SAAS;EAET,MAAM;EAEN,QAAQ;EAER,KAAK;EAEL,UAAU;EAEV,UAAU;EAEV,UAAU;EAEV,SAAS;EAET,QAAQ;EAER,MAAM;EAEN,SAAS;EAET,SAAS;EAET,KAAK;EAEL,WAAW;EAEX,MAAM;CACR,EACF;AACF,GAIM,KAAwB,MAAwC;CACpE,IAAM,IAA0G;EAC9G;GAAE,KAAK,EAAK;GAAS,OAAO,EAAO;EAAQ;EAC3C;GAAE,KAAK;IAAC,EAAK;IAAM,EAAK;IAAM,EAAK;IAAK,EAAK;IAAkB,EAAK;GAAS;GAAG,OAAO,EAAO;EAAK;EACnG;GAAE,KAAK,CAAC,EAAK,SAAS,EAAK,QAAQ;GAAG,OAAO,EAAO;EAAO;EAC3D;GAAE,KAAK,EAAK;GAAQ,OAAO,EAAO;EAAO;EACzC;GAAE,KAAK,CAAC,EAAK,QAAQ,EAAK,OAAO;GAAG,OAAO,EAAO;EAAO;EACzD;GAAE,KAAK;IAAC,EAAK;IAAQ,EAAK;IAAQ,EAAK,QAAQ,EAAK,MAAM;GAAC;GAAG,OAAO,EAAO;EAAO;EACnF;GAAE,KAAK,EAAK,WAAW,EAAK,YAAY;GAAG,OAAO,EAAO;EAAI;EAC7D;GAAE,KAAK,EAAK,MAAM,EAAK,YAAY;GAAG,OAAO,EAAO;EAAS;EAC7D;GAAE,KAAK,EAAK;GAAc,OAAO,EAAO;EAAS;EACjD;GAAE,KAAK,CAAC,EAAK,UAAU,EAAK,SAAS;GAAG,OAAO,EAAO,QAAQ,EAAO;EAAQ;EAC7E;GAAE,KAAK,EAAK;GAAW,OAAO,EAAO,QAAQ,EAAO;EAAI;EACxD;GAAE,KAAK,CAAC,EAAK,QAAQ,EAAK,YAAY,GAAG,EAAK,SAAS;GAAG,OAAO,EAAO;EAAQ;EAChF;GAAE,KAAK,EAAK,WAAW,EAAK,YAAY;GAAG,OAAO,EAAO;EAAS;EAClE;GAAE,KAAK,EAAK;GAAc,OAAO,EAAO;EAAS;EACjD;GAAE,KAAK,EAAK;GAAS,OAAO,EAAO;GAAS,WAAW;EAAS;EAChE;GAAE,KAAK,EAAK;GAAM,OAAO,EAAO;EAAK;EACrC;GAAE,KAAK,EAAK;GAAiB,OAAO,EAAO;EAAS;EACpD;GAAE,KAAK,EAAK;GAAU,OAAO,EAAO;EAAS;EAC7C;GAAE,KAAK,EAAK;GAAS,OAAO,EAAO;EAAQ;EAC3C;GAAE,KAAK,EAAK;GAAc,OAAO,EAAO;EAAQ;EAChD;GAAE,KAAK,EAAK;GAAe,OAAO,EAAO;EAAQ;EACjD;GAAE,KAAK,EAAK;GAAO,OAAO,EAAO;EAAQ;EACzC;GAAE,KAAK,EAAK;GAAO,OAAO,EAAO;EAAQ;EACzC;GAAE,KAAK,EAAK;GAAS,OAAO,EAAO;EAAI;EACvC;GAAE,KAAK,EAAK;GAAe,OAAO,EAAO;EAAU;EACnD;GAAE,KAAK,EAAK;GAAgB,OAAO,EAAO;EAAO;EACjD;GAAE,KAAK,EAAK;GAAM,OAAO,EAAO;GAAM,gBAAgB;EAAY;EAClE;GAAE,KAAK,EAAK;GAAS,OAAO,EAAO;GAAS,YAAY;EAAO;EAC/D;GAAE,KAAK,EAAK;GAAU,WAAW;EAAS;EAC1C;GAAE,KAAK,EAAK;GAAQ,YAAY;EAAO;EACvC;GAAE,KAAK,EAAK;GAAe,gBAAgB;EAAe;CAC5D;CAUA,OARI,EAAO,SACT,EAAM,KAAK;EAAE,KAAK,EAAK;EAAS,OAAO,EAAO;CAAM,CAAC,GAGnD,EAAO,aACT,EAAM,KAAK;EAAE,KAAK,EAAK,QAAQ,EAAK,YAAY;EAAG,OAAO,EAAO;CAAU,CAAC,GAGvE,EAAe,OAAO,CAAK;AACpC,GAIM,KAAqB,MAA+D;CACxF,IAAM,EAAE,WAAQ,YAAS,GAEnB,IAAkC;EACtC,KAAK;GACH,iBAAiB,EAAO;GACxB,OAAO,EAAO;EAChB;EACA,eAAe,EACb,YAAY,EAAO,MACrB;EACA,8BAA8B,EAC5B,iBAAiB,EAAO,MAC1B;EACA,kBAAkB,EAChB,iBAAiB,EAAO,WAC1B;EACA,sBAAsB;GACpB,cAAc;GACd,eAAe;GACf,QAAQ;EACV;EACA,8CAA8C;GAC5C,iBAAiB,EAAO;GACxB,SAAS,EAAO;EAClB;EACA,2BAA2B;GACzB,iBAAiB,EAAO;GACxB,SAAS,EAAO;EAClB;EACA,wCAAwC,EACtC,iBAAiB,EAAO,oBAC1B;EACA,eAAe;GACb,iBAAiB,EAAO;GACxB,OAAO,EAAO;GACd,QAAQ;EACV;CACF;CAMA,OAJI,MACF,EAAW,uCAAuC,EAAE,OAAO,EAAO,iBAAiB,IAG9E,EAAW,MAAM,GAAY,EAAE,QAAK,CAAC;AAC9C,GAIM,oBAAmB,IAAI,IAA4B,GACnD,oBAAiB,IAAI,IAA4B,GAM1C,KAAwB,MAAkC;CACrE,IAAI,EAAiB,IAAI,CAAK,GAC5B,OAAO,EAAiB,IAAI,CAAK;CAInC,IAAM,IAAM,EADG,EAAa,MAAU,EAAa,KACf;CAEpC,OADA,EAAiB,IAAI,GAAO,CAAG,GACxB;AACT,GAMa,KAA4B,MAAkC;CACzE,IAAI,EAAe,IAAI,CAAK,GAC1B,OAAO,EAAe,IAAI,CAAK;CAIjC,IAAM,IAAK,GADI,EAAa,MAAU,EAAa,MACnB,CAAO,MAAM,GACvC,IAAM,EAAmB,CAAE;CAEjC,OADA,EAAe,IAAI,GAAO,CAAG,GACtB;AACT"}
1
+ {"version":3,"file":"themes.js","names":["themeConfigs","createHighlightStyle","specs","tags","colors","HighlightStyle","createEditorTheme","config","baseStyles","dark","EditorView","editorThemeCache","highlightCache","createThemeExtension","theme","ext","createHighlightExtension","hl","syntaxHighlighting"],"sources":["../../../../src/components/pro/CodeEditor/themes.ts"],"sourcesContent":["import { Extension } from '@codemirror/state';\nimport { EditorView } from '@codemirror/view';\nimport { HighlightStyle, syntaxHighlighting } from '@codemirror/language';\nimport { tags } from '@lezer/highlight';\nimport type { EditorTheme } from './types';\n\n// ============= 主题配置类型 =============\n\ninterface ThemeColors {\n background: string;\n foreground: string;\n caret: string;\n activeLine: string;\n selectionBackground: string;\n selectionOpacity: number;\n gutterBackground: string;\n gutterForeground: string;\n // 语法高亮\n keyword: string;\n atom: string;\n number: string;\n def: string;\n variable: string;\n variable2?: string;\n type?: string;\n property: string;\n operator: string;\n comment: string;\n string: string;\n meta: string;\n builtin: string;\n bracket: string;\n tag: string;\n attribute: string;\n link: string;\n error?: string;\n}\n\n// ============= 主题配置 =============\n\nconst themeConfigs: Record<string, { colors: ThemeColors; dark?: boolean }> = {\n light: {\n colors: {\n background: '#ffffff',\n foreground: '#000000',\n caret: '#000000',\n activeLine: 'rgba(0, 0, 0, 0.03)',\n selectionBackground: '#add6ff',\n selectionOpacity: 0.9,\n gutterBackground: '#f8f8f8',\n gutterForeground: '#999',\n keyword: '#0000ff',\n atom: '#219',\n number: '#164',\n def: '#00f',\n variable: '#05a',\n property: '#05a',\n operator: '#000',\n comment: '#708090',\n string: '#a11',\n meta: '#555',\n builtin: '#30a',\n bracket: '#997',\n tag: '#170',\n attribute: '#00c',\n link: '#00e',\n },\n },\n dark: {\n colors: {\n background: '#1e1e1e',\n foreground: '#e0e0e0',\n caret: '#ffffff',\n activeLine: 'rgba(255, 255, 255, 0.08)',\n selectionBackground: '#555555',\n selectionOpacity: 0.85,\n gutterBackground: '#252526',\n gutterForeground: '#858585',\n keyword: '#ff79c6',\n atom: '#bd93f9',\n number: '#ffb86c',\n def: '#50fa7b',\n variable: '#f8f8f2',\n variable2: '#f1fa8c',\n type: '#bd93f9',\n property: '#ffd580',\n operator: '#ff79c6',\n comment: '#6a9955',\n string: '#f1fa8c',\n meta: '#f8f8f2',\n builtin: '#bd93f9',\n bracket: '#f8f8f2',\n tag: '#ff79c6',\n attribute: '#50fa7b',\n link: '#ff79c6',\n error: '#ff5555',\n },\n dark: true,\n },\n cursor: {\n // 参考 Cursor / VS Code 深色:冷调近黑背景、克制的语法配色\n colors: {\n background: '#171922',\n foreground: '#c5cad6',\n caret: '#60a5fa',\n activeLine: 'rgba(96, 165, 250, 0.08)',\n selectionBackground: '#2b3350',\n selectionOpacity: 0.9,\n gutterBackground: '#171922',\n gutterForeground: '#5a6172',\n keyword: '#8ab4f8',\n atom: '#c792ea',\n number: '#f6c177',\n def: '#82aaff',\n variable: '#c5cad6',\n variable2: '#9cdcfe',\n type: '#4ec9b0',\n property: '#9cdcfe',\n operator: '#89ddff',\n comment: '#6a7280',\n string: '#a5d6a7',\n meta: '#c5cad6',\n builtin: '#c792ea',\n bracket: '#c5cad6',\n tag: '#8ab4f8',\n attribute: '#c792ea',\n link: '#60a5fa',\n error: '#f7768e',\n },\n dark: true,\n },\n retro: {\n colors: {\n background: '#2d1b00',\n foreground: '#f5deb3',\n caret: '#ffcc66',\n activeLine: 'rgba(255, 204, 102, 0.1)',\n selectionBackground: '#663300',\n selectionOpacity: 0.8,\n gutterBackground: '#1a0f00',\n gutterForeground: '#997755',\n keyword: '#ff9966',\n atom: '#ffcc99',\n number: '#cc9966',\n def: '#ffaa55',\n variable: '#f5deb3',\n property: '#f5deb3',\n operator: '#ff9966',\n comment: '#8b7355',\n string: '#ffcc66',\n meta: '#cc9966',\n builtin: '#ff9966',\n bracket: '#cc9966',\n tag: '#ff9966',\n attribute: '#ffcc66',\n link: '#ffcc99',\n },\n dark: true,\n },\n cyberpunk: {\n colors: {\n background: '#0d0221',\n foreground: '#f72585',\n caret: '#7209b7',\n activeLine: 'rgba(114, 9, 183, 0.15)',\n selectionBackground: '#3c096c',\n selectionOpacity: 0.8,\n gutterBackground: '#0a0118',\n gutterForeground: '#7209b7',\n keyword: '#f72585',\n atom: '#b5179e',\n number: '#7209b7',\n def: '#f72585',\n variable: '#ffffff',\n property: '#ffffff',\n operator: '#f72585',\n comment: '#560bad',\n string: '#b5179e',\n meta: '#7209b7',\n builtin: '#f72585',\n bracket: '#b5179e',\n tag: '#f72585',\n attribute: '#b5179e',\n link: '#b5179e',\n },\n dark: true,\n },\n matrix: {\n colors: {\n background: '#0d1117',\n foreground: '#00ff00',\n caret: '#00ff00',\n activeLine: 'rgba(0, 255, 0, 0.08)',\n selectionBackground: '#003300',\n selectionOpacity: 0.8,\n gutterBackground: '#0a0e11',\n gutterForeground: '#00aa00',\n keyword: '#00ff00',\n atom: '#00cc00',\n number: '#00ff00',\n def: '#00ff00',\n variable: '#00ee00',\n property: '#00ee00',\n operator: '#00ff00',\n comment: '#008800',\n string: '#00cc00',\n meta: '#00ff00',\n builtin: '#00ff00',\n bracket: '#00dd00',\n tag: '#00ff00',\n attribute: '#00cc00',\n link: '#00ff00',\n },\n dark: true,\n },\n oceanblue: {\n colors: {\n background: '#f0f9ff',\n foreground: '#0c4a6e',\n caret: '#0369a1',\n activeLine: 'rgba(3, 105, 161, 0.05)',\n selectionBackground: '#bae6fd',\n selectionOpacity: 0.9,\n gutterBackground: '#e0f2fe',\n gutterForeground: '#075985',\n keyword: '#0369a1',\n atom: '#0891b2',\n number: '#0e7490',\n def: '#0369a1',\n variable: '#0c4a6e',\n property: '#0c4a6e',\n operator: '#0369a1',\n comment: '#64748b',\n string: '#0891b2',\n meta: '#475569',\n builtin: '#0369a1',\n bracket: '#334155',\n tag: '#0369a1',\n attribute: '#0891b2',\n link: '#0284c7',\n },\n },\n eyecare: {\n colors: {\n background: '#f5f8e8',\n foreground: '#2d4a2b',\n caret: '#4a7c59',\n activeLine: 'rgba(74, 124, 89, 0.06)',\n selectionBackground: '#d4e5d4',\n selectionOpacity: 0.9,\n gutterBackground: '#eef3dc',\n gutterForeground: '#5a8a5f',\n keyword: '#4a7c59',\n atom: '#5a8a5f',\n number: '#6b9b6f',\n def: '#4a7c59',\n variable: '#2d4a2b',\n property: '#2d4a2b',\n operator: '#4a7c59',\n comment: '#7a9d7e',\n string: '#5a8a5f',\n meta: '#5a7a5a',\n builtin: '#4a7c59',\n bracket: '#5a7a5a',\n tag: '#4a7c59',\n attribute: '#5a8a5f',\n link: '#4a7c59',\n },\n },\n ghibli: {\n colors: {\n background: '#fdfbf7',\n foreground: '#5c4a3c',\n caret: '#8b6f4e',\n activeLine: 'rgba(139, 111, 78, 0.05)',\n selectionBackground: '#f0e5d8',\n selectionOpacity: 0.9,\n gutterBackground: '#f7f2ea',\n gutterForeground: '#9b8b78',\n keyword: '#8b6f4e',\n atom: '#a67c52',\n number: '#7ea8a0',\n def: '#8b6f4e',\n variable: '#5c4a3c',\n property: '#5c4a3c',\n operator: '#8b6f4e',\n comment: '#9b8b78',\n string: '#a67c52',\n meta: '#7a6a58',\n builtin: '#8b6f4e',\n bracket: '#7a6a58',\n tag: '#8b6f4e',\n attribute: '#a67c52',\n link: '#7ea8a0',\n },\n },\n pinkgirl: {\n colors: {\n background: '#fff5f7',\n foreground: '#be185d',\n caret: '#db2777',\n activeLine: 'rgba(219, 39, 119, 0.05)',\n selectionBackground: '#fce7f3',\n selectionOpacity: 0.9,\n gutterBackground: '#fef1f5',\n gutterForeground: '#db2777',\n keyword: '#db2777',\n atom: '#ec4899',\n number: '#f472b6',\n def: '#db2777',\n variable: '#be185d',\n property: '#be185d',\n operator: '#db2777',\n comment: '#f9a8d4',\n string: '#ec4899',\n meta: '#be185d',\n builtin: '#db2777',\n bracket: '#be185d',\n tag: '#db2777',\n attribute: '#ec4899',\n link: '#db2777',\n },\n },\n mintgirl: {\n colors: {\n background: '#f0fdf4',\n foreground: '#065f46',\n caret: '#059669',\n activeLine: 'rgba(5, 150, 105, 0.05)',\n selectionBackground: '#d1fae5',\n selectionOpacity: 0.9,\n gutterBackground: '#ecfdf5',\n gutterForeground: '#059669',\n keyword: '#059669',\n atom: '#10b981',\n number: '#34d399',\n def: '#059669',\n variable: '#065f46',\n property: '#065f46',\n operator: '#059669',\n comment: '#6ee7b7',\n string: '#10b981',\n meta: '#047857',\n builtin: '#059669',\n bracket: '#047857',\n tag: '#059669',\n attribute: '#10b981',\n link: '#059669',\n },\n },\n // 五行主题 - 中国传统五行配色\n // 金(白/金) 木(青/绿) 水(黑/蓝) 火(赤/红) 土(黄/棕)\n wuxing: {\n colors: {\n // 背景:米黄色纸张质感(土)\n background: '#f5f0e6',\n // 前景:深棕色(土)\n foreground: '#4a3728',\n // 光标:赤红色(火)\n caret: '#c94c4c',\n // 活跃行:淡黄(土生金)\n activeLine: 'rgba(200, 170, 100, 0.12)',\n // 选中背景:淡青色(木)\n selectionBackground: '#d4e5d8',\n selectionOpacity: 0.85,\n // 行号背景:浅米黄\n gutterBackground: '#ebe5d8',\n gutterForeground: '#8b7355',\n // 关键字:赤红色(火)\n keyword: '#c94c4c',\n // 原子:金色(金)\n atom: '#b8860b',\n // 数字:深蓝(水)\n number: '#2f5496',\n // 定义:青绿色(木)\n def: '#2e7d32',\n // 变量:深棕(土)\n variable: '#5c4033',\n // 属性:棕黄(土)\n property: '#8b6914',\n // 运算符:赤色(火)\n operator: '#b5533c',\n // 注释:灰蓝(水生木)\n comment: '#6b8e8e',\n // 字符串:青绿(木)\n string: '#3d7a5a',\n // 元信息:深棕\n meta: '#6b5344',\n // 内置:金橙(金生水)\n builtin: '#cd853f',\n // 括号:深灰蓝(水)\n bracket: '#4a6670',\n // 标签:赤色(火)\n tag: '#c94c4c',\n // 属性名:青色(木)\n attribute: '#2e8b57',\n // 链接:深蓝(水)\n link: '#2f5496',\n },\n },\n};\n\n// ============= 语法高亮样式创建器 =============\n\nconst createHighlightStyle = (colors: ThemeColors): HighlightStyle => {\n const specs: { tag: any; color?: string; fontStyle?: string; fontWeight?: string; textDecoration?: string }[] = [\n { tag: tags.keyword, color: colors.keyword },\n { tag: [tags.atom, tags.bool, tags.url, tags.contentSeparator, tags.labelName], color: colors.atom },\n { tag: [tags.literal, tags.inserted], color: colors.number },\n { tag: tags.number, color: colors.number },\n { tag: [tags.string, tags.deleted], color: colors.string },\n { tag: [tags.regexp, tags.escape, tags.special(tags.string)], color: colors.string },\n { tag: tags.definition(tags.variableName), color: colors.def },\n { tag: tags.local(tags.variableName), color: colors.variable },\n { tag: tags.variableName, color: colors.variable },\n { tag: [tags.typeName, tags.namespace], color: colors.type || colors.builtin },\n { tag: tags.className, color: colors.type || colors.def },\n { tag: [tags.special(tags.variableName), tags.macroName], color: colors.builtin },\n { tag: tags.definition(tags.propertyName), color: colors.property },\n { tag: tags.propertyName, color: colors.property },\n { tag: tags.comment, color: colors.comment, fontStyle: 'italic' },\n { tag: tags.meta, color: colors.meta },\n { tag: tags.operatorKeyword, color: colors.operator },\n { tag: tags.operator, color: colors.operator },\n { tag: tags.bracket, color: colors.bracket },\n { tag: tags.angleBracket, color: colors.bracket },\n { tag: tags.squareBracket, color: colors.bracket },\n { tag: tags.paren, color: colors.bracket },\n { tag: tags.brace, color: colors.bracket },\n { tag: tags.tagName, color: colors.tag },\n { tag: tags.attributeName, color: colors.attribute },\n { tag: tags.attributeValue, color: colors.string },\n { tag: tags.link, color: colors.link, textDecoration: 'underline' },\n { tag: tags.heading, color: colors.keyword, fontWeight: 'bold' },\n { tag: tags.emphasis, fontStyle: 'italic' },\n { tag: tags.strong, fontWeight: 'bold' },\n { tag: tags.strikethrough, textDecoration: 'line-through' },\n ];\n\n if (colors.error) {\n specs.push({ tag: tags.invalid, color: colors.error });\n }\n\n if (colors.variable2) {\n specs.push({ tag: tags.special(tags.variableName), color: colors.variable2 });\n }\n\n return HighlightStyle.define(specs);\n};\n\n// ============= 编辑器外观主题创建器 =============\n\nconst createEditorTheme = (config: { colors: ThemeColors; dark?: boolean }): Extension => {\n const { colors, dark } = config;\n\n const baseStyles: Record<string, any> = {\n '&': {\n backgroundColor: colors.background,\n color: colors.foreground,\n },\n '.cm-content': {\n caretColor: colors.caret,\n },\n '.cm-cursor, .cm-dropCursor': {\n borderLeftColor: colors.caret,\n },\n '.cm-activeLine': {\n backgroundColor: colors.activeLine,\n },\n '.cm-selectionLayer': {\n mixBlendMode: 'normal',\n pointerEvents: 'none',\n zIndex: 10,\n },\n '.cm-selectionLayer .cm-selectionBackground': {\n backgroundColor: colors.selectionBackground,\n opacity: colors.selectionOpacity,\n },\n '.cm-selectionBackground': {\n backgroundColor: colors.selectionBackground,\n opacity: colors.selectionOpacity,\n },\n '&.cm-focused .cm-selectionBackground': {\n backgroundColor: colors.selectionBackground,\n },\n '.cm-gutters': {\n backgroundColor: colors.gutterBackground,\n color: colors.gutterForeground,\n border: 'none',\n },\n };\n\n if (dark) {\n baseStyles['.cm-lineNumbers .cm-gutterElement'] = { color: colors.gutterForeground };\n }\n\n return EditorView.theme(baseStyles, { dark });\n};\n\n// ============= 缓存 =============\n\nconst editorThemeCache = new Map<EditorTheme, Extension>();\nconst highlightCache = new Map<EditorTheme, Extension>();\n\n/**\n * 创建编辑器外观主题(背景色、光标色等)\n * 放入 themeCompartment\n */\nexport const createThemeExtension = (theme: EditorTheme): Extension => {\n if (editorThemeCache.has(theme)) {\n return editorThemeCache.get(theme)!;\n }\n\n const config = themeConfigs[theme] || themeConfigs.light;\n const ext = createEditorTheme(config);\n editorThemeCache.set(theme, ext);\n return ext;\n};\n\n/**\n * 创建语法高亮扩展\n * 放入 highlightCompartment\n */\nexport const createHighlightExtension = (theme: EditorTheme): Extension => {\n if (highlightCache.has(theme)) {\n return highlightCache.get(theme)!;\n }\n\n const config = themeConfigs[theme] || themeConfigs.light;\n const hl = createHighlightStyle(config.colors);\n const ext = syntaxHighlighting(hl);\n highlightCache.set(theme, ext);\n return ext;\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":[],"sources":["../../../../src/components/pro/CodeEditor/utils.ts"],"sourcesContent":["import type { VariableInfo, OutlineItem, LanguageType } from './types';\n\n// ============= 收集变量信息 =============\n\nexport const collectVariables = (code: string, language: LanguageType): VariableInfo[] => {\n const variables: VariableInfo[] = [];\n const lines = code.split('\\n');\n\n if (language === 'javascript' || language === 'typescript' || language === 'jsx' || language === 'tsx') {\n lines.forEach((line, index) => {\n const trimmedLine = line.trim();\n \n // Classes\n const classMatch = /^class\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/.exec(trimmedLine);\n if (classMatch) {\n variables.push({\n name: classMatch[1],\n line: index + 1,\n type: 'class',\n });\n }\n\n // Interfaces (TypeScript)\n const interfaceMatch = /^(?:export\\s+)?interface\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/.exec(trimmedLine);\n if (interfaceMatch) {\n variables.push({\n name: interfaceMatch[1],\n line: index + 1,\n type: 'interface',\n });\n }\n\n // Types (TypeScript)\n const typeMatch = /^(?:export\\s+)?type\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=/.exec(trimmedLine);\n if (typeMatch) {\n variables.push({\n name: typeMatch[1],\n line: index + 1,\n type: 'type',\n });\n }\n\n // Functions\n const functionMatch = /^(?:export\\s+)?(?:async\\s+)?function\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/.exec(trimmedLine);\n if (functionMatch) {\n variables.push({\n name: functionMatch[1],\n line: index + 1,\n type: 'function',\n });\n }\n\n // Arrow functions and constants\n const arrowFuncMatch = /^(?:export\\s+)?const\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=\\s*(?:\\([^)]*\\)|[a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=>/.exec(trimmedLine);\n if (arrowFuncMatch) {\n variables.push({\n name: arrowFuncMatch[1],\n line: index + 1,\n type: 'function',\n });\n return; // Don't process as constant\n }\n\n // Constants (const with uppercase or specific patterns)\n const constMatch = /^(?:export\\s+)?const\\s+([A-Z_$][A-Z0-9_$]*)\\s*=/.exec(trimmedLine);\n if (constMatch) {\n variables.push({\n name: constMatch[1],\n line: index + 1,\n type: 'constant',\n });\n return;\n }\n\n // Regular const variables\n const constVarMatch = /^(?:export\\s+)?const\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=/.exec(trimmedLine);\n if (constVarMatch) {\n variables.push({\n name: constVarMatch[1],\n line: index + 1,\n type: 'variable',\n });\n return;\n }\n\n // Let and var\n const letVarMatch = /^(?:export\\s+)?(?:let|var)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/.exec(trimmedLine);\n if (letVarMatch) {\n variables.push({\n name: letVarMatch[1],\n line: index + 1,\n type: 'variable',\n });\n }\n\n // Methods in classes (simplified detection)\n if (/^\\s+(?:async\\s+)?([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*\\([^)]*\\)\\s*[{:]/.test(line)) {\n const methodMatch = /^\\s+(?:async\\s+)?([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*\\(/.exec(line);\n if (methodMatch && !['if', 'for', 'while', 'switch', 'catch'].includes(methodMatch[1])) {\n variables.push({\n name: methodMatch[1],\n line: index + 1,\n type: 'method',\n });\n }\n }\n });\n } else if (language === 'python') {\n let inClass = false;\n lines.forEach((line, index) => {\n const trimmedLine = line.trim();\n \n // Skip empty lines and comments\n if (!trimmedLine || trimmedLine.startsWith('#')) {\n return;\n }\n\n // Classes\n const classMatch = /^class\\s+([a-zA-Z_][a-zA-Z0-9_]*)/.exec(trimmedLine);\n if (classMatch) {\n variables.push({\n name: classMatch[1],\n line: index + 1,\n type: 'class',\n });\n inClass = true;\n return;\n }\n\n // Functions/Methods\n const defMatch = /^def\\s+([a-zA-Z_][a-zA-Z0-9_]*)/.exec(trimmedLine);\n if (defMatch) {\n // Check if it's a method by looking at indentation\n const isMethod = /^\\s+def\\s+/.test(line) && inClass;\n variables.push({\n name: defMatch[1],\n line: index + 1,\n type: isMethod ? 'method' : 'function',\n });\n return;\n }\n\n // Constants (uppercase variables)\n const constMatch = /^([A-Z_][A-Z0-9_]*)\\s*=/.exec(trimmedLine);\n if (constMatch) {\n variables.push({\n name: constMatch[1],\n line: index + 1,\n type: 'constant',\n });\n return;\n }\n\n // Regular variables (at module level or in functions)\n const varMatch = /^([a-z_][a-zA-Z0-9_]*)\\s*=/.exec(trimmedLine);\n if (varMatch && !trimmedLine.startsWith('def ') && !trimmedLine.startsWith('class ')) {\n variables.push({\n name: varMatch[1],\n line: index + 1,\n type: 'variable',\n });\n return;\n }\n\n // Reset class context on dedent (non-indented line that's not def/class)\n if (inClass && !line.startsWith(' ') && !line.startsWith('\\t') && trimmedLine) {\n inClass = false;\n }\n });\n }\n\n return variables;\n};\n\n// ============= 生成大纲 =============\n\nexport const generateOutline = (code: string, language: LanguageType): OutlineItem[] => {\n const outline: OutlineItem[] = [];\n const lines = code.split('\\n');\n\n if (language === 'javascript' || language === 'typescript' || language === 'jsx' || language === 'tsx') {\n const functionRegex = /(?:function|const|let|var)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*[=]?\\s*(?:\\([^)]*\\)|async\\s*\\([^)]*\\))\\s*(?:=>|{)/g;\n const classRegex = /class\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;\n const interfaceRegex = /interface\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;\n const typeRegex = /type\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;\n\n lines.forEach((line, index) => {\n let match;\n \n // 类\n while ((match = classRegex.exec(line)) !== null) {\n outline.push({\n name: match[1],\n line: index + 1,\n type: 'class',\n children: [],\n });\n }\n\n // 接口\n while ((match = interfaceRegex.exec(line)) !== null) {\n outline.push({\n name: match[1],\n line: index + 1,\n type: 'interface',\n });\n }\n\n // 类型\n while ((match = typeRegex.exec(line)) !== null) {\n outline.push({\n name: match[1],\n line: index + 1,\n type: 'type',\n });\n }\n\n // 函数\n functionRegex.lastIndex = 0;\n while ((match = functionRegex.exec(line)) !== null) {\n outline.push({\n name: match[1],\n line: index + 1,\n type: 'function',\n });\n }\n });\n } else if (language === 'python') {\n const defRegex = /def\\s+([a-zA-Z_][a-zA-Z0-9_]*)/g;\n const classRegex = /class\\s+([a-zA-Z_][a-zA-Z0-9_]*)/g;\n\n let currentClass: OutlineItem | null = null;\n\n lines.forEach((line, index) => {\n let match;\n\n // 类\n classRegex.lastIndex = 0;\n if ((match = classRegex.exec(line)) !== null) {\n currentClass = {\n name: match[1],\n line: index + 1,\n type: 'class',\n children: [],\n };\n outline.push(currentClass);\n }\n\n // 函数/方法\n defRegex.lastIndex = 0;\n if ((match = defRegex.exec(line)) !== null) {\n const item: OutlineItem = {\n name: match[1],\n line: index + 1,\n type: currentClass && line.startsWith(' ') ? 'method' : 'function',\n };\n\n if (currentClass && line.startsWith(' ')) {\n currentClass.children?.push(item);\n } else {\n outline.push(item);\n currentClass = null;\n }\n }\n });\n }\n\n return outline;\n};\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","names":["collectVariables","variables","lines","code","language","trimmedLine","line","classMatch","index","interfaceMatch","typeMatch","functionMatch","arrowFuncMatch","constMatch","constVarMatch","letVarMatch","methodMatch","inClass","defMatch","isMethod","varMatch","generateOutline","outline","functionRegex","classRegex","interfaceRegex","typeRegex","match","defRegex","currentClass","item"],"sources":["../../../../src/components/pro/CodeEditor/utils.ts"],"sourcesContent":["import type { VariableInfo, OutlineItem, LanguageType } from './types';\n\n// ============= 收集变量信息 =============\n\nexport const collectVariables = (code: string, language: LanguageType): VariableInfo[] => {\n const variables: VariableInfo[] = [];\n const lines = code.split('\\n');\n\n if (language === 'javascript' || language === 'typescript' || language === 'jsx' || language === 'tsx') {\n lines.forEach((line, index) => {\n const trimmedLine = line.trim();\n \n // Classes\n const classMatch = /^class\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/.exec(trimmedLine);\n if (classMatch) {\n variables.push({\n name: classMatch[1],\n line: index + 1,\n type: 'class',\n });\n }\n\n // Interfaces (TypeScript)\n const interfaceMatch = /^(?:export\\s+)?interface\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/.exec(trimmedLine);\n if (interfaceMatch) {\n variables.push({\n name: interfaceMatch[1],\n line: index + 1,\n type: 'interface',\n });\n }\n\n // Types (TypeScript)\n const typeMatch = /^(?:export\\s+)?type\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=/.exec(trimmedLine);\n if (typeMatch) {\n variables.push({\n name: typeMatch[1],\n line: index + 1,\n type: 'type',\n });\n }\n\n // Functions\n const functionMatch = /^(?:export\\s+)?(?:async\\s+)?function\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/.exec(trimmedLine);\n if (functionMatch) {\n variables.push({\n name: functionMatch[1],\n line: index + 1,\n type: 'function',\n });\n }\n\n // Arrow functions and constants\n const arrowFuncMatch = /^(?:export\\s+)?const\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=\\s*(?:\\([^)]*\\)|[a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=>/.exec(trimmedLine);\n if (arrowFuncMatch) {\n variables.push({\n name: arrowFuncMatch[1],\n line: index + 1,\n type: 'function',\n });\n return; // Don't process as constant\n }\n\n // Constants (const with uppercase or specific patterns)\n const constMatch = /^(?:export\\s+)?const\\s+([A-Z_$][A-Z0-9_$]*)\\s*=/.exec(trimmedLine);\n if (constMatch) {\n variables.push({\n name: constMatch[1],\n line: index + 1,\n type: 'constant',\n });\n return;\n }\n\n // Regular const variables\n const constVarMatch = /^(?:export\\s+)?const\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=/.exec(trimmedLine);\n if (constVarMatch) {\n variables.push({\n name: constVarMatch[1],\n line: index + 1,\n type: 'variable',\n });\n return;\n }\n\n // Let and var\n const letVarMatch = /^(?:export\\s+)?(?:let|var)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/.exec(trimmedLine);\n if (letVarMatch) {\n variables.push({\n name: letVarMatch[1],\n line: index + 1,\n type: 'variable',\n });\n }\n\n // Methods in classes (simplified detection)\n if (/^\\s+(?:async\\s+)?([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*\\([^)]*\\)\\s*[{:]/.test(line)) {\n const methodMatch = /^\\s+(?:async\\s+)?([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*\\(/.exec(line);\n if (methodMatch && !['if', 'for', 'while', 'switch', 'catch'].includes(methodMatch[1])) {\n variables.push({\n name: methodMatch[1],\n line: index + 1,\n type: 'method',\n });\n }\n }\n });\n } else if (language === 'python') {\n let inClass = false;\n lines.forEach((line, index) => {\n const trimmedLine = line.trim();\n \n // Skip empty lines and comments\n if (!trimmedLine || trimmedLine.startsWith('#')) {\n return;\n }\n\n // Classes\n const classMatch = /^class\\s+([a-zA-Z_][a-zA-Z0-9_]*)/.exec(trimmedLine);\n if (classMatch) {\n variables.push({\n name: classMatch[1],\n line: index + 1,\n type: 'class',\n });\n inClass = true;\n return;\n }\n\n // Functions/Methods\n const defMatch = /^def\\s+([a-zA-Z_][a-zA-Z0-9_]*)/.exec(trimmedLine);\n if (defMatch) {\n // Check if it's a method by looking at indentation\n const isMethod = /^\\s+def\\s+/.test(line) && inClass;\n variables.push({\n name: defMatch[1],\n line: index + 1,\n type: isMethod ? 'method' : 'function',\n });\n return;\n }\n\n // Constants (uppercase variables)\n const constMatch = /^([A-Z_][A-Z0-9_]*)\\s*=/.exec(trimmedLine);\n if (constMatch) {\n variables.push({\n name: constMatch[1],\n line: index + 1,\n type: 'constant',\n });\n return;\n }\n\n // Regular variables (at module level or in functions)\n const varMatch = /^([a-z_][a-zA-Z0-9_]*)\\s*=/.exec(trimmedLine);\n if (varMatch && !trimmedLine.startsWith('def ') && !trimmedLine.startsWith('class ')) {\n variables.push({\n name: varMatch[1],\n line: index + 1,\n type: 'variable',\n });\n return;\n }\n\n // Reset class context on dedent (non-indented line that's not def/class)\n if (inClass && !line.startsWith(' ') && !line.startsWith('\\t') && trimmedLine) {\n inClass = false;\n }\n });\n }\n\n return variables;\n};\n\n// ============= 生成大纲 =============\n\nexport const generateOutline = (code: string, language: LanguageType): OutlineItem[] => {\n const outline: OutlineItem[] = [];\n const lines = code.split('\\n');\n\n if (language === 'javascript' || language === 'typescript' || language === 'jsx' || language === 'tsx') {\n const functionRegex = /(?:function|const|let|var)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*[=]?\\s*(?:\\([^)]*\\)|async\\s*\\([^)]*\\))\\s*(?:=>|{)/g;\n const classRegex = /class\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;\n const interfaceRegex = /interface\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;\n const typeRegex = /type\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;\n\n lines.forEach((line, index) => {\n let match;\n \n // 类\n while ((match = classRegex.exec(line)) !== null) {\n outline.push({\n name: match[1],\n line: index + 1,\n type: 'class',\n children: [],\n });\n }\n\n // 接口\n while ((match = interfaceRegex.exec(line)) !== null) {\n outline.push({\n name: match[1],\n line: index + 1,\n type: 'interface',\n });\n }\n\n // 类型\n while ((match = typeRegex.exec(line)) !== null) {\n outline.push({\n name: match[1],\n line: index + 1,\n type: 'type',\n });\n }\n\n // 函数\n functionRegex.lastIndex = 0;\n while ((match = functionRegex.exec(line)) !== null) {\n outline.push({\n name: match[1],\n line: index + 1,\n type: 'function',\n });\n }\n });\n } else if (language === 'python') {\n const defRegex = /def\\s+([a-zA-Z_][a-zA-Z0-9_]*)/g;\n const classRegex = /class\\s+([a-zA-Z_][a-zA-Z0-9_]*)/g;\n\n let currentClass: OutlineItem | null = null;\n\n lines.forEach((line, index) => {\n let match;\n\n // 类\n classRegex.lastIndex = 0;\n if ((match = classRegex.exec(line)) !== null) {\n currentClass = {\n name: match[1],\n line: index + 1,\n type: 'class',\n children: [],\n };\n outline.push(currentClass);\n }\n\n // 函数/方法\n defRegex.lastIndex = 0;\n if ((match = defRegex.exec(line)) !== null) {\n const item: OutlineItem = {\n name: match[1],\n line: index + 1,\n type: currentClass && line.startsWith(' ') ? 'method' : 'function',\n };\n\n if (currentClass && line.startsWith(' ')) {\n currentClass.children?.push(item);\n } else {\n outline.push(item);\n currentClass = null;\n }\n }\n });\n }\n\n return outline;\n};\n\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable.js","names":[],"sources":["../../../../src/components/pro/DataTable/DataTable.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport Table from '../../Table';\nimport { TableToolbar } from './components/TableToolbar';\nimport { TableHeader } from './components/TableHeader';\nimport { TableBody } from './components/TableBody';\nimport { TablePagination } from './components/TablePagination';\nimport { DataTableProps, DataTableViewMode } from './types';\nimport type {\n DataTableApi,\n DataTableCellContext,\n\n DataTableMenuItem,\n} from './extension';\nimport { treeRowAnimationStyles } from './treeDataUtils';\nimport { useDataTableModel } from './useDataTableModel';\nimport { useColumnDragReorder } from './useColumnDragReorder';\n\nexport * from './types';\n\nfunction DataTable<T extends object>(props: DataTableProps<T>) {\n const {\n data,\n columns,\n className = '',\n viewMode: controlledViewMode,\n defaultViewMode = 'table',\n onViewModeChange,\n enableViewSwitcher = false,\n viewSwitcherLabels,\n cardOptions,\n enableSorting = true,\n enablePagination = true,\n enableColumnReordering = true,\n enableExpanding = false,\n indentSize = 16,\n toolbar = {\n enabled: false,\n enableColumnSelector: false,\n enableFiltering: false,\n enableBulkActions: false,\n },\n customFilterPanel,\n onRowClick,\n onRowDoubleClick,\n onRowMouseEnter,\n onRowMouseLeave,\n onCellClick,\n onCellDoubleClick,\n onCellMouseEnter,\n onCellMouseLeave,\n onColumnMouseEnter,\n onColumnMouseLeave,\n extensions = [],\n } = props;\n const {\n table, rowSelection, visibilityState, columnOrderState, setColumnOrderState,\n expandedRowsState, handleRowExpand, resolveRowId, handlePaginationChange,\n } = useDataTableModel(props);\n const [activeFilter, setActiveFilter] = useState<string | null>(null);\n const [internalViewMode, setInternalViewMode] = useState<DataTableViewMode>(defaultViewMode);\n const viewMode = controlledViewMode ?? internalViewMode;\n const changeViewMode = (next: DataTableViewMode) => {\n if (next === viewMode) return;\n if (controlledViewMode === undefined) setInternalViewMode(next);\n onViewModeChange?.(next);\n };\n\n const {\n draggedColumnId,\n handleDragStart,\n handleDragOver,\n handleDrop,\n } = useColumnDragReorder(columnOrderState, setColumnOrderState);\n\n // The v9 table instance is stable: take fresh row snapshots on every render,\n // including sort/filter/page/expand changes, not only selection changes.\n const extensionApi: DataTableApi<T> = {\n table,\n data,\n rows: table.getRowModel().rows,\n selectedRows: table.getSelectedRowModel().flatRows.map(row => row.original),\n getRowId: resolveRowId,\n };\n\n // --- 右键菜单(由扩展贡献) --------------------------------------------\n const [contextMenu, setContextMenu] = useState<{\n x: number;\n y: number;\n items: DataTableMenuItem<T>[];\n ctx: DataTableCellContext<T>;\n } | null>(null);\n\n useEffect(() => {\n if (!contextMenu) return;\n const close = () => setContextMenu(null);\n window.addEventListener('click', close);\n window.addEventListener('scroll', close, true);\n return () => {\n window.removeEventListener('click', close);\n window.removeEventListener('scroll', close, true);\n };\n }, [contextMenu]);\n\n const handleCellContextMenu = useCallback(\n (e: React.MouseEvent, row: T, column: any, rowIndex: number) => {\n if (extensions.length === 0) return;\n const columnId = column?.id ?? '';\n const value =\n column?.id != null ? (row as any)[column.id] : undefined;\n const ctx: DataTableCellContext<T> = {\n value,\n row,\n rowId: resolveRowId(row, rowIndex),\n rowIndex,\n columnId,\n };\n const items = extensions.flatMap(\n (ext) => ext.contextMenu?.(ctx, extensionApi) ?? [],\n );\n if (!items.length) return;\n e.preventDefault();\n setContextMenu({ x: e.clientX, y: e.clientY, items, ctx });\n },\n [extensions, extensionApi, resolveRowId],\n );\n\n // 收集工具栏 / 底部 / 主体接管的扩展贡献。\n const toolbarExtras = extensions\n .map((ext) =>\n ext.toolbar ? { name: ext.name, node: ext.toolbar(extensionApi) } : null,\n )\n .filter((x): x is { name: string; node: React.ReactNode } => !!x && !!x.node);\n\n const footerExtras = extensions\n .map((ext) =>\n ext.footer ? { name: ext.name, node: ext.footer(extensionApi) } : null,\n )\n .filter((x): x is { name: string; node: React.ReactNode } => !!x && !!x.node);\n\n let overrideContent: React.ReactNode | undefined = undefined;\n for (const ext of extensions) {\n const out = ext.renderContent?.(extensionApi);\n if (out !== undefined) {\n overrideContent = out;\n break;\n }\n }\n\n\n const toggleColumnVisibility = (columnId: string) => {\n table.getColumn(columnId)?.toggleVisibility();\n };\n\n useEffect(() => {\n const styleElement = document.createElement('style');\n styleElement.textContent = treeRowAnimationStyles;\n document.head.appendChild(styleElement);\n return () => { document.head.removeChild(styleElement); };\n }, []);\n\n return (\n <div className={`w-full ${className}`}>\n <TableToolbar\n toolbar={toolbar}\n table={table}\n columns={columns}\n columnOrderState={columnOrderState}\n visibilityState={visibilityState}\n activeFilter={activeFilter}\n setActiveFilter={setActiveFilter}\n customFilterPanel={customFilterPanel}\n draggedColumnId={draggedColumnId}\n handleDragStart={handleDragStart}\n toggleColumnVisibility={toggleColumnVisibility}\n rowSelection={rowSelection}\n data={data}\n enableColumnReordering={enableColumnReordering}\n handleDrop={handleDrop}\n viewSwitcher={enableViewSwitcher && overrideContent === undefined ? (\n <div role=\"group\" aria-label={viewSwitcherLabels?.label ?? '显示方式'} className=\"flex items-center gap-1\">\n {(['table', 'card'] as const).map(mode => (\n <button\n key={mode}\n type=\"button\"\n className={`btn btn-sm ${viewMode === mode ? 'btn-neutral' : 'btn-ghost'}`}\n aria-pressed={viewMode === mode}\n disabled={controlledViewMode !== undefined && !onViewModeChange}\n onClick={() => changeViewMode(mode)}\n >\n {viewSwitcherLabels?.[mode] ?? (mode === 'table' ? '表格' : '卡片')}\n </button>\n ))}\n </div>\n ) : undefined}\n />\n\n {/* 扩展贡献的工具栏控件 */}\n {toolbarExtras.length > 0 && (\n <div className=\"flex flex-wrap items-start gap-3 mb-4\">\n {toolbarExtras.map((item) => (\n <React.Fragment key={item.name}>{item.node}</React.Fragment>\n ))}\n </div>\n )}\n\n {overrideContent !== undefined ? (\n // 扩展接管了主体渲染(如 Pivot 透视模式)。\n <div className=\"w-full\">{overrideContent}</div>\n ) : (\n <>\n <div className=\"overflow-x-auto\">\n <Table className=\"table-sm w-full\" card={viewMode === 'card'} cardOptions={cardOptions}>\n <TableHeader\n table={table}\n visibilityState={visibilityState}\n enableSorting={enableSorting}\n enableColumnReordering={enableColumnReordering}\n draggedColumnId={draggedColumnId}\n onColumnMouseEnter={onColumnMouseEnter}\n onColumnMouseLeave={onColumnMouseLeave}\n handleDragStart={handleDragStart}\n handleDragOver={handleDragOver}\n handleDrop={handleDrop}\n />\n <TableBody\n table={table}\n card={viewMode === 'card'}\n fieldLabels={cardOptions?.fieldLabels}\n expandedRowsState={expandedRowsState}\n onRowClick={onRowClick}\n onRowDoubleClick={onRowDoubleClick}\n onRowMouseEnter={onRowMouseEnter}\n onRowMouseLeave={onRowMouseLeave}\n onCellClick={onCellClick}\n onCellDoubleClick={onCellDoubleClick}\n onCellMouseEnter={onCellMouseEnter}\n onCellMouseLeave={onCellMouseLeave}\n enableExpanding={enableExpanding}\n indentSize={indentSize}\n handleRowExpand={handleRowExpand}\n extensions={extensions}\n extensionApi={extensionApi}\n getRowId={resolveRowId}\n onCellContextMenu={handleCellContextMenu}\n />\n </Table>\n </div>\n\n <TablePagination\n enablePagination={enablePagination}\n table={table}\n onPaginationChange={handlePaginationChange}\n />\n </>\n )}\n\n {/* 扩展贡献的底部控件 */}\n {footerExtras.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-3 mt-4\">\n {footerExtras.map((item) => (\n <React.Fragment key={item.name}>{item.node}</React.Fragment>\n ))}\n </div>\n )}\n\n {/* 扩展贡献的右键菜单 */}\n {contextMenu && (\n <ul\n className=\"menu bg-base-100 rounded-box shadow-lg border border-base-300 z-1000 p-1\"\n style={{\n position: 'fixed',\n top: contextMenu.y,\n left: contextMenu.x,\n minWidth: 160,\n }}\n >\n {contextMenu.items.map((item) =>\n item.separator ? (\n <li key={item.key} className=\"my-1 border-t border-base-300\" />\n ) : (\n <li key={item.key}>\n <button\n type=\"button\"\n disabled={item.disabled}\n onClick={() => {\n item.onSelect?.(contextMenu.ctx);\n setContextMenu(null);\n }}\n >\n {item.label}\n </button>\n </li>\n ),\n )}\n </ul>\n )}\n </div>\n );\n}\n\nexport default DataTable;\n"],"mappings":"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"}
1
+ {"version":3,"file":"DataTable.js","names":["_Fragment","Table","TableWithCompounds","React","DataTable","controlledViewMode","props","useDataTableModel","activeFilter","setActiveFilter","useState","internalViewMode","setInternalViewMode","defaultViewMode","viewMode","changeViewMode","next","onViewModeChange","useColumnDragReorder","columnOrderState","setColumnOrderState","extensionApi","table","row","resolveRowId","contextMenu","setContextMenu","close","handleCellContextMenu","useCallback","extensions","columnId","column","ctx","rowIndex","items","ext","toolbarExtras","x","footerExtras","overrideContent","out","useEffect","styleElement","treeRowAnimationStyles","className","TableToolbar","enableViewSwitcher","viewSwitcherLabels","mode","item","Fragment","TableHeader","TableBody","cardOptions","TablePagination","handlePaginationChange"],"sources":["../../../../src/components/pro/DataTable/DataTable.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport Table from '../../Table';\nimport { TableToolbar } from './components/TableToolbar';\nimport { TableHeader } from './components/TableHeader';\nimport { TableBody } from './components/TableBody';\nimport { TablePagination } from './components/TablePagination';\nimport { DataTableProps, DataTableViewMode } from './types';\nimport type {\n DataTableApi,\n DataTableCellContext,\n\n DataTableMenuItem,\n} from './extension';\nimport { treeRowAnimationStyles } from './treeDataUtils';\nimport { useDataTableModel } from './useDataTableModel';\nimport { useColumnDragReorder } from './useColumnDragReorder';\n\nexport * from './types';\n\nfunction DataTable<T extends object>(props: DataTableProps<T>) {\n const {\n data,\n columns,\n className = '',\n viewMode: controlledViewMode,\n defaultViewMode = 'table',\n onViewModeChange,\n enableViewSwitcher = false,\n viewSwitcherLabels,\n cardOptions,\n enableSorting = true,\n enablePagination = true,\n enableColumnReordering = true,\n enableExpanding = false,\n indentSize = 16,\n toolbar = {\n enabled: false,\n enableColumnSelector: false,\n enableFiltering: false,\n enableBulkActions: false,\n },\n customFilterPanel,\n onRowClick,\n onRowDoubleClick,\n onRowMouseEnter,\n onRowMouseLeave,\n onCellClick,\n onCellDoubleClick,\n onCellMouseEnter,\n onCellMouseLeave,\n onColumnMouseEnter,\n onColumnMouseLeave,\n extensions = [],\n } = props;\n const {\n table, rowSelection, visibilityState, columnOrderState, setColumnOrderState,\n expandedRowsState, handleRowExpand, resolveRowId, handlePaginationChange,\n } = useDataTableModel(props);\n const [activeFilter, setActiveFilter] = useState<string | null>(null);\n const [internalViewMode, setInternalViewMode] = useState<DataTableViewMode>(defaultViewMode);\n const viewMode = controlledViewMode ?? internalViewMode;\n const changeViewMode = (next: DataTableViewMode) => {\n if (next === viewMode) return;\n if (controlledViewMode === undefined) setInternalViewMode(next);\n onViewModeChange?.(next);\n };\n\n const {\n draggedColumnId,\n handleDragStart,\n handleDragOver,\n handleDrop,\n } = useColumnDragReorder(columnOrderState, setColumnOrderState);\n\n // The v9 table instance is stable: take fresh row snapshots on every render,\n // including sort/filter/page/expand changes, not only selection changes.\n const extensionApi: DataTableApi<T> = {\n table,\n data,\n rows: table.getRowModel().rows,\n selectedRows: table.getSelectedRowModel().flatRows.map(row => row.original),\n getRowId: resolveRowId,\n };\n\n // --- 右键菜单(由扩展贡献) --------------------------------------------\n const [contextMenu, setContextMenu] = useState<{\n x: number;\n y: number;\n items: DataTableMenuItem<T>[];\n ctx: DataTableCellContext<T>;\n } | null>(null);\n\n useEffect(() => {\n if (!contextMenu) return;\n const close = () => setContextMenu(null);\n window.addEventListener('click', close);\n window.addEventListener('scroll', close, true);\n return () => {\n window.removeEventListener('click', close);\n window.removeEventListener('scroll', close, true);\n };\n }, [contextMenu]);\n\n const handleCellContextMenu = useCallback(\n (e: React.MouseEvent, row: T, column: any, rowIndex: number) => {\n if (extensions.length === 0) return;\n const columnId = column?.id ?? '';\n const value =\n column?.id != null ? (row as any)[column.id] : undefined;\n const ctx: DataTableCellContext<T> = {\n value,\n row,\n rowId: resolveRowId(row, rowIndex),\n rowIndex,\n columnId,\n };\n const items = extensions.flatMap(\n (ext) => ext.contextMenu?.(ctx, extensionApi) ?? [],\n );\n if (!items.length) return;\n e.preventDefault();\n setContextMenu({ x: e.clientX, y: e.clientY, items, ctx });\n },\n [extensions, extensionApi, resolveRowId],\n );\n\n // 收集工具栏 / 底部 / 主体接管的扩展贡献。\n const toolbarExtras = extensions\n .map((ext) =>\n ext.toolbar ? { name: ext.name, node: ext.toolbar(extensionApi) } : null,\n )\n .filter((x): x is { name: string; node: React.ReactNode } => !!x && !!x.node);\n\n const footerExtras = extensions\n .map((ext) =>\n ext.footer ? { name: ext.name, node: ext.footer(extensionApi) } : null,\n )\n .filter((x): x is { name: string; node: React.ReactNode } => !!x && !!x.node);\n\n let overrideContent: React.ReactNode | undefined = undefined;\n for (const ext of extensions) {\n const out = ext.renderContent?.(extensionApi);\n if (out !== undefined) {\n overrideContent = out;\n break;\n }\n }\n\n\n const toggleColumnVisibility = (columnId: string) => {\n table.getColumn(columnId)?.toggleVisibility();\n };\n\n useEffect(() => {\n const styleElement = document.createElement('style');\n styleElement.textContent = treeRowAnimationStyles;\n document.head.appendChild(styleElement);\n return () => { document.head.removeChild(styleElement); };\n }, []);\n\n return (\n <div className={`w-full ${className}`}>\n <TableToolbar\n toolbar={toolbar}\n table={table}\n columns={columns}\n columnOrderState={columnOrderState}\n visibilityState={visibilityState}\n activeFilter={activeFilter}\n setActiveFilter={setActiveFilter}\n customFilterPanel={customFilterPanel}\n draggedColumnId={draggedColumnId}\n handleDragStart={handleDragStart}\n toggleColumnVisibility={toggleColumnVisibility}\n rowSelection={rowSelection}\n data={data}\n enableColumnReordering={enableColumnReordering}\n handleDrop={handleDrop}\n viewSwitcher={enableViewSwitcher && overrideContent === undefined ? (\n <div role=\"group\" aria-label={viewSwitcherLabels?.label ?? '显示方式'} className=\"flex items-center gap-1\">\n {(['table', 'card'] as const).map(mode => (\n <button\n key={mode}\n type=\"button\"\n className={`btn btn-sm ${viewMode === mode ? 'btn-neutral' : 'btn-ghost'}`}\n aria-pressed={viewMode === mode}\n disabled={controlledViewMode !== undefined && !onViewModeChange}\n onClick={() => changeViewMode(mode)}\n >\n {viewSwitcherLabels?.[mode] ?? (mode === 'table' ? '表格' : '卡片')}\n </button>\n ))}\n </div>\n ) : undefined}\n />\n\n {/* 扩展贡献的工具栏控件 */}\n {toolbarExtras.length > 0 && (\n <div className=\"flex flex-wrap items-start gap-3 mb-4\">\n {toolbarExtras.map((item) => (\n <React.Fragment key={item.name}>{item.node}</React.Fragment>\n ))}\n </div>\n )}\n\n {overrideContent !== undefined ? (\n // 扩展接管了主体渲染(如 Pivot 透视模式)。\n <div className=\"w-full\">{overrideContent}</div>\n ) : (\n <>\n <div className=\"overflow-x-auto\">\n <Table className=\"table-sm w-full\" card={viewMode === 'card'} cardOptions={cardOptions}>\n <TableHeader\n table={table}\n visibilityState={visibilityState}\n enableSorting={enableSorting}\n enableColumnReordering={enableColumnReordering}\n draggedColumnId={draggedColumnId}\n onColumnMouseEnter={onColumnMouseEnter}\n onColumnMouseLeave={onColumnMouseLeave}\n handleDragStart={handleDragStart}\n handleDragOver={handleDragOver}\n handleDrop={handleDrop}\n />\n <TableBody\n table={table}\n card={viewMode === 'card'}\n fieldLabels={cardOptions?.fieldLabels}\n expandedRowsState={expandedRowsState}\n onRowClick={onRowClick}\n onRowDoubleClick={onRowDoubleClick}\n onRowMouseEnter={onRowMouseEnter}\n onRowMouseLeave={onRowMouseLeave}\n onCellClick={onCellClick}\n onCellDoubleClick={onCellDoubleClick}\n onCellMouseEnter={onCellMouseEnter}\n onCellMouseLeave={onCellMouseLeave}\n enableExpanding={enableExpanding}\n indentSize={indentSize}\n handleRowExpand={handleRowExpand}\n extensions={extensions}\n extensionApi={extensionApi}\n getRowId={resolveRowId}\n onCellContextMenu={handleCellContextMenu}\n />\n </Table>\n </div>\n\n <TablePagination\n enablePagination={enablePagination}\n table={table}\n onPaginationChange={handlePaginationChange}\n />\n </>\n )}\n\n {/* 扩展贡献的底部控件 */}\n {footerExtras.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-3 mt-4\">\n {footerExtras.map((item) => (\n <React.Fragment key={item.name}>{item.node}</React.Fragment>\n ))}\n </div>\n )}\n\n {/* 扩展贡献的右键菜单 */}\n {contextMenu && (\n <ul\n className=\"menu bg-base-100 rounded-box shadow-lg border border-base-300 z-1000 p-1\"\n style={{\n position: 'fixed',\n top: contextMenu.y,\n left: contextMenu.x,\n minWidth: 160,\n }}\n >\n {contextMenu.items.map((item) =>\n item.separator ? (\n <li key={item.key} className=\"my-1 border-t border-base-300\" />\n ) : (\n <li key={item.key}>\n <button\n type=\"button\"\n disabled={item.disabled}\n onClick={() => {\n item.onSelect?.(contextMenu.ctx);\n setContextMenu(null);\n }}\n >\n {item.label}\n </button>\n </li>\n ),\n )}\n </ul>\n )}\n </div>\n );\n}\n\nexport default DataTable;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Filters.js","names":[],"sources":["../../../../src/components/pro/DataTable/Filters.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { Column } from './tanstack-table';\nimport { useDebounce } from '../../../hooks/useDebounce';\n\n// 扩展列元数据接口(v9 的 ColumnMeta 位于 @tanstack/table-core,签名必须与原声明完全一致)\ndeclare module '@tanstack/table-core' {\n interface ColumnMeta<\n in out TFeatures extends import('@tanstack/table-core').TableFeatures,\n in out TData extends import('@tanstack/table-core').RowData,\n TValue extends import('@tanstack/table-core').CellData = import('@tanstack/table-core').CellData,\n > {\n filterType?: 'text' | 'number' | 'select' | 'boolean' | 'date' | 'multiSelect';\n filterOptions?: { value: any; label: string }[];\n }\n}\n\nexport interface TextFilterProps {\n column: Column<any, unknown>;\n placeholder?: string;\n}\n\n// 文本过滤器组件\nexport const TextFilter: React.FC<TextFilterProps> = ({\n column,\n placeholder = '搜索...'\n}) => {\n const [value, setValue] = useState('');\n const debouncedValue = useDebounce(value, 300);\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const currentFilterValue = column.getFilterValue() as string || '';\n if (currentFilterValue !== value) {\n setValue(currentFilterValue);\n }\n }, [column.getFilterValue()]);\n\n // 当 debouncedValue 变化时更新列过滤状态\n useEffect(() => {\n column.setFilterValue(debouncedValue || undefined);\n }, [debouncedValue]);\n\n // 处理输入变更\n const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setValue(e.target.value);\n };\n\n return (\n <div className=\"flex items-center mt-2\">\n <input\n type=\"text\"\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n className=\"input input-bordered input-sm w-full\"\n />\n {value && (\n <button\n className=\"btn btn-ghost btn-xs ml-1\"\n onClick={() => {\n setValue('');\n column.setFilterValue(undefined);\n }}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n );\n};\n\nexport interface NumberFilterProps {\n column: Column<any, unknown>;\n min?: number;\n max?: number;\n step?: number;\n}\n\n// 数字范围过滤器组件\nexport const NumberRangeFilter: React.FC<NumberFilterProps> = ({\n column,\n min,\n max,\n step = 1\n}) => {\n const [minValue, setMinValue] = useState<string>('');\n const [maxValue, setMaxValue] = useState<string>('');\n\n const debouncedMin = useDebounce(minValue, 300);\n const debouncedMax = useDebounce(maxValue, 300);\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue() as [number, number] | undefined;\n const newMin = filterValue && filterValue[0] !== undefined ? String(filterValue[0]) : '';\n const newMax = filterValue && filterValue[1] !== undefined ? String(filterValue[1]) : '';\n\n if (newMin !== minValue) setMinValue(newMin);\n if (newMax !== maxValue) setMaxValue(newMax);\n }, [column.getFilterValue()]);\n\n // 当 debounced 值变化时更新列过滤状态\n useEffect(() => {\n const filterValue: [number | undefined, number | undefined] = [\n debouncedMin === '' ? undefined : Number(debouncedMin),\n debouncedMax === '' ? undefined : Number(debouncedMax)\n ];\n\n // 如果两者都是undefined,则清除过滤器\n if (filterValue[0] === undefined && filterValue[1] === undefined) {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(filterValue);\n }\n }, [debouncedMin, debouncedMax]);\n\n\n\n return (\n <div className=\"flex flex-col gap-1 mt-2\">\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n value={minValue}\n onChange={(e) => {\n setMinValue(e.target.value);\n }}\n placeholder=\"最小值\"\n min={min}\n max={max}\n step={step}\n className=\"input input-bordered input-sm w-full\"\n />\n <span>至</span>\n <input\n type=\"number\"\n value={maxValue}\n onChange={(e) => {\n setMaxValue(e.target.value);\n }}\n placeholder=\"最大值\"\n min={min}\n max={max}\n step={step}\n className=\"input input-bordered input-sm w-full\"\n />\n </div>\n {(minValue || maxValue) && (\n <button\n className=\"btn btn-ghost btn-xs self-end\"\n onClick={() => {\n setMinValue('');\n setMaxValue('');\n column.setFilterValue(undefined);\n }}\n >\n 清除\n </button>\n )}\n </div>\n );\n};\n\nexport interface SelectFilterProps {\n column: Column<any, unknown>;\n options: { value: any; label: string }[];\n placeholder?: string;\n}\n\n// 选择过滤器组件\nexport const SelectFilter: React.FC<SelectFilterProps> = ({\n column,\n options,\n placeholder = '全部'\n}) => {\n const [value, setValue] = useState<string>('');\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue();\n setValue(filterValue !== undefined ? String(filterValue) : '');\n }, [column.getFilterValue()]);\n\n // 处理选择变更\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n const selectedValue = e.target.value;\n setValue(selectedValue);\n\n if (selectedValue === '') {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(selectedValue);\n }\n };\n\n return (\n <div className=\"mt-2\">\n <select\n value={value}\n onChange={handleChange}\n className=\"select select-bordered select-sm w-full\"\n >\n <option value=\"\">{placeholder}</option>\n {options.map((option, index) => (\n <option key={index} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n );\n};\n\nexport interface BooleanFilterProps {\n column: Column<any, unknown>;\n trueLabel?: string;\n falseLabel?: string;\n allLabel?: string;\n}\n\n// 布尔值过滤器组件\nexport const BooleanFilter: React.FC<BooleanFilterProps> = ({\n column,\n trueLabel = '是',\n falseLabel = '否',\n allLabel = '全部'\n}) => {\n const options = [\n { value: '', label: allLabel },\n { value: 'true', label: trueLabel },\n { value: 'false', label: falseLabel }\n ];\n\n const [value, setValue] = useState<string>('');\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue();\n setValue(filterValue !== undefined ? String(filterValue) : '');\n }, [column.getFilterValue()]);\n\n // 处理选择变更\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n const selectedValue = e.target.value;\n setValue(selectedValue);\n\n if (selectedValue === '') {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(selectedValue === 'true');\n }\n };\n\n return (\n <div className=\"mt-2\">\n <select\n value={value}\n onChange={handleChange}\n className=\"select select-bordered select-sm w-full\"\n >\n {options.map((option, index) => (\n <option key={index} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n );\n};\n\nexport interface DateRangeFilterProps {\n column: Column<any, unknown>;\n}\n\n// 日期范围过滤器组件\nexport const DateRangeFilter: React.FC<DateRangeFilterProps> = ({\n column\n}) => {\n const [startDate, setStartDate] = useState<string>('');\n const [endDate, setEndDate] = useState<string>('');\n\n const debouncedStart = useDebounce(startDate, 300);\n const debouncedEnd = useDebounce(endDate, 300);\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue() as [string, string] | undefined;\n const newStart = filterValue && filterValue[0] ? filterValue[0] : '';\n const newEnd = filterValue && filterValue[1] ? filterValue[1] : '';\n\n if (newStart !== startDate) setStartDate(newStart);\n if (newEnd !== endDate) setEndDate(newEnd);\n }, [column.getFilterValue()]);\n\n // 当 debounced 值变化时更新列过滤状态\n useEffect(() => {\n const filterValue: [string | undefined, string | undefined] = [\n debouncedStart || undefined,\n debouncedEnd || undefined\n ];\n\n // 如果两者都是undefined,则清除过滤器\n if (!filterValue[0] && !filterValue[1]) {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(filterValue);\n }\n }, [debouncedStart, debouncedEnd]);\n\n\n\n return (\n <div className=\"flex flex-col gap-1 mt-2\">\n <div className=\"flex items-center gap-2\">\n <input\n type=\"date\"\n value={startDate}\n onChange={(e) => {\n setStartDate(e.target.value);\n }}\n className=\"input input-bordered input-sm w-full\"\n />\n <span>至</span>\n <input\n type=\"date\"\n value={endDate}\n onChange={(e) => {\n setEndDate(e.target.value);\n }}\n className=\"input input-bordered input-sm w-full\"\n />\n </div>\n {(startDate || endDate) && (\n <button\n className=\"btn btn-ghost btn-xs self-end\"\n onClick={() => {\n setStartDate('');\n setEndDate('');\n column.setFilterValue(undefined);\n }}\n >\n 清除\n </button>\n )}\n </div>\n );\n};\n\n// 多选过滤器组件\nexport const MultiSelectFilter: React.FC<SelectFilterProps> = ({\n column,\n options,\n placeholder = '选择选项'\n}) => {\n const [selectedValues, setSelectedValues] = useState<string[]>([]);\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue() as string[] | undefined;\n setSelectedValues(filterValue || []);\n }, [column.getFilterValue()]);\n\n // 处理选择变更\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n const values = Array.from(e.target.selectedOptions, option => option.value);\n setSelectedValues(values);\n\n if (values.length === 0) {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(values);\n }\n };\n\n return (\n <div className=\"mt-2\">\n <select\n multiple\n value={selectedValues}\n onChange={handleChange}\n className=\"select select-bordered select-sm w-full max-h-32\"\n >\n {options.map((option, index) => (\n <option key={index} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {selectedValues.length > 0 && (\n <div className=\"flex justify-between mt-1\">\n <span className=\"text-xs text-base-content/70\">已选择 {selectedValues.length} 项</span>\n <button\n className=\"btn btn-ghost btn-xs\"\n onClick={() => {\n setSelectedValues([]);\n column.setFilterValue(undefined);\n }}\n >\n 清除\n </button>\n </div>\n )}\n </div>\n );\n};\n\n// 过滤器面板组件\nexport interface FilterPanelProps {\n column: Column<any, unknown>;\n onClose: () => void;\n}\n\nexport const FilterPanel: React.FC<FilterPanelProps> = ({\n column,\n onClose\n}) => {\n // 确保column和column.columnDef存在\n if (!column || !column.columnDef) {\n return null;\n }\n\n // 获取过滤器类型,确保meta存在\n const meta = column.columnDef.meta || {};\n const filterType = meta.filterType;\n const filterOptions = meta.filterOptions || [];\n\n // 根据过滤器类型渲染相应的组件\n const renderFilter = () => {\n if (!filterType) return null;\n\n switch (filterType) {\n case 'text':\n return <TextFilter column={column} />;\n case 'number':\n return <NumberRangeFilter column={column} />;\n case 'select':\n return <SelectFilter column={column} options={filterOptions} />;\n case 'boolean':\n return <BooleanFilter column={column} />;\n case 'date':\n return <DateRangeFilter column={column} />;\n case 'multiSelect':\n return <MultiSelectFilter column={column} options={filterOptions} />;\n default:\n return <TextFilter column={column} />;\n }\n };\n\n // 列标题\n const columnHeader = column.columnDef.header ?\n (typeof column.columnDef.header === 'string' ?\n column.columnDef.header :\n column.id\n ) : column.id;\n\n return (\n <div className=\"card bg-base-100 shadow-lg p-4 w-64 z-50\">\n <div className=\"flex justify-between items-center mb-2\">\n <h3 className=\"font-medium\">{columnHeader}</h3>\n <button\n className=\"btn btn-ghost btn-xs\"\n onClick={onClose}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {renderFilter()}\n\n <div className=\"flex justify-end mt-2\">\n <button\n className=\"btn btn-ghost btn-xs\"\n onClick={() => {\n column.setFilterValue(undefined);\n onClose();\n }}\n >\n 清除过滤\n </button>\n </div>\n </div>\n );\n};\n\nexport default {\n TextFilter,\n NumberRangeFilter,\n SelectFilter,\n BooleanFilter,\n DateRangeFilter,\n MultiSelectFilter,\n FilterPanel\n}; "],"mappings":"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"}
1
+ {"version":3,"file":"Filters.js","names":["Filters_exports","BooleanFilter","DateRangeFilter","FilterPanel","MultiSelectFilter","NumberRangeFilter","SelectFilter","TextFilter","Filters_default","value","setValue","useState","debouncedValue","useDebounce","useEffect","currentFilterValue","column","minValue","setMinValue","maxValue","setMaxValue","debouncedMin","debouncedMax","filterValue","newMin","newMax","selectedValue","e","placeholder","options","option","index","allLabel","trueLabel","falseLabel","startDate","setStartDate","endDate","setEndDate","debouncedStart","debouncedEnd","newStart","newEnd","selectedValues","setSelectedValues","values","meta","filterType","filterOptions","renderFilter","columnHeader","onClose"],"sources":["../../../../src/components/pro/DataTable/Filters.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { Column } from './tanstack-table';\nimport { useDebounce } from '../../../hooks/useDebounce';\n\n// 扩展列元数据接口(v9 的 ColumnMeta 位于 @tanstack/table-core,签名必须与原声明完全一致)\ndeclare module '@tanstack/table-core' {\n interface ColumnMeta<\n in out TFeatures extends import('@tanstack/table-core').TableFeatures,\n in out TData extends import('@tanstack/table-core').RowData,\n TValue extends import('@tanstack/table-core').CellData = import('@tanstack/table-core').CellData,\n > {\n filterType?: 'text' | 'number' | 'select' | 'boolean' | 'date' | 'multiSelect';\n filterOptions?: { value: any; label: string }[];\n }\n}\n\nexport interface TextFilterProps {\n column: Column<any, unknown>;\n placeholder?: string;\n}\n\n// 文本过滤器组件\nexport const TextFilter: React.FC<TextFilterProps> = ({\n column,\n placeholder = '搜索...'\n}) => {\n const [value, setValue] = useState('');\n const debouncedValue = useDebounce(value, 300);\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const currentFilterValue = column.getFilterValue() as string || '';\n if (currentFilterValue !== value) {\n setValue(currentFilterValue);\n }\n }, [column.getFilterValue()]);\n\n // 当 debouncedValue 变化时更新列过滤状态\n useEffect(() => {\n column.setFilterValue(debouncedValue || undefined);\n }, [debouncedValue]);\n\n // 处理输入变更\n const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setValue(e.target.value);\n };\n\n return (\n <div className=\"flex items-center mt-2\">\n <input\n type=\"text\"\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n className=\"input input-bordered input-sm w-full\"\n />\n {value && (\n <button\n className=\"btn btn-ghost btn-xs ml-1\"\n onClick={() => {\n setValue('');\n column.setFilterValue(undefined);\n }}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n );\n};\n\nexport interface NumberFilterProps {\n column: Column<any, unknown>;\n min?: number;\n max?: number;\n step?: number;\n}\n\n// 数字范围过滤器组件\nexport const NumberRangeFilter: React.FC<NumberFilterProps> = ({\n column,\n min,\n max,\n step = 1\n}) => {\n const [minValue, setMinValue] = useState<string>('');\n const [maxValue, setMaxValue] = useState<string>('');\n\n const debouncedMin = useDebounce(minValue, 300);\n const debouncedMax = useDebounce(maxValue, 300);\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue() as [number, number] | undefined;\n const newMin = filterValue && filterValue[0] !== undefined ? String(filterValue[0]) : '';\n const newMax = filterValue && filterValue[1] !== undefined ? String(filterValue[1]) : '';\n\n if (newMin !== minValue) setMinValue(newMin);\n if (newMax !== maxValue) setMaxValue(newMax);\n }, [column.getFilterValue()]);\n\n // 当 debounced 值变化时更新列过滤状态\n useEffect(() => {\n const filterValue: [number | undefined, number | undefined] = [\n debouncedMin === '' ? undefined : Number(debouncedMin),\n debouncedMax === '' ? undefined : Number(debouncedMax)\n ];\n\n // 如果两者都是undefined,则清除过滤器\n if (filterValue[0] === undefined && filterValue[1] === undefined) {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(filterValue);\n }\n }, [debouncedMin, debouncedMax]);\n\n\n\n return (\n <div className=\"flex flex-col gap-1 mt-2\">\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n value={minValue}\n onChange={(e) => {\n setMinValue(e.target.value);\n }}\n placeholder=\"最小值\"\n min={min}\n max={max}\n step={step}\n className=\"input input-bordered input-sm w-full\"\n />\n <span>至</span>\n <input\n type=\"number\"\n value={maxValue}\n onChange={(e) => {\n setMaxValue(e.target.value);\n }}\n placeholder=\"最大值\"\n min={min}\n max={max}\n step={step}\n className=\"input input-bordered input-sm w-full\"\n />\n </div>\n {(minValue || maxValue) && (\n <button\n className=\"btn btn-ghost btn-xs self-end\"\n onClick={() => {\n setMinValue('');\n setMaxValue('');\n column.setFilterValue(undefined);\n }}\n >\n 清除\n </button>\n )}\n </div>\n );\n};\n\nexport interface SelectFilterProps {\n column: Column<any, unknown>;\n options: { value: any; label: string }[];\n placeholder?: string;\n}\n\n// 选择过滤器组件\nexport const SelectFilter: React.FC<SelectFilterProps> = ({\n column,\n options,\n placeholder = '全部'\n}) => {\n const [value, setValue] = useState<string>('');\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue();\n setValue(filterValue !== undefined ? String(filterValue) : '');\n }, [column.getFilterValue()]);\n\n // 处理选择变更\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n const selectedValue = e.target.value;\n setValue(selectedValue);\n\n if (selectedValue === '') {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(selectedValue);\n }\n };\n\n return (\n <div className=\"mt-2\">\n <select\n value={value}\n onChange={handleChange}\n className=\"select select-bordered select-sm w-full\"\n >\n <option value=\"\">{placeholder}</option>\n {options.map((option, index) => (\n <option key={index} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n );\n};\n\nexport interface BooleanFilterProps {\n column: Column<any, unknown>;\n trueLabel?: string;\n falseLabel?: string;\n allLabel?: string;\n}\n\n// 布尔值过滤器组件\nexport const BooleanFilter: React.FC<BooleanFilterProps> = ({\n column,\n trueLabel = '是',\n falseLabel = '否',\n allLabel = '全部'\n}) => {\n const options = [\n { value: '', label: allLabel },\n { value: 'true', label: trueLabel },\n { value: 'false', label: falseLabel }\n ];\n\n const [value, setValue] = useState<string>('');\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue();\n setValue(filterValue !== undefined ? String(filterValue) : '');\n }, [column.getFilterValue()]);\n\n // 处理选择变更\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n const selectedValue = e.target.value;\n setValue(selectedValue);\n\n if (selectedValue === '') {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(selectedValue === 'true');\n }\n };\n\n return (\n <div className=\"mt-2\">\n <select\n value={value}\n onChange={handleChange}\n className=\"select select-bordered select-sm w-full\"\n >\n {options.map((option, index) => (\n <option key={index} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n );\n};\n\nexport interface DateRangeFilterProps {\n column: Column<any, unknown>;\n}\n\n// 日期范围过滤器组件\nexport const DateRangeFilter: React.FC<DateRangeFilterProps> = ({\n column\n}) => {\n const [startDate, setStartDate] = useState<string>('');\n const [endDate, setEndDate] = useState<string>('');\n\n const debouncedStart = useDebounce(startDate, 300);\n const debouncedEnd = useDebounce(endDate, 300);\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue() as [string, string] | undefined;\n const newStart = filterValue && filterValue[0] ? filterValue[0] : '';\n const newEnd = filterValue && filterValue[1] ? filterValue[1] : '';\n\n if (newStart !== startDate) setStartDate(newStart);\n if (newEnd !== endDate) setEndDate(newEnd);\n }, [column.getFilterValue()]);\n\n // 当 debounced 值变化时更新列过滤状态\n useEffect(() => {\n const filterValue: [string | undefined, string | undefined] = [\n debouncedStart || undefined,\n debouncedEnd || undefined\n ];\n\n // 如果两者都是undefined,则清除过滤器\n if (!filterValue[0] && !filterValue[1]) {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(filterValue);\n }\n }, [debouncedStart, debouncedEnd]);\n\n\n\n return (\n <div className=\"flex flex-col gap-1 mt-2\">\n <div className=\"flex items-center gap-2\">\n <input\n type=\"date\"\n value={startDate}\n onChange={(e) => {\n setStartDate(e.target.value);\n }}\n className=\"input input-bordered input-sm w-full\"\n />\n <span>至</span>\n <input\n type=\"date\"\n value={endDate}\n onChange={(e) => {\n setEndDate(e.target.value);\n }}\n className=\"input input-bordered input-sm w-full\"\n />\n </div>\n {(startDate || endDate) && (\n <button\n className=\"btn btn-ghost btn-xs self-end\"\n onClick={() => {\n setStartDate('');\n setEndDate('');\n column.setFilterValue(undefined);\n }}\n >\n 清除\n </button>\n )}\n </div>\n );\n};\n\n// 多选过滤器组件\nexport const MultiSelectFilter: React.FC<SelectFilterProps> = ({\n column,\n options,\n placeholder = '选择选项'\n}) => {\n const [selectedValues, setSelectedValues] = useState<string[]>([]);\n\n // 将组件状态与列过滤状态同步\n useEffect(() => {\n const filterValue = column.getFilterValue() as string[] | undefined;\n setSelectedValues(filterValue || []);\n }, [column.getFilterValue()]);\n\n // 处理选择变更\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n const values = Array.from(e.target.selectedOptions, option => option.value);\n setSelectedValues(values);\n\n if (values.length === 0) {\n column.setFilterValue(undefined);\n } else {\n column.setFilterValue(values);\n }\n };\n\n return (\n <div className=\"mt-2\">\n <select\n multiple\n value={selectedValues}\n onChange={handleChange}\n className=\"select select-bordered select-sm w-full max-h-32\"\n >\n {options.map((option, index) => (\n <option key={index} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {selectedValues.length > 0 && (\n <div className=\"flex justify-between mt-1\">\n <span className=\"text-xs text-base-content/70\">已选择 {selectedValues.length} 项</span>\n <button\n className=\"btn btn-ghost btn-xs\"\n onClick={() => {\n setSelectedValues([]);\n column.setFilterValue(undefined);\n }}\n >\n 清除\n </button>\n </div>\n )}\n </div>\n );\n};\n\n// 过滤器面板组件\nexport interface FilterPanelProps {\n column: Column<any, unknown>;\n onClose: () => void;\n}\n\nexport const FilterPanel: React.FC<FilterPanelProps> = ({\n column,\n onClose\n}) => {\n // 确保column和column.columnDef存在\n if (!column || !column.columnDef) {\n return null;\n }\n\n // 获取过滤器类型,确保meta存在\n const meta = column.columnDef.meta || {};\n const filterType = meta.filterType;\n const filterOptions = meta.filterOptions || [];\n\n // 根据过滤器类型渲染相应的组件\n const renderFilter = () => {\n if (!filterType) return null;\n\n switch (filterType) {\n case 'text':\n return <TextFilter column={column} />;\n case 'number':\n return <NumberRangeFilter column={column} />;\n case 'select':\n return <SelectFilter column={column} options={filterOptions} />;\n case 'boolean':\n return <BooleanFilter column={column} />;\n case 'date':\n return <DateRangeFilter column={column} />;\n case 'multiSelect':\n return <MultiSelectFilter column={column} options={filterOptions} />;\n default:\n return <TextFilter column={column} />;\n }\n };\n\n // 列标题\n const columnHeader = column.columnDef.header ?\n (typeof column.columnDef.header === 'string' ?\n column.columnDef.header :\n column.id\n ) : column.id;\n\n return (\n <div className=\"card bg-base-100 shadow-lg p-4 w-64 z-50\">\n <div className=\"flex justify-between items-center mb-2\">\n <h3 className=\"font-medium\">{columnHeader}</h3>\n <button\n className=\"btn btn-ghost btn-xs\"\n onClick={onClose}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {renderFilter()}\n\n <div className=\"flex justify-end mt-2\">\n <button\n className=\"btn btn-ghost btn-xs\"\n onClick={() => {\n column.setFilterValue(undefined);\n onClose();\n }}\n >\n 清除过滤\n </button>\n </div>\n </div>\n );\n};\n\nexport default {\n TextFilter,\n NumberRangeFilter,\n SelectFilter,\n BooleanFilter,\n DateRangeFilter,\n MultiSelectFilter,\n FilterPanel\n}; "],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PivotPanel.js","names":[],"sources":["../../../../src/components/pro/DataTable/PivotPanel.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport type { PivotValue, PivotFieldLabels } from './PivotView';\nimport type { PivotAggFn } from './pivotEngine';\nimport type { PivotField } from './pivotExtension';\n\nconst AGG_FNS: PivotAggFn[] = ['sum', 'avg', 'count', 'min', 'max'];\n\n/** 面板内的区域标识。 */\ntype ZoneId = 'available' | 'rows' | 'cols' | 'values';\n\nconst TEXT = {\n zh: {\n available: '可用字段',\n rowGroups: '行分组',\n colGroups: '列分组',\n values: '数值',\n empty: '(无字段)',\n dropHint: '拖拽字段到此',\n remove: '移除',\n },\n en: {\n available: 'Available',\n rowGroups: 'Row Groups',\n colGroups: 'Column Labels',\n values: 'Values',\n empty: '(no fields)',\n dropHint: 'Drag fields here',\n remove: 'Remove',\n },\n} as const;\n\n/** 透明的 1x1 拖拽图,用于隐藏浏览器默认的拖拽影像(改用自定义 ghost)。 */\nconst EMPTY_DRAG_IMAGE =\n typeof Image !== 'undefined'\n ? (() => {\n const img = new Image();\n img.src =\n 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';\n return img;\n })()\n : null;\n\nexport interface PivotPanelProps {\n /** 面板排布方向:水平(工具栏下方)或垂直(表格左/右侧)。 */\n orientation: 'horizontal' | 'vertical';\n lang: 'zh' | 'en';\n fieldLabels: PivotFieldLabels;\n dimensionFields: PivotField[];\n numericFields: PivotField[];\n rowFields: string[];\n colFields: string[];\n values: PivotValue[];\n setRowFields: React.Dispatch<React.SetStateAction<string[]>>;\n setColFields: React.Dispatch<React.SetStateAction<string[]>>;\n setValues: React.Dispatch<React.SetStateAction<PivotValue[]>>;\n /**\n * 垂直(左/右)面板的宽度。数字视为 px,字符串直接作为 CSS 宽度\n * (如 `'20%'` / `'16rem'`)。仅在 `orientation='vertical'` 时生效,默认 224px。\n */\n panelWidth?: number | string;\n}\n\n/**\n * 当前拖拽的字段信息(低频变化:仅在拖拽开始 / 结束时更新,\n * 不含坐标,避免拖拽过程中高频 setState 导致 chip 重挂载而使拖拽卡死)。\n */\ninterface DragInfo {\n field: string;\n label: string;\n numeric: boolean;\n}\n\n/**\n * ag-grid 风格的透视配置面板。\n *\n * 特性:\n * - 支持水平(`horizontal`)与垂直(`vertical`)两种排布,后者用于表格左/右侧。\n * - 拖拽字段时显示跟随光标的「拖拽引用」(ghost 预览),并高亮可放置的目标区域。\n *\n * 关键实现:拖拽期间**不** setState 更新坐标,而是用 ref 直接改写 ghost 的\n * transform;`Chip`/`Zone` 用渲染函数而非内联组件,避免每次渲染都被 React\n * 当作新组件类型而卸载重挂载(那会中断浏览器原生拖拽,导致卡死)。\n */\nexport function PivotPanel({\n orientation,\n lang,\n fieldLabels,\n dimensionFields,\n numericFields,\n rowFields,\n colFields,\n values,\n setRowFields,\n setColFields,\n setValues,\n panelWidth = 224,\n}: PivotPanelProps) {\n const t = TEXT[lang];\n const labelOf = (field: string) => fieldLabels[field] ?? field;\n const isNumericField = (field: string) =>\n numericFields.some((f) => f.field === field);\n\n const [drag, setDrag] = useState<DragInfo | null>(null);\n const [overZone, setOverZone] = useState<ZoneId | null>(null);\n const ghostRef = useRef<HTMLDivElement | null>(null);\n const pointerRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n const dragging = drag != null;\n\n // 拖拽期间用 window 级 `dragover` 直接更新 ghost 位置(ref 操作 DOM,不触发\n // React 重渲染),坐标不进入 state,从根本上避免 chip 子树重挂载而卡死。\n // 同时用 window 级 `dragend`/`drop` 兜底清除拖拽状态:放置后源 chip 常因状态\n // 更新被移动/重建,其自身的 `onDragEnd` 可能不再触发,导致 ghost 残留。\n useEffect(() => {\n if (!dragging) return;\n const positionGhost = () => {\n const el = ghostRef.current;\n if (!el) return;\n el.style.transform = `translate(${pointerRef.current.x + 12}px, ${\n pointerRef.current.y + 12\n }px)`;\n };\n positionGhost();\n const onWindowDragOver = (e: DragEvent) => {\n if (e.clientX === 0 && e.clientY === 0) return;\n pointerRef.current = { x: e.clientX, y: e.clientY };\n positionGhost();\n };\n const clear = () => {\n setDrag(null);\n setOverZone(null);\n };\n window.addEventListener('dragover', onWindowDragOver);\n window.addEventListener('dragend', clear);\n window.addEventListener('drop', clear);\n return () => {\n window.removeEventListener('dragover', onWindowDragOver);\n window.removeEventListener('dragend', clear);\n window.removeEventListener('drop', clear);\n };\n }, [dragging]);\n\n const usedDims = new Set<string>([...rowFields, ...colFields]);\n const availableDims = dimensionFields.filter((f) => !usedDims.has(f.field));\n const usedValues = new Set(values.map((v) => v.field));\n const availableValues = numericFields.filter((f) => !usedValues.has(f.field));\n\n const removeFromAll = (field: string) => {\n setRowFields((prev) => prev.filter((x) => x !== field));\n setColFields((prev) => prev.filter((x) => x !== field));\n setValues((prev) => prev.filter((x) => x.field !== field));\n };\n\n /** 某个区域是否能接收当前正在拖拽的字段。 */\n const zoneAccepts = (zone: ZoneId): boolean => {\n if (!drag) return false;\n if (zone === 'available') return true;\n if (zone === 'values') return drag.numeric;\n return !drag.numeric; // rows / cols 只接受维度字段\n };\n\n const dropTo = (zone: ZoneId, field: string) => {\n const numeric = isNumericField(field);\n if (zone === 'values') {\n if (!numeric) return;\n setRowFields((prev) => prev.filter((x) => x !== field));\n setColFields((prev) => prev.filter((x) => x !== field));\n setValues((prev) =>\n prev.some((v) => v.field === field)\n ? prev\n : [...prev, { field, aggFn: 'sum' }],\n );\n return;\n }\n if (zone === 'rows' || zone === 'cols') {\n if (numeric) return;\n setValues((prev) => prev.filter((x) => x.field !== field));\n if (zone === 'rows') {\n setColFields((prev) => prev.filter((x) => x !== field));\n setRowFields((prev) =>\n prev.includes(field) ? prev : [...prev, field],\n );\n } else {\n setRowFields((prev) => prev.filter((x) => x !== field));\n setColFields((prev) =>\n prev.includes(field) ? prev : [...prev, field],\n );\n }\n return;\n }\n removeFromAll(field);\n };\n\n const onChipDragStart = (e: React.DragEvent, field: string) => {\n e.dataTransfer.setData('text/plain', field);\n e.dataTransfer.effectAllowed = 'move';\n if (EMPTY_DRAG_IMAGE) {\n e.dataTransfer.setDragImage(EMPTY_DRAG_IMAGE, 0, 0);\n }\n pointerRef.current = { x: e.clientX, y: e.clientY };\n setDrag({\n field,\n label: labelOf(field),\n numeric: isNumericField(field),\n });\n };\n\n const onChipDragEnd = () => {\n setDrag(null);\n setOverZone(null);\n };\n\n const vertical = orientation === 'vertical';\n\n // 渲染一个可拖拽的字段 chip(用渲染函数而非组件,避免重挂载)。\n const renderChip = (\n field: string,\n opts?: { onRemove?: () => void; prefix?: React.ReactNode },\n ) => (\n <span\n key={field}\n draggable\n onDragStart={(e) => onChipDragStart(e, field)}\n onDragEnd={onChipDragEnd}\n className={`badge badge-outline gap-1 items-center cursor-grab active:cursor-grabbing select-none ${\n drag?.field === field ? 'opacity-40' : ''\n }`}\n >\n {opts?.prefix}\n {labelOf(field)}\n {opts?.onRemove && (\n <button\n type=\"button\"\n className=\"text-xs opacity-60 hover:opacity-100\"\n onClick={opts.onRemove}\n aria-label={t.remove}\n >\n ✕\n </button>\n )}\n </span>\n );\n\n // 渲染一个拖放区段(渲染函数,非组件)。\n const renderZone = (\n zone: ZoneId,\n icon: string,\n title: string,\n children: React.ReactNode,\n ) => {\n const accepts = zoneAccepts(zone);\n const isOver = overZone === zone;\n const boxTone = drag\n ? accepts\n ? isOver\n ? 'border-primary border-solid bg-primary/10'\n : 'border-primary/60 border-dashed bg-primary/5'\n : 'border-base-300 border-dashed opacity-40'\n : 'border-base-300 border-dashed bg-base-100/50';\n return (\n <div\n className={`flex flex-col gap-1 ${vertical ? 'w-full' : 'flex-1 min-w-40'}`}\n onDragOver={(e) => {\n if (!accepts) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n if (overZone !== zone) setOverZone(zone);\n }}\n onDragLeave={(e) => {\n // 仅当真正离开该区域(而非进入其子元素)时才清除高亮。\n if (e.currentTarget.contains(e.relatedTarget as Node)) return;\n if (overZone === zone) setOverZone(null);\n }}\n onDrop={(e) => {\n e.preventDefault();\n const field = e.dataTransfer.getData('text/plain');\n setOverZone(null);\n if (field) dropTo(zone, field);\n }}\n >\n <span className=\"text-xs font-semibold opacity-60 flex items-center gap-1\">\n <span aria-hidden>{icon}</span>\n {title}\n </span>\n <div\n className={`flex flex-wrap gap-1 items-center content-start p-1.5 border rounded transition-colors ${\n vertical ? 'min-h-16' : 'min-h-9'\n } ${boxTone}`}\n >\n {children}\n </div>\n </div>\n );\n };\n\n const divider = vertical ? null : (\n <div className=\"w-px bg-base-300 self-stretch\" />\n );\n\n return (\n <>\n <div\n className={`gap-2 p-2 border border-base-300 rounded-box bg-base-200/40 ${\n vertical\n ? 'flex flex-col shrink-0 self-stretch overflow-auto'\n : 'w-full flex flex-wrap items-stretch'\n }`}\n style={\n vertical\n ? {\n width:\n typeof panelWidth === 'number'\n ? `${panelWidth}px`\n : panelWidth,\n }\n : undefined\n }\n >\n {renderZone(\n 'available',\n '☷',\n t.available,\n <>\n {availableDims.length === 0 &&\n availableValues.length === 0 && (\n <span className=\"text-xs opacity-40\">\n {t.empty}\n </span>\n )}\n {availableDims.map((f) => renderChip(f.field))}\n {availableValues.map((f) =>\n renderChip(f.field, {\n prefix: <span className=\"opacity-70\">#</span>,\n }),\n )}\n </>,\n )}\n\n {divider}\n\n {renderZone(\n 'rows',\n '≣',\n t.rowGroups,\n <>\n {rowFields.length === 0 && (\n <span className=\"text-xs opacity-40\">\n {t.dropHint}\n </span>\n )}\n {rowFields.map((field) =>\n renderChip(field, {\n onRemove: () => removeFromAll(field),\n }),\n )}\n </>,\n )}\n\n {divider}\n\n {renderZone(\n 'cols',\n '║',\n t.colGroups,\n <>\n {colFields.length === 0 && (\n <span className=\"text-xs opacity-40\">\n {t.dropHint}\n </span>\n )}\n {colFields.map((field) =>\n renderChip(field, {\n onRemove: () => removeFromAll(field),\n }),\n )}\n </>,\n )}\n\n {divider}\n\n {renderZone(\n 'values',\n 'Σ',\n t.values,\n <>\n {values.length === 0 && (\n <span className=\"text-xs opacity-40\">\n {t.dropHint}\n </span>\n )}\n {values.map((v, i) => (\n <span\n key={`${v.field}:${i}`}\n draggable\n onDragStart={(e) => onChipDragStart(e, v.field)}\n onDragEnd={onChipDragEnd}\n className={`badge badge-outline gap-1 items-center cursor-grab active:cursor-grabbing select-none ${\n drag?.field === v.field ? 'opacity-40' : ''\n }`}\n >\n <select\n className=\"bg-transparent text-xs outline-none\"\n value={v.aggFn}\n // 防止在 select 上开始拖拽。\n draggable={false}\n onChange={(e) =>\n setValues(\n values.map((x, xi) =>\n xi === i\n ? {\n ...x,\n aggFn: e.target\n .value as PivotAggFn,\n }\n : x,\n ),\n )\n }\n >\n {AGG_FNS.map((fn) => (\n <option key={fn} value={fn}>\n {fn}\n </option>\n ))}\n </select>\n <span>{labelOf(v.field)}</span>\n <button\n type=\"button\"\n className=\"text-xs opacity-60 hover:opacity-100\"\n onClick={() =>\n setValues(\n values.filter((_, xi) => xi !== i),\n )\n }\n aria-label={t.remove}\n >\n ✕\n </button>\n </span>\n ))}\n </>,\n )}\n </div>\n\n {/* 拖拽引用(ghost 预览):跟随光标显示当前拖拽的字段。\n 位置由 window `dragover` 通过 ref 直接更新,不触发重渲染。 */}\n {drag && (\n <div\n ref={ghostRef}\n className=\"badge badge-primary gap-1 items-center shadow-lg pointer-events-none\"\n style={{\n position: 'fixed',\n left: 0,\n top: 0,\n zIndex: 2000,\n willChange: 'transform',\n }}\n >\n {drag.numeric && <span className=\"opacity-80\">#</span>}\n {drag.label}\n </div>\n )}\n </>\n );\n}\n\nexport default PivotPanel;\n"],"mappings":"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"}
1
+ {"version":3,"file":"PivotPanel.js","names":["_Fragment","AGG_FNS","TEXT","EMPTY_DRAG_IMAGE","img","PivotPanel","t","lang","labelOf","fieldLabels","field","isNumericField","numericFields","f","drag","setDrag","useState","overZone","setOverZone","ghostRef","useRef","pointerRef","dragging","positionGhost","el","onWindowDragOver","e","clear","usedDims","rowFields","colFields","availableDims","dimensionFields","usedValues","values","v","availableValues","removeFromAll","setRowFields","prev","x","setColFields","setValues","zoneAccepts","zone","dropTo","numeric","onChipDragStart","onChipDragEnd","vertical","orientation","renderChip","opts","renderZone","accepts","icon","title","divider","Fragment","panelWidth","xi","i","fn"],"sources":["../../../../src/components/pro/DataTable/PivotPanel.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport type { PivotValue, PivotFieldLabels } from './PivotView';\nimport type { PivotAggFn } from './pivotEngine';\nimport type { PivotField } from './pivotExtension';\n\nconst AGG_FNS: PivotAggFn[] = ['sum', 'avg', 'count', 'min', 'max'];\n\n/** 面板内的区域标识。 */\ntype ZoneId = 'available' | 'rows' | 'cols' | 'values';\n\nconst TEXT = {\n zh: {\n available: '可用字段',\n rowGroups: '行分组',\n colGroups: '列分组',\n values: '数值',\n empty: '(无字段)',\n dropHint: '拖拽字段到此',\n remove: '移除',\n },\n en: {\n available: 'Available',\n rowGroups: 'Row Groups',\n colGroups: 'Column Labels',\n values: 'Values',\n empty: '(no fields)',\n dropHint: 'Drag fields here',\n remove: 'Remove',\n },\n} as const;\n\n/** 透明的 1x1 拖拽图,用于隐藏浏览器默认的拖拽影像(改用自定义 ghost)。 */\nconst EMPTY_DRAG_IMAGE =\n typeof Image !== 'undefined'\n ? (() => {\n const img = new Image();\n img.src =\n 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';\n return img;\n })()\n : null;\n\nexport interface PivotPanelProps {\n /** 面板排布方向:水平(工具栏下方)或垂直(表格左/右侧)。 */\n orientation: 'horizontal' | 'vertical';\n lang: 'zh' | 'en';\n fieldLabels: PivotFieldLabels;\n dimensionFields: PivotField[];\n numericFields: PivotField[];\n rowFields: string[];\n colFields: string[];\n values: PivotValue[];\n setRowFields: React.Dispatch<React.SetStateAction<string[]>>;\n setColFields: React.Dispatch<React.SetStateAction<string[]>>;\n setValues: React.Dispatch<React.SetStateAction<PivotValue[]>>;\n /**\n * 垂直(左/右)面板的宽度。数字视为 px,字符串直接作为 CSS 宽度\n * (如 `'20%'` / `'16rem'`)。仅在 `orientation='vertical'` 时生效,默认 224px。\n */\n panelWidth?: number | string;\n}\n\n/**\n * 当前拖拽的字段信息(低频变化:仅在拖拽开始 / 结束时更新,\n * 不含坐标,避免拖拽过程中高频 setState 导致 chip 重挂载而使拖拽卡死)。\n */\ninterface DragInfo {\n field: string;\n label: string;\n numeric: boolean;\n}\n\n/**\n * ag-grid 风格的透视配置面板。\n *\n * 特性:\n * - 支持水平(`horizontal`)与垂直(`vertical`)两种排布,后者用于表格左/右侧。\n * - 拖拽字段时显示跟随光标的「拖拽引用」(ghost 预览),并高亮可放置的目标区域。\n *\n * 关键实现:拖拽期间**不** setState 更新坐标,而是用 ref 直接改写 ghost 的\n * transform;`Chip`/`Zone` 用渲染函数而非内联组件,避免每次渲染都被 React\n * 当作新组件类型而卸载重挂载(那会中断浏览器原生拖拽,导致卡死)。\n */\nexport function PivotPanel({\n orientation,\n lang,\n fieldLabels,\n dimensionFields,\n numericFields,\n rowFields,\n colFields,\n values,\n setRowFields,\n setColFields,\n setValues,\n panelWidth = 224,\n}: PivotPanelProps) {\n const t = TEXT[lang];\n const labelOf = (field: string) => fieldLabels[field] ?? field;\n const isNumericField = (field: string) =>\n numericFields.some((f) => f.field === field);\n\n const [drag, setDrag] = useState<DragInfo | null>(null);\n const [overZone, setOverZone] = useState<ZoneId | null>(null);\n const ghostRef = useRef<HTMLDivElement | null>(null);\n const pointerRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n const dragging = drag != null;\n\n // 拖拽期间用 window 级 `dragover` 直接更新 ghost 位置(ref 操作 DOM,不触发\n // React 重渲染),坐标不进入 state,从根本上避免 chip 子树重挂载而卡死。\n // 同时用 window 级 `dragend`/`drop` 兜底清除拖拽状态:放置后源 chip 常因状态\n // 更新被移动/重建,其自身的 `onDragEnd` 可能不再触发,导致 ghost 残留。\n useEffect(() => {\n if (!dragging) return;\n const positionGhost = () => {\n const el = ghostRef.current;\n if (!el) return;\n el.style.transform = `translate(${pointerRef.current.x + 12}px, ${\n pointerRef.current.y + 12\n }px)`;\n };\n positionGhost();\n const onWindowDragOver = (e: DragEvent) => {\n if (e.clientX === 0 && e.clientY === 0) return;\n pointerRef.current = { x: e.clientX, y: e.clientY };\n positionGhost();\n };\n const clear = () => {\n setDrag(null);\n setOverZone(null);\n };\n window.addEventListener('dragover', onWindowDragOver);\n window.addEventListener('dragend', clear);\n window.addEventListener('drop', clear);\n return () => {\n window.removeEventListener('dragover', onWindowDragOver);\n window.removeEventListener('dragend', clear);\n window.removeEventListener('drop', clear);\n };\n }, [dragging]);\n\n const usedDims = new Set<string>([...rowFields, ...colFields]);\n const availableDims = dimensionFields.filter((f) => !usedDims.has(f.field));\n const usedValues = new Set(values.map((v) => v.field));\n const availableValues = numericFields.filter((f) => !usedValues.has(f.field));\n\n const removeFromAll = (field: string) => {\n setRowFields((prev) => prev.filter((x) => x !== field));\n setColFields((prev) => prev.filter((x) => x !== field));\n setValues((prev) => prev.filter((x) => x.field !== field));\n };\n\n /** 某个区域是否能接收当前正在拖拽的字段。 */\n const zoneAccepts = (zone: ZoneId): boolean => {\n if (!drag) return false;\n if (zone === 'available') return true;\n if (zone === 'values') return drag.numeric;\n return !drag.numeric; // rows / cols 只接受维度字段\n };\n\n const dropTo = (zone: ZoneId, field: string) => {\n const numeric = isNumericField(field);\n if (zone === 'values') {\n if (!numeric) return;\n setRowFields((prev) => prev.filter((x) => x !== field));\n setColFields((prev) => prev.filter((x) => x !== field));\n setValues((prev) =>\n prev.some((v) => v.field === field)\n ? prev\n : [...prev, { field, aggFn: 'sum' }],\n );\n return;\n }\n if (zone === 'rows' || zone === 'cols') {\n if (numeric) return;\n setValues((prev) => prev.filter((x) => x.field !== field));\n if (zone === 'rows') {\n setColFields((prev) => prev.filter((x) => x !== field));\n setRowFields((prev) =>\n prev.includes(field) ? prev : [...prev, field],\n );\n } else {\n setRowFields((prev) => prev.filter((x) => x !== field));\n setColFields((prev) =>\n prev.includes(field) ? prev : [...prev, field],\n );\n }\n return;\n }\n removeFromAll(field);\n };\n\n const onChipDragStart = (e: React.DragEvent, field: string) => {\n e.dataTransfer.setData('text/plain', field);\n e.dataTransfer.effectAllowed = 'move';\n if (EMPTY_DRAG_IMAGE) {\n e.dataTransfer.setDragImage(EMPTY_DRAG_IMAGE, 0, 0);\n }\n pointerRef.current = { x: e.clientX, y: e.clientY };\n setDrag({\n field,\n label: labelOf(field),\n numeric: isNumericField(field),\n });\n };\n\n const onChipDragEnd = () => {\n setDrag(null);\n setOverZone(null);\n };\n\n const vertical = orientation === 'vertical';\n\n // 渲染一个可拖拽的字段 chip(用渲染函数而非组件,避免重挂载)。\n const renderChip = (\n field: string,\n opts?: { onRemove?: () => void; prefix?: React.ReactNode },\n ) => (\n <span\n key={field}\n draggable\n onDragStart={(e) => onChipDragStart(e, field)}\n onDragEnd={onChipDragEnd}\n className={`badge badge-outline gap-1 items-center cursor-grab active:cursor-grabbing select-none ${\n drag?.field === field ? 'opacity-40' : ''\n }`}\n >\n {opts?.prefix}\n {labelOf(field)}\n {opts?.onRemove && (\n <button\n type=\"button\"\n className=\"text-xs opacity-60 hover:opacity-100\"\n onClick={opts.onRemove}\n aria-label={t.remove}\n >\n ✕\n </button>\n )}\n </span>\n );\n\n // 渲染一个拖放区段(渲染函数,非组件)。\n const renderZone = (\n zone: ZoneId,\n icon: string,\n title: string,\n children: React.ReactNode,\n ) => {\n const accepts = zoneAccepts(zone);\n const isOver = overZone === zone;\n const boxTone = drag\n ? accepts\n ? isOver\n ? 'border-primary border-solid bg-primary/10'\n : 'border-primary/60 border-dashed bg-primary/5'\n : 'border-base-300 border-dashed opacity-40'\n : 'border-base-300 border-dashed bg-base-100/50';\n return (\n <div\n className={`flex flex-col gap-1 ${vertical ? 'w-full' : 'flex-1 min-w-40'}`}\n onDragOver={(e) => {\n if (!accepts) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n if (overZone !== zone) setOverZone(zone);\n }}\n onDragLeave={(e) => {\n // 仅当真正离开该区域(而非进入其子元素)时才清除高亮。\n if (e.currentTarget.contains(e.relatedTarget as Node)) return;\n if (overZone === zone) setOverZone(null);\n }}\n onDrop={(e) => {\n e.preventDefault();\n const field = e.dataTransfer.getData('text/plain');\n setOverZone(null);\n if (field) dropTo(zone, field);\n }}\n >\n <span className=\"text-xs font-semibold opacity-60 flex items-center gap-1\">\n <span aria-hidden>{icon}</span>\n {title}\n </span>\n <div\n className={`flex flex-wrap gap-1 items-center content-start p-1.5 border rounded transition-colors ${\n vertical ? 'min-h-16' : 'min-h-9'\n } ${boxTone}`}\n >\n {children}\n </div>\n </div>\n );\n };\n\n const divider = vertical ? null : (\n <div className=\"w-px bg-base-300 self-stretch\" />\n );\n\n return (\n <>\n <div\n className={`gap-2 p-2 border border-base-300 rounded-box bg-base-200/40 ${\n vertical\n ? 'flex flex-col shrink-0 self-stretch overflow-auto'\n : 'w-full flex flex-wrap items-stretch'\n }`}\n style={\n vertical\n ? {\n width:\n typeof panelWidth === 'number'\n ? `${panelWidth}px`\n : panelWidth,\n }\n : undefined\n }\n >\n {renderZone(\n 'available',\n '☷',\n t.available,\n <>\n {availableDims.length === 0 &&\n availableValues.length === 0 && (\n <span className=\"text-xs opacity-40\">\n {t.empty}\n </span>\n )}\n {availableDims.map((f) => renderChip(f.field))}\n {availableValues.map((f) =>\n renderChip(f.field, {\n prefix: <span className=\"opacity-70\">#</span>,\n }),\n )}\n </>,\n )}\n\n {divider}\n\n {renderZone(\n 'rows',\n '≣',\n t.rowGroups,\n <>\n {rowFields.length === 0 && (\n <span className=\"text-xs opacity-40\">\n {t.dropHint}\n </span>\n )}\n {rowFields.map((field) =>\n renderChip(field, {\n onRemove: () => removeFromAll(field),\n }),\n )}\n </>,\n )}\n\n {divider}\n\n {renderZone(\n 'cols',\n '║',\n t.colGroups,\n <>\n {colFields.length === 0 && (\n <span className=\"text-xs opacity-40\">\n {t.dropHint}\n </span>\n )}\n {colFields.map((field) =>\n renderChip(field, {\n onRemove: () => removeFromAll(field),\n }),\n )}\n </>,\n )}\n\n {divider}\n\n {renderZone(\n 'values',\n 'Σ',\n t.values,\n <>\n {values.length === 0 && (\n <span className=\"text-xs opacity-40\">\n {t.dropHint}\n </span>\n )}\n {values.map((v, i) => (\n <span\n key={`${v.field}:${i}`}\n draggable\n onDragStart={(e) => onChipDragStart(e, v.field)}\n onDragEnd={onChipDragEnd}\n className={`badge badge-outline gap-1 items-center cursor-grab active:cursor-grabbing select-none ${\n drag?.field === v.field ? 'opacity-40' : ''\n }`}\n >\n <select\n className=\"bg-transparent text-xs outline-none\"\n value={v.aggFn}\n // 防止在 select 上开始拖拽。\n draggable={false}\n onChange={(e) =>\n setValues(\n values.map((x, xi) =>\n xi === i\n ? {\n ...x,\n aggFn: e.target\n .value as PivotAggFn,\n }\n : x,\n ),\n )\n }\n >\n {AGG_FNS.map((fn) => (\n <option key={fn} value={fn}>\n {fn}\n </option>\n ))}\n </select>\n <span>{labelOf(v.field)}</span>\n <button\n type=\"button\"\n className=\"text-xs opacity-60 hover:opacity-100\"\n onClick={() =>\n setValues(\n values.filter((_, xi) => xi !== i),\n )\n }\n aria-label={t.remove}\n >\n ✕\n </button>\n </span>\n ))}\n </>,\n )}\n </div>\n\n {/* 拖拽引用(ghost 预览):跟随光标显示当前拖拽的字段。\n 位置由 window `dragover` 通过 ref 直接更新,不触发重渲染。 */}\n {drag && (\n <div\n ref={ghostRef}\n className=\"badge badge-primary gap-1 items-center shadow-lg pointer-events-none\"\n style={{\n position: 'fixed',\n left: 0,\n top: 0,\n zIndex: 2000,\n willChange: 'transform',\n }}\n >\n {drag.numeric && <span className=\"opacity-80\">#</span>}\n {drag.label}\n </div>\n )}\n </>\n );\n}\n\nexport default PivotPanel;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PivotView.js","names":[],"sources":["../../../../src/components/pro/DataTable/PivotView.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react';\nimport Table from '../../Table';\nimport {\n computePivot,\n type PivotAggFn,\n type PivotConfig,\n type PivotResult,\n type PivotRowNode,\n} from './pivotEngine';\n\nconst SEP = '\\u0001';\n\n/** 一个数值度量:字段 + 聚合函数。 */\nexport interface PivotValue {\n field: string;\n aggFn: PivotAggFn;\n}\n\n/** 字段的展示标签映射。 */\nexport type PivotFieldLabels = Record<string, string>;\n\nconst AGG_LABELS: Record<PivotAggFn, { zh: string; en: string }> = {\n sum: { zh: '求和', en: 'Sum' },\n avg: { zh: '平均', en: 'Avg' },\n count: { zh: '计数', en: 'Count' },\n min: { zh: '最小', en: 'Min' },\n max: { zh: '最大', en: 'Max' },\n};\n\nfunction fmt(v: number | null): string {\n if (v == null) return '';\n return v.toLocaleString(undefined, { maximumFractionDigits: 2 });\n}\n\nexport interface PivotViewProps<T extends object> {\n /** 全量数据(会在其之上进行客户端聚合)。 */\n data: T[];\n /** 行分组字段。 */\n rowFields: string[];\n /** 列分组字段。 */\n colFields: string[];\n /** 数值度量列表。 */\n values: PivotValue[];\n /** 字段展示标签。 */\n fieldLabels?: PivotFieldLabels;\n /** 语言(影响聚合函数文案)。默认 'zh'。 */\n lang?: 'zh' | 'en';\n /** 是否以树形(可展开分组)方式展示多级行分组。默认 true。 */\n treeView?: boolean;\n}\n\n/**\n * ag-grid 风格的透视(Pivot)交叉表视图。支持多级行分组、列分组交叉表、\n * 多个数值度量,以及树形分组的展开/折叠。\n */\nexport function PivotView<T extends object>({\n data,\n rowFields,\n colFields,\n values,\n fieldLabels = {},\n lang = 'zh',\n treeView = true,\n}: PivotViewProps<T>) {\n const [expanded, setExpanded] = useState<Record<string, boolean>>({});\n\n const fieldLabel = (f: string) => fieldLabels[f] ?? f;\n const aggLabel = (fn: PivotAggFn) => AGG_LABELS[fn][lang];\n\n // 为每个数值度量分别计算一份透视结果。\n const results: PivotResult[] = useMemo(() => {\n const activeValues = values.length\n ? values\n : [{ field: '', aggFn: 'count' as PivotAggFn }];\n return activeValues.map((v) => {\n const config: PivotConfig = {\n rowFields,\n colFields,\n valueField: v.field,\n aggFn: v.aggFn,\n };\n return computePivot(data, config);\n });\n }, [data, rowFields, colFields, values]);\n\n const primary = results[0];\n if (!primary || rowFields.length === 0) {\n return (\n <div className=\"p-8 text-center opacity-60\">\n {lang === 'zh'\n ? '请至少配置一个行分组字段以启用透视视图。'\n : 'Add at least one row group field to enable the pivot view.'}\n </div>\n );\n }\n\n const activeValues = values.length ? values : [{ field: '', aggFn: 'count' as PivotAggFn }];\n const { rowKeys, colKeys, rowFields: rf } = primary;\n const colCount = colKeys.length;\n const rowCounts = primary.rowCounts;\n const hasCols = primary.colFields.length > 0;\n const treeMode = treeView && rf.length > 1 && primary.rowTree.length > 0;\n\n const groupLabel = rf.map(fieldLabel).join(' / ') || 'Group';\n const columns = hasCols ? colKeys : [[]];\n\n const toggle = (nodeKey: string) =>\n setExpanded((prev) => ({ ...prev, [nodeKey]: !prev[nodeKey] }));\n\n // 树形模式:将树扁平化为可见行(尊重展开状态)。\n interface VisibleRow {\n keyStr: string;\n label: string;\n depth: number;\n count: number;\n hasChildren: boolean;\n open: boolean;\n cellsByValue: (number | null)[][];\n }\n\n const visibleRows: VisibleRow[] = [];\n if (treeMode) {\n const indexTree = (nodes: PivotRowNode[]): Map<string, PivotRowNode> => {\n const map = new Map<string, PivotRowNode>();\n const walk = (ns: PivotRowNode[]) => {\n for (const n of ns) {\n map.set(n.key.join(SEP), n);\n if (n.children.length) walk(n.children);\n }\n };\n walk(nodes);\n return map;\n };\n const valueIndexes = results.map((r) => indexTree(r.rowTree));\n\n const walk = (nodes: PivotRowNode[]) => {\n for (const node of nodes) {\n const keyStr = node.key.join(SEP);\n const hasChildren = node.children.length > 0;\n const open = expanded[keyStr] ?? node.depth === 0;\n const cellsByValue = valueIndexes.map(\n (idx) => idx.get(keyStr)?.cells ?? [],\n );\n visibleRows.push({\n keyStr,\n label: node.label,\n depth: node.depth,\n count: node.count,\n hasChildren,\n open,\n cellsByValue,\n });\n if (hasChildren && open) walk(node.children);\n }\n };\n walk(primary.rowTree);\n }\n\n return (\n <div className=\"overflow-auto border border-base-300 rounded-box\">\n <Table className=\"table-sm w-full border-collapse\">\n <Table.Head>\n {/* 列分组标签行(交叉表) */}\n {hasCols && (\n <Table.Row>\n <Table.Cell className=\"bg-base-200 font-semibold text-left align-bottom\">\n {groupLabel}\n </Table.Cell>\n {columns.map((ck, ci) => (\n <Table.Cell\n key={ci}\n colSpan={activeValues.length}\n className=\"bg-base-200 font-semibold text-center\"\n >\n {ck.join(' / ')}\n </Table.Cell>\n ))}\n </Table.Row>\n )}\n {/* 度量表头行 */}\n <Table.Row>\n <Table.Cell className=\"bg-base-200 font-semibold text-left\">\n {hasCols ? '' : groupLabel}\n </Table.Cell>\n {columns.map((_, ci) =>\n activeValues.map((v) => (\n <Table.Cell\n key={`${ci}:${v.field}:${v.aggFn}`}\n className=\"bg-base-200 font-semibold text-right\"\n >\n {aggLabel(v.aggFn)}\n {v.field ? `(${fieldLabel(v.field)})` : ''}\n </Table.Cell>\n )),\n )}\n </Table.Row>\n </Table.Head>\n <Table.Body>\n {treeMode\n ? visibleRows.map((row) => (\n <Table.Row key={row.keyStr}>\n <Table.Cell\n style={{ paddingLeft: row.depth * 16 + 8 }}\n >\n <span\n className=\"inline-flex items-center gap-1\"\n style={{\n cursor: row.hasChildren\n ? 'pointer'\n : 'default',\n }}\n onClick={() =>\n row.hasChildren && toggle(row.keyStr)\n }\n >\n <span\n aria-hidden\n className=\"inline-block w-3 text-xs opacity-60\"\n >\n {row.hasChildren\n ? row.open\n ? '▾'\n : '▸'\n : ''}\n </span>\n <span\n style={{\n fontWeight:\n row.depth === 0 ? 600 : 400,\n }}\n >\n {row.label}\n </span>\n <span className=\"opacity-50\">\n {' '}\n ({row.count.toLocaleString()})\n </span>\n </span>\n </Table.Cell>\n {Array.from({\n length: hasCols ? colCount : 1,\n }).map((_, ci) =>\n row.cellsByValue.map((cells, vi) => (\n <Table.Cell\n key={`${ci}:${vi}`}\n className=\"text-right tabular-nums\"\n >\n {fmt(cells[hasCols ? ci : 0] ?? null)}\n </Table.Cell>\n )),\n )}\n </Table.Row>\n ))\n : rowKeys.map((rk, ri) => (\n <Table.Row key={ri}>\n <Table.Cell>\n {rk.join(' / ')}\n {rowCounts[ri] != null && (\n <span className=\"opacity-50\">\n {' '}\n ({rowCounts[ri].toLocaleString()})\n </span>\n )}\n </Table.Cell>\n {Array.from({\n length: hasCols ? colCount : 1,\n }).map((_, ci) =>\n results.map((res, vi) => (\n <Table.Cell\n key={`${ci}:${vi}`}\n className=\"text-right tabular-nums\"\n >\n {fmt(\n res.matrix[ri]?.[\n hasCols ? ci : 0\n ] ?? null,\n )}\n </Table.Cell>\n )),\n )}\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </div>\n );\n}\n\nexport default PivotView;\n"],"mappings":"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"}
1
+ {"version":3,"file":"PivotView.js","names":["Table","TableWithCompounds","SEP","AGG_LABELS","fmt","v","PivotView","expanded","setExpanded","useState","fieldLabel","fieldLabels","f","aggLabel","fn","lang","results","useMemo","values","config","computePivot","data","rowFields","colFields","primary","activeValues","rf","colCount","colKeys","rowCounts","hasCols","treeMode","treeView","groupLabel","columns","toggle","prev","nodeKey","visibleRows","indexTree","map","walk","n","ns","nodes","valueIndexes","r","node","keyStr","hasChildren","open","cellsByValue","idx","ck","ci","row","cells","vi","rowKeys","rk","ri","res"],"sources":["../../../../src/components/pro/DataTable/PivotView.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react';\nimport Table from '../../Table';\nimport {\n computePivot,\n type PivotAggFn,\n type PivotConfig,\n type PivotResult,\n type PivotRowNode,\n} from './pivotEngine';\n\nconst SEP = '\\u0001';\n\n/** 一个数值度量:字段 + 聚合函数。 */\nexport interface PivotValue {\n field: string;\n aggFn: PivotAggFn;\n}\n\n/** 字段的展示标签映射。 */\nexport type PivotFieldLabels = Record<string, string>;\n\nconst AGG_LABELS: Record<PivotAggFn, { zh: string; en: string }> = {\n sum: { zh: '求和', en: 'Sum' },\n avg: { zh: '平均', en: 'Avg' },\n count: { zh: '计数', en: 'Count' },\n min: { zh: '最小', en: 'Min' },\n max: { zh: '最大', en: 'Max' },\n};\n\nfunction fmt(v: number | null): string {\n if (v == null) return '';\n return v.toLocaleString(undefined, { maximumFractionDigits: 2 });\n}\n\nexport interface PivotViewProps<T extends object> {\n /** 全量数据(会在其之上进行客户端聚合)。 */\n data: T[];\n /** 行分组字段。 */\n rowFields: string[];\n /** 列分组字段。 */\n colFields: string[];\n /** 数值度量列表。 */\n values: PivotValue[];\n /** 字段展示标签。 */\n fieldLabels?: PivotFieldLabels;\n /** 语言(影响聚合函数文案)。默认 'zh'。 */\n lang?: 'zh' | 'en';\n /** 是否以树形(可展开分组)方式展示多级行分组。默认 true。 */\n treeView?: boolean;\n}\n\n/**\n * ag-grid 风格的透视(Pivot)交叉表视图。支持多级行分组、列分组交叉表、\n * 多个数值度量,以及树形分组的展开/折叠。\n */\nexport function PivotView<T extends object>({\n data,\n rowFields,\n colFields,\n values,\n fieldLabels = {},\n lang = 'zh',\n treeView = true,\n}: PivotViewProps<T>) {\n const [expanded, setExpanded] = useState<Record<string, boolean>>({});\n\n const fieldLabel = (f: string) => fieldLabels[f] ?? f;\n const aggLabel = (fn: PivotAggFn) => AGG_LABELS[fn][lang];\n\n // 为每个数值度量分别计算一份透视结果。\n const results: PivotResult[] = useMemo(() => {\n const activeValues = values.length\n ? values\n : [{ field: '', aggFn: 'count' as PivotAggFn }];\n return activeValues.map((v) => {\n const config: PivotConfig = {\n rowFields,\n colFields,\n valueField: v.field,\n aggFn: v.aggFn,\n };\n return computePivot(data, config);\n });\n }, [data, rowFields, colFields, values]);\n\n const primary = results[0];\n if (!primary || rowFields.length === 0) {\n return (\n <div className=\"p-8 text-center opacity-60\">\n {lang === 'zh'\n ? '请至少配置一个行分组字段以启用透视视图。'\n : 'Add at least one row group field to enable the pivot view.'}\n </div>\n );\n }\n\n const activeValues = values.length ? values : [{ field: '', aggFn: 'count' as PivotAggFn }];\n const { rowKeys, colKeys, rowFields: rf } = primary;\n const colCount = colKeys.length;\n const rowCounts = primary.rowCounts;\n const hasCols = primary.colFields.length > 0;\n const treeMode = treeView && rf.length > 1 && primary.rowTree.length > 0;\n\n const groupLabel = rf.map(fieldLabel).join(' / ') || 'Group';\n const columns = hasCols ? colKeys : [[]];\n\n const toggle = (nodeKey: string) =>\n setExpanded((prev) => ({ ...prev, [nodeKey]: !prev[nodeKey] }));\n\n // 树形模式:将树扁平化为可见行(尊重展开状态)。\n interface VisibleRow {\n keyStr: string;\n label: string;\n depth: number;\n count: number;\n hasChildren: boolean;\n open: boolean;\n cellsByValue: (number | null)[][];\n }\n\n const visibleRows: VisibleRow[] = [];\n if (treeMode) {\n const indexTree = (nodes: PivotRowNode[]): Map<string, PivotRowNode> => {\n const map = new Map<string, PivotRowNode>();\n const walk = (ns: PivotRowNode[]) => {\n for (const n of ns) {\n map.set(n.key.join(SEP), n);\n if (n.children.length) walk(n.children);\n }\n };\n walk(nodes);\n return map;\n };\n const valueIndexes = results.map((r) => indexTree(r.rowTree));\n\n const walk = (nodes: PivotRowNode[]) => {\n for (const node of nodes) {\n const keyStr = node.key.join(SEP);\n const hasChildren = node.children.length > 0;\n const open = expanded[keyStr] ?? node.depth === 0;\n const cellsByValue = valueIndexes.map(\n (idx) => idx.get(keyStr)?.cells ?? [],\n );\n visibleRows.push({\n keyStr,\n label: node.label,\n depth: node.depth,\n count: node.count,\n hasChildren,\n open,\n cellsByValue,\n });\n if (hasChildren && open) walk(node.children);\n }\n };\n walk(primary.rowTree);\n }\n\n return (\n <div className=\"overflow-auto border border-base-300 rounded-box\">\n <Table className=\"table-sm w-full border-collapse\">\n <Table.Head>\n {/* 列分组标签行(交叉表) */}\n {hasCols && (\n <Table.Row>\n <Table.Cell className=\"bg-base-200 font-semibold text-left align-bottom\">\n {groupLabel}\n </Table.Cell>\n {columns.map((ck, ci) => (\n <Table.Cell\n key={ci}\n colSpan={activeValues.length}\n className=\"bg-base-200 font-semibold text-center\"\n >\n {ck.join(' / ')}\n </Table.Cell>\n ))}\n </Table.Row>\n )}\n {/* 度量表头行 */}\n <Table.Row>\n <Table.Cell className=\"bg-base-200 font-semibold text-left\">\n {hasCols ? '' : groupLabel}\n </Table.Cell>\n {columns.map((_, ci) =>\n activeValues.map((v) => (\n <Table.Cell\n key={`${ci}:${v.field}:${v.aggFn}`}\n className=\"bg-base-200 font-semibold text-right\"\n >\n {aggLabel(v.aggFn)}\n {v.field ? `(${fieldLabel(v.field)})` : ''}\n </Table.Cell>\n )),\n )}\n </Table.Row>\n </Table.Head>\n <Table.Body>\n {treeMode\n ? visibleRows.map((row) => (\n <Table.Row key={row.keyStr}>\n <Table.Cell\n style={{ paddingLeft: row.depth * 16 + 8 }}\n >\n <span\n className=\"inline-flex items-center gap-1\"\n style={{\n cursor: row.hasChildren\n ? 'pointer'\n : 'default',\n }}\n onClick={() =>\n row.hasChildren && toggle(row.keyStr)\n }\n >\n <span\n aria-hidden\n className=\"inline-block w-3 text-xs opacity-60\"\n >\n {row.hasChildren\n ? row.open\n ? '▾'\n : '▸'\n : ''}\n </span>\n <span\n style={{\n fontWeight:\n row.depth === 0 ? 600 : 400,\n }}\n >\n {row.label}\n </span>\n <span className=\"opacity-50\">\n {' '}\n ({row.count.toLocaleString()})\n </span>\n </span>\n </Table.Cell>\n {Array.from({\n length: hasCols ? colCount : 1,\n }).map((_, ci) =>\n row.cellsByValue.map((cells, vi) => (\n <Table.Cell\n key={`${ci}:${vi}`}\n className=\"text-right tabular-nums\"\n >\n {fmt(cells[hasCols ? ci : 0] ?? null)}\n </Table.Cell>\n )),\n )}\n </Table.Row>\n ))\n : rowKeys.map((rk, ri) => (\n <Table.Row key={ri}>\n <Table.Cell>\n {rk.join(' / ')}\n {rowCounts[ri] != null && (\n <span className=\"opacity-50\">\n {' '}\n ({rowCounts[ri].toLocaleString()})\n </span>\n )}\n </Table.Cell>\n {Array.from({\n length: hasCols ? colCount : 1,\n }).map((_, ci) =>\n results.map((res, vi) => (\n <Table.Cell\n key={`${ci}:${vi}`}\n className=\"text-right tabular-nums\"\n >\n {fmt(\n res.matrix[ri]?.[\n hasCols ? ci : 0\n ] ?? null,\n )}\n </Table.Cell>\n )),\n )}\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </div>\n );\n}\n\nexport default PivotView;\n"],"mappings":"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"}