dishui 0.0.62 → 0.0.65

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 (177) hide show
  1. package/dist/components/Badge/index.js +12 -9
  2. package/dist/components/Badge/index.js.map +1 -1
  3. package/dist/components/Button/index.js +43 -40
  4. package/dist/components/Button/index.js.map +1 -1
  5. package/dist/components/Card/index.d.ts +11 -0
  6. package/dist/components/Card/index.js +62 -37
  7. package/dist/components/Card/index.js.map +1 -1
  8. package/dist/components/Chart/Chart.js.map +1 -1
  9. package/dist/components/Checkbox/index.js +32 -30
  10. package/dist/components/Checkbox/index.js.map +1 -1
  11. package/dist/components/Demo/index.js.map +1 -1
  12. package/dist/components/EmptyState/index.d.ts +4 -1
  13. package/dist/components/EmptyState/index.js +3 -3
  14. package/dist/components/EmptyState/index.js.map +1 -1
  15. package/dist/components/FileUploader/DropZone.js.map +1 -1
  16. package/dist/components/FileUploader/FileItem.js.map +1 -1
  17. package/dist/components/FileUploader/FileUploader.js.map +1 -1
  18. package/dist/components/FileUploader/UploadQueue.js.map +1 -1
  19. package/dist/components/Input/index.js +30 -30
  20. package/dist/components/Input/index.js.map +1 -1
  21. package/dist/components/Label/index.js +41 -40
  22. package/dist/components/Label/index.js.map +1 -1
  23. package/dist/components/List/index.js +47 -32
  24. package/dist/components/List/index.js.map +1 -1
  25. package/dist/components/Markdown/Markdown.js +61 -57
  26. package/dist/components/Markdown/Markdown.js.map +1 -1
  27. package/dist/components/Markdown/markdownComponents.js +49 -49
  28. package/dist/components/Markdown/markdownComponents.js.map +1 -1
  29. package/dist/components/Modal/index.d.ts +7 -3
  30. package/dist/components/Modal/index.js +77 -65
  31. package/dist/components/Modal/index.js.map +1 -1
  32. package/dist/components/Page/index.d.ts +58 -0
  33. package/dist/components/Page/index.js +74 -0
  34. package/dist/components/Page/index.js.map +1 -0
  35. package/dist/components/PageHeader/index.js.map +1 -1
  36. package/dist/components/Select/index.js +0 -3
  37. package/dist/components/Select/index.js.map +1 -1
  38. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  39. package/dist/components/StatCard/index.d.ts +3 -1
  40. package/dist/components/StatCard/index.js +39 -11
  41. package/dist/components/StatCard/index.js.map +1 -1
  42. package/dist/components/Table/index.js +103 -85
  43. package/dist/components/Table/index.js.map +1 -1
  44. package/dist/components/Tabs/index.d.ts +19 -5
  45. package/dist/components/Tabs/index.js +32 -13
  46. package/dist/components/Tabs/index.js.map +1 -1
  47. package/dist/components/Tree/Tree.js.map +1 -1
  48. package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
  49. package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
  50. package/dist/components/pro/CodeEditor/editors/CodeEditor.js +141 -134
  51. package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
  52. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +81 -78
  53. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
  54. package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
  55. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
  56. package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
  57. package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
  58. package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
  59. package/dist/components/pro/CodeEditor/themes.js +59 -59
  60. package/dist/components/pro/CodeEditor/themes.js.map +1 -1
  61. package/dist/components/pro/DataTable/DataTable.js +49 -48
  62. package/dist/components/pro/DataTable/DataTable.js.map +1 -1
  63. package/dist/components/pro/DataTable/Filters.js +42 -42
  64. package/dist/components/pro/DataTable/Filters.js.map +1 -1
  65. package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
  66. package/dist/components/pro/DataTable/PivotView.js +35 -32
  67. package/dist/components/pro/DataTable/PivotView.js.map +1 -1
  68. package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
  69. package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
  70. package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
  71. package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
  72. package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
  73. package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
  74. package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
  75. package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
  76. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  77. package/dist/components/pro/DataTable/tanstack-table.js +37 -37
  78. package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
  79. package/dist/components/pro/FileExplorer/Breadcrumb.js +53 -53
  80. package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
  81. package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
  82. package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
  83. package/dist/components/pro/FileExplorer/FileIcon.js +22 -22
  84. package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
  85. package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
  86. package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
  87. package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
  88. package/dist/components/pro/Flow/Flow.js +496 -494
  89. package/dist/components/pro/Flow/Flow.js.map +1 -1
  90. package/dist/components/pro/Flow/FlowCanvas.js +916 -917
  91. package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
  92. package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
  93. package/dist/components/pro/Flow/edges/EdgeRenderer.js +59 -59
  94. package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
  95. package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
  96. package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
  97. package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
  98. package/dist/components/pro/Flow/hooks/useLayoutActions.js +9 -11
  99. package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
  100. package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
  101. package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
  102. package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
  103. package/dist/components/pro/Flow/lines/FreehandTool.js +9 -9
  104. package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
  105. package/dist/components/pro/Flow/lines/LineRenderer.js +5 -5
  106. package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
  107. package/dist/components/pro/Flow/nodes/DataNodeView.js +113 -93
  108. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  109. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  110. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  111. package/dist/components/pro/Flow/nodes/Model3DView.js +1 -1
  112. package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
  113. package/dist/components/pro/Flow/nodes/NodeRenderer.js +118 -118
  114. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  115. package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
  116. package/dist/components/pro/Flow/nodes/shapes.js +1 -3
  117. package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
  118. package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
  119. package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
  120. package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
  121. package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
  122. package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
  123. package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
  124. package/dist/components/pro/Flow/panels/FlowToolbar.js +79 -79
  125. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  126. package/dist/components/pro/Flow/panels/InspectorPanel.js +57 -57
  127. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  128. package/dist/components/pro/Flow/panels/OutlinePanel.js +26 -22
  129. package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
  130. package/dist/components/pro/Flow/panels/PresentationMode.js +18 -16
  131. package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
  132. package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
  133. package/dist/components/pro/Flow/panels/ShapePalette.js +109 -104
  134. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  135. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  136. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  137. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  138. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  139. package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
  140. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  141. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  142. package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
  143. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  144. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  145. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  146. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  147. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  148. package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
  149. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
  150. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  151. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  152. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  153. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  154. package/dist/contexts/AppContext.js.map +1 -1
  155. package/dist/dishui.css +1 -1
  156. package/dist/hooks/useTableColumns.js +7 -8
  157. package/dist/hooks/useTableColumns.js.map +1 -1
  158. package/dist/index.d.ts +2 -0
  159. package/dist/index.js +227 -221
  160. package/dist/layouts/MainLayout.js +22 -22
  161. package/dist/layouts/MainLayout.js.map +1 -1
  162. package/dist/layouts/Navbar.js.map +1 -1
  163. package/dist/layouts/Sidebar.js +94 -73
  164. package/dist/layouts/Sidebar.js.map +1 -1
  165. package/dist/layouts/headbar/Headbar.js.map +1 -1
  166. package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
  167. package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
  168. package/dist/layouts/headbar/HeadbarThemeSwitcher.js +11 -11
  169. package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
  170. package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
  171. package/dist/utils/i18n.js +10 -10
  172. package/dist/utils/i18n.js.map +1 -1
  173. package/dist/utils/menu.js.map +1 -1
  174. package/dist/utils/routerBuilder.js +17 -15
  175. package/dist/utils/routerBuilder.js.map +1 -1
  176. package/dist/utils/themes.js.map +1 -1
  177. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownBlock.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/extensions/MarkdownBlock.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { Node, mergeAttributes } from '@tiptap/react';\nimport { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';\nimport type { NodeViewProps } from '@tiptap/react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\nimport rehypeRaw from 'rehype-raw';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport mermaid from 'mermaid';\nimport 'katex/dist/katex.min.css';\n\nlet mermaidInitialized = false;\n\nfunction initMermaid() {\n if (!mermaidInitialized) {\n mermaid.initialize({\n startOnLoad: false,\n theme: 'default',\n securityLevel: 'loose',\n fontFamily: 'inherit',\n flowchart: { useMaxWidth: true, htmlLabels: true },\n });\n mermaidInitialized = true;\n }\n}\n\nconst MermaidRenderer: React.FC<{ code: string }> = ({ code }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!code.trim() || !containerRef.current) return;\n initMermaid();\n\n let cancelled = false;\n const render = async () => {\n try {\n const id = `mermaid-md-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n const { svg } = await mermaid.render(id, code);\n if (!cancelled && containerRef.current) {\n containerRef.current.innerHTML = svg;\n }\n } catch (err) {\n if (!cancelled && containerRef.current) {\n containerRef.current.innerHTML = `<pre style=\"color:red;font-size:12px;\">${String(err)}</pre>`;\n }\n }\n };\n render();\n return () => { cancelled = true; };\n }, [code]);\n\n return <div ref={containerRef} className=\"rte-mermaid-container\" />;\n};\n\nconst MarkdownPreview: React.FC<{ content: string }> = ({ content }) => {\n return (\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeKatex, rehypeRaw]}\n components={{\n code({ className, children, ...props }) {\n const match = /language-(\\w+)/.exec(className || '');\n const lang = match?.[1];\n const text = String(children).replace(/\\n$/, '');\n\n if (lang === 'mermaid') {\n return <MermaidRenderer code={text} />;\n }\n\n if (lang) {\n return (\n <SyntaxHighlighter\n style={oneLight as Record<string, React.CSSProperties>}\n language={lang}\n PreTag=\"div\"\n customStyle={{\n borderRadius: '0.5rem',\n fontSize: '0.875em',\n padding: '1em',\n margin: '0.5em 0',\n }}\n >\n {text}\n </SyntaxHighlighter>\n );\n }\n return <code className={className} {...props}>{children}</code>;\n },\n }}\n >\n {content}\n </ReactMarkdown>\n );\n};\n\nconst MarkdownBlockView: React.FC<NodeViewProps> = ({\n node,\n updateAttributes,\n selected,\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [localContent, setLocalContent] = useState(node.attrs.content || '');\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n setLocalContent(node.attrs.content || '');\n }, [node.attrs.content]);\n\n useEffect(() => {\n if (isEditing && textareaRef.current) {\n textareaRef.current.focus();\n adjustTextareaHeight(textareaRef.current);\n }\n }, [isEditing]);\n\n const adjustTextareaHeight = (el: HTMLTextAreaElement) => {\n el.style.height = 'auto';\n el.style.height = el.scrollHeight + 'px';\n };\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setLocalContent(e.target.value);\n adjustTextareaHeight(e.target);\n }, []);\n\n const handleBlur = useCallback(() => {\n updateAttributes({ content: localContent });\n setIsEditing(false);\n }, [localContent, updateAttributes]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n updateAttributes({ content: localContent });\n setIsEditing(false);\n }\n }, [localContent, updateAttributes]);\n\n const defaultContent = `# Markdown Block\n\nWrite your **markdown** here.\n\n\\`\\`\\`mermaid\ngraph LR\n A[Start] --> B[End]\n\\`\\`\\`\n`;\n\n const displayContent = localContent || defaultContent;\n\n return (\n <NodeViewWrapper className={`rte-markdown-block ${selected ? 'rte-markdown-block--selected' : ''}`}>\n <div className=\"rte-markdown-block__header\">\n <span className=\"rte-markdown-block__label\">Markdown</span>\n <button\n type=\"button\"\n className={`rte-markdown-block__toggle ${isEditing ? 'rte-markdown-block__toggle--active' : ''}`}\n onClick={() => {\n if (isEditing) {\n updateAttributes({ content: localContent });\n }\n setIsEditing(!isEditing);\n }}\n title={isEditing ? 'Preview' : 'Edit'}\n >\n {isEditing ? (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n ) : (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n )}\n <span>{isEditing ? 'Preview' : 'Edit'}</span>\n </button>\n </div>\n\n <div className=\"rte-markdown-block__body\">\n {isEditing ? (\n <textarea\n ref={textareaRef}\n className=\"rte-markdown-block__editor\"\n value={localContent}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder=\"Enter Markdown content...\"\n rows={5}\n />\n ) : (\n <div\n className=\"rte-markdown-block__preview prose\"\n onDoubleClick={() => setIsEditing(true)}\n >\n {displayContent.trim() ? (\n <MarkdownPreview content={displayContent} />\n ) : (\n <p className=\"rte-markdown-block__placeholder\">\n Double-click to edit Markdown content...\n </p>\n )}\n </div>\n )}\n </div>\n </NodeViewWrapper>\n );\n};\n\nexport const MarkdownBlockExtension = Node.create({\n name: 'markdownBlock',\n group: 'block',\n atom: true,\n draggable: true,\n\n addAttributes() {\n return {\n content: {\n default: '',\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"markdown-block\"]',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'markdown-block' }), 0];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(MarkdownBlockView);\n },\n});\n\nexport default MarkdownBlockExtension;\n"],"mappings":";;;;;;;;;;;;AAcA,IAAI,IAAqB;AAEzB,SAAS,IAAc;AACrB,EAAK,MACH,EAAQ,WAAW;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,WAAW;AAAA,MAAE,aAAa;AAAA,MAAM,YAAY;AAAA,IAAK;AAAA,EACnD,CAAC,GACD,IAAqB;AAEzB;AAEA,IAAM,IAAA,CAA+C,EAAE,MAAA,EAAA,MAAW;AAChE,QAAM,IAAe,EAAuB,IAAI;AAEhD,SAAA,EAAA,MAAgB;AACd,QAAI,CAAC,EAAK,KAAK,KAAK,CAAC,EAAa,QAAS;AAC3C,IAAA,EAAY;AAEZ,QAAI,IAAY;AAchB,YAbe,YAAY;AACzB,UAAI;AACF,cAAM,IAAK,cAAc,KAAK,IAAI,CAAA,IAAK,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAA,IACtE,EAAE,KAAA,EAAA,IAAQ,MAAM,EAAQ,OAAO,GAAI,CAAI;AAC7C,QAAI,CAAC,KAAa,EAAa,YAC7B,EAAa,QAAQ,YAAY;AAAA,MAErC,SAAS,GAAK;AACZ,QAAI,CAAC,KAAa,EAAa,YAC7B,EAAa,QAAQ,YAAY,0CAA0C,OAAO,CAAG,CAAA;AAAA,MAEzF;AAAA,IACF,GACO,GACP,MAAa;AAAE,MAAA,IAAY;AAAA,IAAM;AAAA,EACnC,GAAG,CAAC,CAAI,CAAC,GAEF,gBAAA,EAAC,OAAD;AAAA,IAAK,KAAK;AAAA,IAAc,WAAU;AAAA,EAAyB,CAAA;AACpE,GAEM,IAAA,CAAkD,EAAE,SAAA,EAAA,MAEtD,gBAAA,EAAC,GAAD;AAAA,EACE,eAAe,CAAC,GAAW,CAAU;AAAA,EACrC,eAAe,CAAC,GAAa,CAAS;AAAA,EACtC,YAAY,EACV,KAAK,EAAE,WAAA,GAAW,UAAA,GAAU,GAAG,EAAA,GAAS;AAEtC,UAAM,IADQ,iBAAiB,KAAK,KAAa,EACpC,IAAQ,CAAA,GACf,IAAO,OAAO,CAAQ,EAAE,QAAQ,OAAO,EAAE;AAE/C,WAAI,MAAS,YACJ,gBAAA,EAAC,GAAD,EAAiB,MAAM,EAAO,CAAA,IAGnC,IAEA,gBAAA,EAAC,GAAD;AAAA,MACE,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAO;AAAA,MACP,aAAa;AAAA,QACX,cAAc;AAAA,QACd,UAAU;AAAA,QACV,SAAS;AAAA,QACT,QAAQ;AAAA,MACV;AAAA,gBAEC;AAAA,IACgB,CAAA,IAGhB,gBAAA,EAAC,QAAD;AAAA,MAAiB,WAAA;AAAA,MAAW,GAAI;AAAA,MAAQ,UAAA;AAAA,IAAe,CAAA;AAAA,EAChE,EACF;AAAA,YAEC;AACY,CAAA,GAIb,IAAA,CAA8C,EAClD,MAAA,GACA,kBAAA,GACA,UAAA,EAAA,MACI;AACJ,QAAM,CAAC,GAAW,CAAA,IAAgB,EAAS,EAAK,GAC1C,CAAC,GAAc,CAAA,IAAmB,EAAS,EAAK,MAAM,WAAW,EAAE,GACnE,IAAc,EAA4B,IAAI;AAEpD,EAAA,EAAA,MAAgB;AACd,IAAA,EAAgB,EAAK,MAAM,WAAW,EAAE;AAAA,EAC1C,GAAG,CAAC,EAAK,MAAM,OAAO,CAAC,GAEvB,EAAA,MAAgB;AACd,IAAI,KAAa,EAAY,YAC3B,EAAY,QAAQ,MAAM,GAC1B,EAAqB,EAAY,OAAO;AAAA,EAE5C,GAAG,CAAC,CAAS,CAAC;AAEd,QAAM,IAAA,CAAwB,MAA4B;AACxD,IAAA,EAAG,MAAM,SAAS,QAClB,EAAG,MAAM,SAAS,EAAG,eAAe;AAAA,EACtC,GAEM,IAAe,EAAA,CAAa,MAA8C;AAC9E,IAAA,EAAgB,EAAE,OAAO,KAAK,GAC9B,EAAqB,EAAE,MAAM;AAAA,EAC/B,GAAG,CAAC,CAAC,GAEC,IAAa,EAAA,MAAkB;AACnC,IAAA,EAAiB,EAAE,SAAS,EAAa,CAAC,GAC1C,EAAa,EAAK;AAAA,EACpB,GAAG,CAAC,GAAc,CAAgB,CAAC,GAE7B,IAAgB,EAAA,CAAa,MAA2B;AAC5D,IAAI,EAAE,QAAQ,aACZ,EAAiB,EAAE,SAAS,EAAa,CAAC,GAC1C,EAAa,EAAK;AAAA,EAEtB,GAAG,CAAC,GAAc,CAAgB,CAAC,GAY7B,IAAiB,KAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEvC,SACE,gBAAA,EAAC,GAAD;AAAA,IAAiB,WAAW,sBAAsB,IAAW,iCAAiC,EAAA;AAAA,cAA9F,CACE,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBAAf,CACE,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,kBAA4B;AAAA,MAAc,CAAA,GAC1D,gBAAA,EAAC,UAAD;AAAA,QACE,MAAK;AAAA,QACL,WAAW,8BAA8B,IAAY,uCAAuC,EAAA;AAAA,QAC5F,SAAA,MAAe;AACb,UAAI,KACF,EAAiB,EAAE,SAAS,EAAa,CAAC,GAE5C,EAAa,CAAC,CAAS;AAAA,QACzB;AAAA,QACA,OAAO,IAAY,YAAY;AAAA,kBATjC,CAWG,IACC,gBAAA,EAAC,OAAD;AAAA,UAAK,OAAM;AAAA,UAAK,QAAO;AAAA,UAAK,SAAQ;AAAA,UAAY,MAAK;AAAA,UAAO,QAAO;AAAA,UAAe,aAAY;AAAA,UAAI,eAAc;AAAA,UAAQ,gBAAe;AAAA,oBAAvI,CACE,gBAAA,EAAC,QAAD,EAAM,GAAE,+CAAgD,CAAA,GACxD,gBAAA,EAAC,UAAD;AAAA,YAAQ,IAAG;AAAA,YAAK,IAAG;AAAA,YAAK,GAAE;AAAA,UAAK,CAAA,CAC5B;AAAA,aAEL,gBAAA,EAAC,OAAD;AAAA,UAAK,OAAM;AAAA,UAAK,QAAO;AAAA,UAAK,SAAQ;AAAA,UAAY,MAAK;AAAA,UAAO,QAAO;AAAA,UAAe,aAAY;AAAA,UAAI,eAAc;AAAA,UAAQ,gBAAe;AAAA,oBAAvI,CACE,gBAAA,EAAC,QAAD,EAAM,GAAE,wDAAyD,CAAA,GACjE,gBAAA,EAAC,QAAD,EAAM,GAAE,wDAAyD,CAAA,CAC9D;AAAA,YAEP,gBAAA,EAAC,QAAD,EAAA,UAAO,IAAY,YAAY,OAAa,CAAA,CACtC;AAAA,QACL;AAAA,QAEL,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBACZ,IACC,gBAAA,EAAC,YAAD;AAAA,QACE,KAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAO;AAAA,QACP,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAY;AAAA,QACZ,MAAM;AAAA,MACP,CAAA,IAED,gBAAA,EAAC,OAAD;AAAA,QACE,WAAU;AAAA,QACV,eAAA,MAAqB,EAAa,EAAI;AAAA,kBAErC,EAAe,KAAK,IACnB,gBAAA,EAAC,GAAD,EAAiB,SAAS,EAAiB,CAAA,IAE3C,gBAAA,EAAC,KAAD;AAAA,UAAG,WAAU;AAAA,oBAAkC;AAAA,QAE5C,CAAA;AAAA,MAEF,CAAA;AAAA,IAEJ,CAAA,CACU;AAAA;AAErB,GAEa,IAAyB,EAAK,OAAO;AAAA,EAChD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,WAAW;AAAA,EAEX,gBAAgB;AACd,WAAO,EACL,SAAS,EACP,SAAS,GACX,EACF;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO,CACL,EACE,KAAK,kCACP,CACF;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,gBAAA,EAAA,GAAkB;AAC7B,WAAO;AAAA,MAAC;AAAA,MAAO,EAAgB,GAAgB,EAAE,aAAa,iBAAiB,CAAC;AAAA,MAAG;AAAA,IAAC;AAAA,EACtF;AAAA,EAEA,cAAc;AACZ,WAAO,EAAsB,CAAiB;AAAA,EAChD;AACF,CAAC"}
1
+ {"version":3,"file":"MarkdownBlock.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/extensions/MarkdownBlock.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { Node, mergeAttributes } from '@tiptap/react';\nimport { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';\nimport type { NodeViewProps } from '@tiptap/react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\nimport rehypeRaw from 'rehype-raw';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport mermaid from 'mermaid';\nimport 'katex/dist/katex.min.css';\n\nlet mermaidInitialized = false;\n\nfunction initMermaid() {\n if (!mermaidInitialized) {\n mermaid.initialize({\n startOnLoad: false,\n theme: 'default',\n securityLevel: 'loose',\n fontFamily: 'inherit',\n flowchart: { useMaxWidth: true, htmlLabels: true },\n });\n mermaidInitialized = true;\n }\n}\n\nconst MermaidRenderer: React.FC<{ code: string }> = ({ code }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!code.trim() || !containerRef.current) return;\n initMermaid();\n\n let cancelled = false;\n const render = async () => {\n try {\n const id = `mermaid-md-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n const { svg } = await mermaid.render(id, code);\n if (!cancelled && containerRef.current) {\n containerRef.current.innerHTML = svg;\n }\n } catch (err) {\n if (!cancelled && containerRef.current) {\n containerRef.current.innerHTML = `<pre style=\"color:red;font-size:12px;\">${String(err)}</pre>`;\n }\n }\n };\n render();\n return () => { cancelled = true; };\n }, [code]);\n\n return <div ref={containerRef} className=\"rte-mermaid-container\" />;\n};\n\nconst MarkdownPreview: React.FC<{ content: string }> = ({ content }) => {\n return (\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeKatex, rehypeRaw]}\n components={{\n code({ className, children, ...props }) {\n const match = /language-(\\w+)/.exec(className || '');\n const lang = match?.[1];\n const text = String(children).replace(/\\n$/, '');\n\n if (lang === 'mermaid') {\n return <MermaidRenderer code={text} />;\n }\n\n if (lang) {\n return (\n <SyntaxHighlighter\n style={oneLight as Record<string, React.CSSProperties>}\n language={lang}\n PreTag=\"div\"\n customStyle={{\n borderRadius: '0.5rem',\n fontSize: '0.875em',\n padding: '1em',\n margin: '0.5em 0',\n }}\n >\n {text}\n </SyntaxHighlighter>\n );\n }\n return <code className={className} {...props}>{children}</code>;\n },\n }}\n >\n {content}\n </ReactMarkdown>\n );\n};\n\nconst MarkdownBlockView: React.FC<NodeViewProps> = ({\n node,\n updateAttributes,\n selected,\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [localContent, setLocalContent] = useState(node.attrs.content || '');\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n setLocalContent(node.attrs.content || '');\n }, [node.attrs.content]);\n\n useEffect(() => {\n if (isEditing && textareaRef.current) {\n textareaRef.current.focus();\n adjustTextareaHeight(textareaRef.current);\n }\n }, [isEditing]);\n\n const adjustTextareaHeight = (el: HTMLTextAreaElement) => {\n el.style.height = 'auto';\n el.style.height = el.scrollHeight + 'px';\n };\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setLocalContent(e.target.value);\n adjustTextareaHeight(e.target);\n }, []);\n\n const handleBlur = useCallback(() => {\n updateAttributes({ content: localContent });\n setIsEditing(false);\n }, [localContent, updateAttributes]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n updateAttributes({ content: localContent });\n setIsEditing(false);\n }\n }, [localContent, updateAttributes]);\n\n const defaultContent = `# Markdown Block\n\nWrite your **markdown** here.\n\n\\`\\`\\`mermaid\ngraph LR\n A[Start] --> B[End]\n\\`\\`\\`\n`;\n\n const displayContent = localContent || defaultContent;\n\n return (\n <NodeViewWrapper className={`rte-markdown-block ${selected ? 'rte-markdown-block--selected' : ''}`}>\n <div className=\"rte-markdown-block__header\">\n <span className=\"rte-markdown-block__label\">Markdown</span>\n <button\n type=\"button\"\n className={`rte-markdown-block__toggle ${isEditing ? 'rte-markdown-block__toggle--active' : ''}`}\n onClick={() => {\n if (isEditing) {\n updateAttributes({ content: localContent });\n }\n setIsEditing(!isEditing);\n }}\n title={isEditing ? 'Preview' : 'Edit'}\n >\n {isEditing ? (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n ) : (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n )}\n <span>{isEditing ? 'Preview' : 'Edit'}</span>\n </button>\n </div>\n\n <div className=\"rte-markdown-block__body\">\n {isEditing ? (\n <textarea\n ref={textareaRef}\n className=\"rte-markdown-block__editor\"\n value={localContent}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder=\"Enter Markdown content...\"\n rows={5}\n />\n ) : (\n <div\n className=\"rte-markdown-block__preview prose\"\n onDoubleClick={() => setIsEditing(true)}\n >\n {displayContent.trim() ? (\n <MarkdownPreview content={displayContent} />\n ) : (\n <p className=\"rte-markdown-block__placeholder\">\n Double-click to edit Markdown content...\n </p>\n )}\n </div>\n )}\n </div>\n </NodeViewWrapper>\n );\n};\n\nexport const MarkdownBlockExtension = Node.create({\n name: 'markdownBlock',\n group: 'block',\n atom: true,\n draggable: true,\n\n addAttributes() {\n return {\n content: {\n default: '',\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"markdown-block\"]',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'markdown-block' }), 0];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(MarkdownBlockView);\n },\n});\n\nexport default MarkdownBlockExtension;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppContext.js","names":[],"sources":["../../src/contexts/AppContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useState, useEffect } from 'react';\nimport { RouterProvider } from '@tanstack/react-router';\nimport { Router } from '@tanstack/react-router';\nimport Sidebar from '../layouts/Sidebar';\nimport { Headbar } from '../layouts/headbar';\nimport type { SearchConfig } from '../layouts/headbar';\nimport { Outlet } from '@tanstack/react-router';\nimport { MenuItem } from '../types/menu';\nimport { ThemeConfig } from '../utils/themes';\nimport { SidebarToggleButtons } from '../components/SidebarToggleButton';\n\n// 主题类型\nexport type ThemeType = 'light' | 'dark' | 'retro' | 'cyberpunk' | 'matrix' | 'oceanblue' | 'eyecare' | 'ghibli' | 'pinkgirl' | 'mintgirl' | 'wuxing' | 'jukebox';\n\n// 用户类型定义\nexport type User = {\n id: string;\n name: string;\n email: string;\n roles: string[];\n};\n\n// 认证上下文类型\nexport type AuthContextType = {\n user: User | null;\n isAuthenticated: boolean;\n login: (user: User) => void;\n logout: () => void;\n hasRole: (role: string) => boolean;\n hasAnyRole: (roles: string[]) => boolean;\n};\n\n// 应用上下文类型\nexport type AppContextType = {\n title?: string;\n language: 'zh' | 'en';\n theme: ThemeType;\n setLanguage: (lang: 'zh' | 'en') => void;\n setTheme: (theme: ThemeType) => void;\n auth: AuthContextType;\n menuItems?: MenuItem[];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n themes?: ThemeConfig[];\n sidebarWidth?: number;\n sidebarCollapsedWidth?: number;\n navbarHeight?: number;\n};\n\nconst AppContext = createContext<AppContextType | undefined>(undefined);\n\nexport const useAppContext = () => {\n const context = useContext(AppContext);\n if (!context) {\n throw new Error('useAppContext must be used within an AppShell');\n }\n return context;\n};\n\n// 导出独立的认证 hook\nexport const useAuth = () => {\n const context = useAppContext();\n return context.auth;\n};\n\n// AppShell 配置类型\nexport type AppShellConfig = {\n title?: string;\n initialLang?: 'zh' | 'en';\n initialTheme?: ThemeType;\n menuItems?: MenuItem[];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n themes?: ThemeConfig[];\n enableAuth?: boolean;\n onAuthRequired?: () => boolean | void;\n protectedRoutes?: string[];\n publicRoutes?: string[];\n loginUrl?: string;\n authFailedCallback?: (path: string, loginUrl: string) => void;\n /** 布局模式: 'sidebar'(默认,顶栏+侧边栏) | 'topbar'(仅顶栏,无侧边栏) */\n layout?: 'sidebar' | 'topbar';\n sidebarWidth?: number;\n sidebarCollapsedWidth?: number;\n navbarHeight?: number; // Navbar 高度(像素),默认 64px\n searchConfig?: SearchConfig;\n /** Headbar 左侧插槽(传入 ReactNode 或接收 toggleSidebar 的渲染函数) */\n headbarLeft?: React.ReactNode | ((toggleSidebar: () => void) => React.ReactNode);\n /** Headbar 中间插槽 */\n headbarMiddle?: React.ReactNode;\n /** Headbar 右侧插槽 */\n headbarRight?: React.ReactNode;\n};\n\n// 全局配置存储\nlet globalConfig: AppShellConfig = {};\nlet globalAuthState: {\n user: User | null;\n setUser: React.Dispatch<React.SetStateAction<User | null>>;\n} | null = null;\n\n// 导出的布局包装器组件 - 用于路由\nexport const AppLayoutWrapper: React.FC = () => {\n const { title, language, theme, menuItems, getMenuItems, themes, sidebarWidth: configSidebarWidth, sidebarCollapsedWidth, navbarHeight: configNavbarHeight } = useAppContext();\n\n // 从 localStorage 读取侧边栏折叠状态\n const [sidebarCollapsed, setSidebarCollapsed] = useState(() => {\n const saved = localStorage.getItem('sidebar-collapsed');\n return saved ? JSON.parse(saved) : false;\n });\n\n const [sidebarWidth, setSidebarWidth] = useState(configSidebarWidth || 280);\n const sidebarRef = React.useRef<HTMLDivElement>(null);\n\n // 当配置的 sidebarWidth 改变时,更新本地 state\n React.useEffect(() => {\n if (configSidebarWidth) {\n setSidebarWidth(configSidebarWidth);\n }\n }, [configSidebarWidth]);\n\n // 保存侧边栏折叠状态到 localStorage\n React.useEffect(() => {\n localStorage.setItem('sidebar-collapsed', JSON.stringify(sidebarCollapsed));\n }, [sidebarCollapsed]);\n\n const toggleSidebar = () => {\n setSidebarCollapsed(!sidebarCollapsed);\n };\n\n const handleSidebarWidthChange = (width: number) => {\n setSidebarWidth(width);\n };\n\n const navbarHeight = configNavbarHeight || 64; // 默认 64px\n const layout = globalConfig.layout || 'sidebar';\n\n // 解析 headbar 插槽:支持 ReactNode 或渲染函数\n const headbarLeftConfig = globalConfig.headbarLeft;\n const resolvedLeft = typeof headbarLeftConfig === 'function'\n ? headbarLeftConfig(toggleSidebar)\n : headbarLeftConfig;\n\n // topbar 模式:仅顶部导航,无侧边栏\n if (layout === 'topbar') {\n return (\n <div className=\"h-screen flex flex-col bg-base-100\" data-theme={theme}>\n <div style={{ height: `${navbarHeight}px`, flexShrink: 0 }}>\n <Headbar\n left={resolvedLeft}\n middle={globalConfig.headbarMiddle}\n right={globalConfig.headbarRight}\n height={navbarHeight}\n />\n </div>\n <main className=\"flex-1 overflow-y-auto\" style={{ paddingLeft: '128px', paddingRight: '128px', paddingTop: '16px', paddingBottom: '16px' }}>\n <Outlet />\n </main>\n </div>\n );\n }\n\n // sidebar 模式(默认):顶栏 + 侧边栏\n return (\n <div className=\"h-screen flex flex-col bg-base-100\" data-theme={theme}>\n {/* 固定高度的 Headbar */}\n <div style={{ height: `${navbarHeight}px`, flexShrink: 0 }}>\n <Headbar\n left={resolvedLeft}\n middle={globalConfig.headbarMiddle}\n right={globalConfig.headbarRight}\n height={navbarHeight}\n />\n </div>\n\n {/* Sidebar 和 Content 区域 - 独立滚动 */}\n <div className=\"flex flex-1 overflow-hidden\" style={{ height: `calc(100vh - ${navbarHeight}px)` }}>\n {/* Sidebar - 独立滚动 */}\n <div\n className=\"flex-shrink-0\"\n ref={sidebarRef}\n style={{ height: '100%', overflow: 'hidden' }}\n >\n <Sidebar\n isCollapsed={sidebarCollapsed}\n language={language}\n items={menuItems}\n getMenuItems={getMenuItems}\n onWidthChange={handleSidebarWidthChange}\n initialWidth={configSidebarWidth || 280}\n collapsedWidth={sidebarCollapsedWidth || 64}\n />\n </div>\n\n {/* Content - 独立滚动 */}\n <main className=\"flex-1 overflow-y-auto\" style={{ height: '100%', paddingLeft: '128px', paddingRight: '128px', paddingTop: '16px', paddingBottom: '16px' }}>\n <Outlet />\n </main>\n\n {/* 悬浮侧边栏切换按钮 */}\n <SidebarToggleButtons\n isCollapsed={sidebarCollapsed}\n onToggle={toggleSidebar}\n sidebarWidth={sidebarWidth}\n collapsedWidth={sidebarCollapsedWidth || 64}\n />\n </div>\n </div>\n );\n};\n\n// AppShell 属性类型\nexport type AppShellProps = {\n router?: Router<any, any>;\n children?: React.ReactNode;\n} & AppShellConfig;\n\n// AppShell 主组件\nexport const AppShell: React.FC<AppShellProps> = ({\n router,\n children,\n title = 'DiShUI',\n initialLang,\n initialTheme,\n menuItems,\n getMenuItems,\n themes,\n enableAuth = false,\n onAuthRequired,\n protectedRoutes = [],\n publicRoutes = ['/login', '/register'],\n loginUrl = '/login',\n authFailedCallback,\n layout = 'sidebar',\n sidebarWidth = 280,\n sidebarCollapsedWidth = 64,\n navbarHeight = 64,\n searchConfig,\n headbarLeft,\n headbarMiddle,\n headbarRight,\n}) => {\n // 保存全局配置\n globalConfig = {\n title,\n initialLang,\n initialTheme,\n menuItems,\n getMenuItems,\n themes,\n enableAuth,\n onAuthRequired,\n protectedRoutes,\n publicRoutes,\n loginUrl,\n authFailedCallback,\n layout,\n sidebarWidth,\n sidebarCollapsedWidth,\n navbarHeight,\n searchConfig,\n headbarLeft,\n headbarMiddle,\n headbarRight,\n };\n\n // 语言状态管理\n const [language, setLanguage] = useState<'zh' | 'en'>(() => {\n const savedLanguage = localStorage.getItem('app-language');\n if (savedLanguage === 'zh' || savedLanguage === 'en') return savedLanguage;\n return initialLang || 'zh';\n });\n\n // 主题状态管理\n const [theme, setTheme] = useState<ThemeType>(() => {\n const savedTheme = localStorage.getItem('app-theme');\n const validThemes: ThemeType[] = ['light', 'dark', 'retro', 'cyberpunk', 'matrix', 'oceanblue', 'eyecare', 'ghibli', 'pinkgirl', 'mintgirl', 'wuxing', 'jukebox'];\n if (savedTheme && validThemes.includes(savedTheme as ThemeType)) {\n return savedTheme as ThemeType;\n }\n return initialTheme || 'light';\n });\n\n // 用户认证状态管理\n const [user, setUser] = useState<User | null>(() => {\n if (!enableAuth) return null;\n const savedUser = localStorage.getItem('app-user');\n return savedUser ? JSON.parse(savedUser) : null;\n });\n\n // 保存全局认证状态\n globalAuthState = { user, setUser };\n\n // 保存语言设置\n useEffect(() => {\n localStorage.setItem('app-language', language);\n }, [language]);\n\n // 保存主题设置\n useEffect(() => {\n localStorage.setItem('app-theme', theme);\n document.documentElement.setAttribute('data-theme', theme);\n }, [theme]);\n\n // 保存用户信息\n useEffect(() => {\n if (enableAuth) {\n if (user) {\n localStorage.setItem('app-user', JSON.stringify(user));\n } else {\n localStorage.removeItem('app-user');\n }\n }\n }, [user, enableAuth]);\n\n // 认证方法\n const login = (newUser: User) => {\n setUser(newUser);\n };\n\n const logout = () => {\n setUser(null);\n localStorage.removeItem('app-user');\n };\n\n const hasRole = (role: string): boolean => {\n return user?.roles.includes(role) || false;\n };\n\n const hasAnyRole = (roles: string[]): boolean => {\n return roles.some(role => user?.roles.includes(role)) || false;\n };\n\n // 路由守卫 - 检查认证状态\n useEffect(() => {\n if (!enableAuth || !router) return;\n\n const unsubscribe = router.subscribe('onBeforeLoad', ({ pathChanged, toLocation }) => {\n if (!pathChanged) return;\n\n const isPublicRoute = publicRoutes.some(route =>\n toLocation.pathname.startsWith(route)\n );\n\n const isProtectedRoute = protectedRoutes.length === 0 ||\n protectedRoutes.some(route => toLocation.pathname.startsWith(route));\n\n if (isProtectedRoute && !isPublicRoute && !user) {\n // 允许调用方先自行处理认证需求。返回 true 表示已处理,直接放行。\n if (onAuthRequired) {\n const handled = onAuthRequired();\n if (handled) return;\n }\n\n // 未被自定义逻辑处理时,执行认证失败回调或默认重定向。\n if (authFailedCallback) {\n authFailedCallback(toLocation.pathname, loginUrl);\n } else {\n window.location.href = loginUrl;\n }\n }\n });\n\n return () => {\n if (unsubscribe) unsubscribe();\n };\n }, [enableAuth, user, router, protectedRoutes, publicRoutes, onAuthRequired, loginUrl, authFailedCallback]);\n\n const authContext: AuthContextType = {\n user,\n isAuthenticated: !!user,\n login,\n logout,\n hasRole,\n hasAnyRole,\n };\n\n const value: AppContextType = {\n title,\n language,\n theme,\n setLanguage,\n setTheme,\n auth: authContext,\n menuItems,\n getMenuItems,\n themes,\n sidebarWidth,\n sidebarCollapsedWidth,\n navbarHeight,\n };\n\n return (\n <AppContext.Provider value={value}>\n {router ? (\n children || <RouterProvider router={router} />\n ) : (\n children\n )}\n </AppContext.Provider>\n );\n};\n\n// 保持向后兼容的 AppProvider 别名\nexport const AppProvider = AppShell;\n\nexport default AppShell;\n"],"mappings":"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"}
1
+ {"version":3,"file":"AppContext.js","names":[],"sources":["../../src/contexts/AppContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useState, useEffect } from 'react';\nimport { RouterProvider } from '@tanstack/react-router';\nimport { Router } from '@tanstack/react-router';\nimport Sidebar from '../layouts/Sidebar';\nimport { Headbar } from '../layouts/headbar';\nimport type { SearchConfig } from '../layouts/headbar';\nimport { Outlet } from '@tanstack/react-router';\nimport { MenuItem } from '../types/menu';\nimport { ThemeConfig } from '../utils/themes';\nimport { SidebarToggleButtons } from '../components/SidebarToggleButton';\n\n// 主题类型\nexport type ThemeType = 'light' | 'dark' | 'retro' | 'cyberpunk' | 'matrix' | 'oceanblue' | 'eyecare' | 'ghibli' | 'pinkgirl' | 'mintgirl' | 'wuxing' | 'jukebox';\n\n// 用户类型定义\nexport type User = {\n id: string;\n name: string;\n email: string;\n roles: string[];\n};\n\n// 认证上下文类型\nexport type AuthContextType = {\n user: User | null;\n isAuthenticated: boolean;\n login: (user: User) => void;\n logout: () => void;\n hasRole: (role: string) => boolean;\n hasAnyRole: (roles: string[]) => boolean;\n};\n\n// 应用上下文类型\nexport type AppContextType = {\n title?: string;\n language: 'zh' | 'en';\n theme: ThemeType;\n setLanguage: (lang: 'zh' | 'en') => void;\n setTheme: (theme: ThemeType) => void;\n auth: AuthContextType;\n menuItems?: MenuItem[];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n themes?: ThemeConfig[];\n sidebarWidth?: number;\n sidebarCollapsedWidth?: number;\n navbarHeight?: number;\n};\n\nconst AppContext = createContext<AppContextType | undefined>(undefined);\n\nexport const useAppContext = () => {\n const context = useContext(AppContext);\n if (!context) {\n throw new Error('useAppContext must be used within an AppShell');\n }\n return context;\n};\n\n// 导出独立的认证 hook\nexport const useAuth = () => {\n const context = useAppContext();\n return context.auth;\n};\n\n// AppShell 配置类型\nexport type AppShellConfig = {\n title?: string;\n initialLang?: 'zh' | 'en';\n initialTheme?: ThemeType;\n menuItems?: MenuItem[];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n themes?: ThemeConfig[];\n enableAuth?: boolean;\n onAuthRequired?: () => boolean | void;\n protectedRoutes?: string[];\n publicRoutes?: string[];\n loginUrl?: string;\n authFailedCallback?: (path: string, loginUrl: string) => void;\n /** 布局模式: 'sidebar'(默认,顶栏+侧边栏) | 'topbar'(仅顶栏,无侧边栏) */\n layout?: 'sidebar' | 'topbar';\n sidebarWidth?: number;\n sidebarCollapsedWidth?: number;\n navbarHeight?: number; // Navbar 高度(像素),默认 64px\n searchConfig?: SearchConfig;\n /** Headbar 左侧插槽(传入 ReactNode 或接收 toggleSidebar 的渲染函数) */\n headbarLeft?: React.ReactNode | ((toggleSidebar: () => void) => React.ReactNode);\n /** Headbar 中间插槽 */\n headbarMiddle?: React.ReactNode;\n /** Headbar 右侧插槽 */\n headbarRight?: React.ReactNode;\n};\n\n// 全局配置存储\nlet globalConfig: AppShellConfig = {};\nlet globalAuthState: {\n user: User | null;\n setUser: React.Dispatch<React.SetStateAction<User | null>>;\n} | null = null;\n\n// 导出的布局包装器组件 - 用于路由\nexport const AppLayoutWrapper: React.FC = () => {\n const { title, language, theme, menuItems, getMenuItems, themes, sidebarWidth: configSidebarWidth, sidebarCollapsedWidth, navbarHeight: configNavbarHeight } = useAppContext();\n\n // 从 localStorage 读取侧边栏折叠状态\n const [sidebarCollapsed, setSidebarCollapsed] = useState(() => {\n const saved = localStorage.getItem('sidebar-collapsed');\n return saved ? JSON.parse(saved) : false;\n });\n\n const [sidebarWidth, setSidebarWidth] = useState(configSidebarWidth || 280);\n const sidebarRef = React.useRef<HTMLDivElement>(null);\n\n // 当配置的 sidebarWidth 改变时,更新本地 state\n React.useEffect(() => {\n if (configSidebarWidth) {\n setSidebarWidth(configSidebarWidth);\n }\n }, [configSidebarWidth]);\n\n // 保存侧边栏折叠状态到 localStorage\n React.useEffect(() => {\n localStorage.setItem('sidebar-collapsed', JSON.stringify(sidebarCollapsed));\n }, [sidebarCollapsed]);\n\n const toggleSidebar = () => {\n setSidebarCollapsed(!sidebarCollapsed);\n };\n\n const handleSidebarWidthChange = (width: number) => {\n setSidebarWidth(width);\n };\n\n const navbarHeight = configNavbarHeight || 64; // 默认 64px\n const layout = globalConfig.layout || 'sidebar';\n\n // 解析 headbar 插槽:支持 ReactNode 或渲染函数\n const headbarLeftConfig = globalConfig.headbarLeft;\n const resolvedLeft = typeof headbarLeftConfig === 'function'\n ? headbarLeftConfig(toggleSidebar)\n : headbarLeftConfig;\n\n // topbar 模式:仅顶部导航,无侧边栏\n if (layout === 'topbar') {\n return (\n <div className=\"h-screen flex flex-col bg-base-100\" data-theme={theme}>\n <div style={{ height: `${navbarHeight}px`, flexShrink: 0 }}>\n <Headbar\n left={resolvedLeft}\n middle={globalConfig.headbarMiddle}\n right={globalConfig.headbarRight}\n height={navbarHeight}\n />\n </div>\n <main className=\"flex-1 overflow-y-auto\" style={{ paddingLeft: '128px', paddingRight: '128px', paddingTop: '16px', paddingBottom: '16px' }}>\n <Outlet />\n </main>\n </div>\n );\n }\n\n // sidebar 模式(默认):顶栏 + 侧边栏\n return (\n <div className=\"h-screen flex flex-col bg-base-100\" data-theme={theme}>\n {/* 固定高度的 Headbar */}\n <div style={{ height: `${navbarHeight}px`, flexShrink: 0 }}>\n <Headbar\n left={resolvedLeft}\n middle={globalConfig.headbarMiddle}\n right={globalConfig.headbarRight}\n height={navbarHeight}\n />\n </div>\n\n {/* Sidebar 和 Content 区域 - 独立滚动 */}\n <div className=\"flex flex-1 overflow-hidden\" style={{ height: `calc(100vh - ${navbarHeight}px)` }}>\n {/* Sidebar - 独立滚动 */}\n <div\n className=\"flex-shrink-0\"\n ref={sidebarRef}\n style={{ height: '100%', overflow: 'hidden' }}\n >\n <Sidebar\n isCollapsed={sidebarCollapsed}\n language={language}\n items={menuItems}\n getMenuItems={getMenuItems}\n onWidthChange={handleSidebarWidthChange}\n initialWidth={configSidebarWidth || 280}\n collapsedWidth={sidebarCollapsedWidth || 64}\n />\n </div>\n\n {/* Content - 独立滚动 */}\n <main className=\"flex-1 overflow-y-auto\" style={{ height: '100%', paddingLeft: '128px', paddingRight: '128px', paddingTop: '16px', paddingBottom: '16px' }}>\n <Outlet />\n </main>\n\n {/* 悬浮侧边栏切换按钮 */}\n <SidebarToggleButtons\n isCollapsed={sidebarCollapsed}\n onToggle={toggleSidebar}\n sidebarWidth={sidebarWidth}\n collapsedWidth={sidebarCollapsedWidth || 64}\n />\n </div>\n </div>\n );\n};\n\n// AppShell 属性类型\nexport type AppShellProps = {\n router?: Router<any, any>;\n children?: React.ReactNode;\n} & AppShellConfig;\n\n// AppShell 主组件\nexport const AppShell: React.FC<AppShellProps> = ({\n router,\n children,\n title = 'DiShUI',\n initialLang,\n initialTheme,\n menuItems,\n getMenuItems,\n themes,\n enableAuth = false,\n onAuthRequired,\n protectedRoutes = [],\n publicRoutes = ['/login', '/register'],\n loginUrl = '/login',\n authFailedCallback,\n layout = 'sidebar',\n sidebarWidth = 280,\n sidebarCollapsedWidth = 64,\n navbarHeight = 64,\n searchConfig,\n headbarLeft,\n headbarMiddle,\n headbarRight,\n}) => {\n // 保存全局配置\n globalConfig = {\n title,\n initialLang,\n initialTheme,\n menuItems,\n getMenuItems,\n themes,\n enableAuth,\n onAuthRequired,\n protectedRoutes,\n publicRoutes,\n loginUrl,\n authFailedCallback,\n layout,\n sidebarWidth,\n sidebarCollapsedWidth,\n navbarHeight,\n searchConfig,\n headbarLeft,\n headbarMiddle,\n headbarRight,\n };\n\n // 语言状态管理\n const [language, setLanguage] = useState<'zh' | 'en'>(() => {\n const savedLanguage = localStorage.getItem('app-language');\n if (savedLanguage === 'zh' || savedLanguage === 'en') return savedLanguage;\n return initialLang || 'zh';\n });\n\n // 主题状态管理\n const [theme, setTheme] = useState<ThemeType>(() => {\n const savedTheme = localStorage.getItem('app-theme');\n const validThemes: ThemeType[] = ['light', 'dark', 'retro', 'cyberpunk', 'matrix', 'oceanblue', 'eyecare', 'ghibli', 'pinkgirl', 'mintgirl', 'wuxing', 'jukebox'];\n if (savedTheme && validThemes.includes(savedTheme as ThemeType)) {\n return savedTheme as ThemeType;\n }\n return initialTheme || 'light';\n });\n\n // 用户认证状态管理\n const [user, setUser] = useState<User | null>(() => {\n if (!enableAuth) return null;\n const savedUser = localStorage.getItem('app-user');\n return savedUser ? JSON.parse(savedUser) : null;\n });\n\n // 保存全局认证状态\n globalAuthState = { user, setUser };\n\n // 保存语言设置\n useEffect(() => {\n localStorage.setItem('app-language', language);\n }, [language]);\n\n // 保存主题设置\n useEffect(() => {\n localStorage.setItem('app-theme', theme);\n document.documentElement.setAttribute('data-theme', theme);\n }, [theme]);\n\n // 保存用户信息\n useEffect(() => {\n if (enableAuth) {\n if (user) {\n localStorage.setItem('app-user', JSON.stringify(user));\n } else {\n localStorage.removeItem('app-user');\n }\n }\n }, [user, enableAuth]);\n\n // 认证方法\n const login = (newUser: User) => {\n setUser(newUser);\n };\n\n const logout = () => {\n setUser(null);\n localStorage.removeItem('app-user');\n };\n\n const hasRole = (role: string): boolean => {\n return user?.roles.includes(role) || false;\n };\n\n const hasAnyRole = (roles: string[]): boolean => {\n return roles.some(role => user?.roles.includes(role)) || false;\n };\n\n // 路由守卫 - 检查认证状态\n useEffect(() => {\n if (!enableAuth || !router) return;\n\n const unsubscribe = router.subscribe('onBeforeLoad', ({ pathChanged, toLocation }) => {\n if (!pathChanged) return;\n\n const isPublicRoute = publicRoutes.some(route =>\n toLocation.pathname.startsWith(route)\n );\n\n const isProtectedRoute = protectedRoutes.length === 0 ||\n protectedRoutes.some(route => toLocation.pathname.startsWith(route));\n\n if (isProtectedRoute && !isPublicRoute && !user) {\n // 允许调用方先自行处理认证需求。返回 true 表示已处理,直接放行。\n if (onAuthRequired) {\n const handled = onAuthRequired();\n if (handled) return;\n }\n\n // 未被自定义逻辑处理时,执行认证失败回调或默认重定向。\n if (authFailedCallback) {\n authFailedCallback(toLocation.pathname, loginUrl);\n } else {\n window.location.href = loginUrl;\n }\n }\n });\n\n return () => {\n if (unsubscribe) unsubscribe();\n };\n }, [enableAuth, user, router, protectedRoutes, publicRoutes, onAuthRequired, loginUrl, authFailedCallback]);\n\n const authContext: AuthContextType = {\n user,\n isAuthenticated: !!user,\n login,\n logout,\n hasRole,\n hasAnyRole,\n };\n\n const value: AppContextType = {\n title,\n language,\n theme,\n setLanguage,\n setTheme,\n auth: authContext,\n menuItems,\n getMenuItems,\n themes,\n sidebarWidth,\n sidebarCollapsedWidth,\n navbarHeight,\n };\n\n return (\n <AppContext.Provider value={value}>\n {router ? (\n children || <RouterProvider router={router} />\n ) : (\n children\n )}\n </AppContext.Provider>\n );\n};\n\n// 保持向后兼容的 AppProvider 别名\nexport const AppProvider = AppShell;\n\nexport default AppShell;\n"],"mappings":"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"}