dishui 0.0.108 → 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.
- package/dist/.release-verified.json +3 -2
- package/dist/components/Accordion/index.js.map +1 -1
- package/dist/components/Avatar/index.js.map +1 -1
- package/dist/components/Badge/index.js.map +1 -1
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/ButtonMenu/index.js.map +1 -1
- package/dist/components/Card/Metric2.js.map +1 -1
- package/dist/components/Card/Ticket2.js.map +1 -1
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Chart/Chart.js.map +1 -1
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/ChoicePicker/index.js.map +1 -1
- package/dist/components/Column/index.js.map +1 -1
- package/dist/components/ConfirmDialog/index.js.map +1 -1
- package/dist/components/DateTimeInput/index.js.map +1 -1
- package/dist/components/Demo/index.js.map +1 -1
- package/dist/components/Demo/source.js.map +1 -1
- package/dist/components/Divider/index.js.map +1 -1
- package/dist/components/EmptyState/index.js.map +1 -1
- package/dist/components/Field/index.js.map +1 -1
- package/dist/components/FileUploader/DropZone.js.map +1 -1
- package/dist/components/FileUploader/FileItem.js.map +1 -1
- package/dist/components/FileUploader/FileUploader.js.map +1 -1
- package/dist/components/FileUploader/UploadQueue.js.map +1 -1
- package/dist/components/GroupButton/index.js.map +1 -1
- package/dist/components/GroupedTable/index.js.map +1 -1
- package/dist/components/Icon/index.js.map +1 -1
- package/dist/components/Image/index.js.map +1 -1
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/Label/index.js.map +1 -1
- package/dist/components/Layout/index.js.map +1 -1
- package/dist/components/LayoutSuite/DashboardSuite.js.map +1 -1
- package/dist/components/LayoutSuite/index.js.map +1 -1
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Markdown/codeThemes.js.map +1 -1
- package/dist/components/Markdown/markdownComponents.js.map +1 -1
- package/dist/components/Markdown/parseCodeBlockMeta.js.map +1 -1
- package/dist/components/Markdown/useMarkdownSource.js.map +1 -1
- package/dist/components/Markdown/useMarkmapRenderer.js.map +1 -1
- package/dist/components/Markdown/useMermaidRenderer.js.map +1 -1
- package/dist/components/Modal/focusScope.js.map +1 -1
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/MultipleChoice/index.js.map +1 -1
- package/dist/components/NavigationList/index.js.map +1 -1
- package/dist/components/Page/Float2.js.map +1 -1
- package/dist/components/Page/index.js.map +1 -1
- package/dist/components/Page/resize2.js.map +1 -1
- package/dist/components/PageHeader/index.js.map +1 -1
- package/dist/components/PagePanel/index.js.map +1 -1
- package/dist/components/ProtectedRoute/index.js.map +1 -1
- package/dist/components/Resizable/ResizeGrip.js.map +1 -1
- package/dist/components/Resizable/index.js.map +1 -1
- package/dist/components/Resizable/useResize.js.map +1 -1
- package/dist/components/Row/index.js.map +1 -1
- package/dist/components/Section/index.js.map +1 -1
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/Skeleton/index.js.map +1 -1
- package/dist/components/Slider/index.js.map +1 -1
- package/dist/components/Switch/index.js.map +1 -1
- package/dist/components/Tab/index.js.map +1 -1
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tabs/tabNavigation.js.map +1 -1
- package/dist/components/Text/index.js.map +1 -1
- package/dist/components/Textarea/index.js.map +1 -1
- package/dist/components/Tooltip/index.js.map +1 -1
- package/dist/components/Tree/Tree.js.map +1 -1
- package/dist/components/ai/AgentChat/index.js.map +1 -1
- package/dist/components/ai/AgentRunCard/index.js.map +1 -1
- package/dist/components/ai/AgentScreen/index.js.map +1 -1
- package/dist/components/ai/ApprovalCard/index.js.map +1 -1
- package/dist/components/ai/CodeView/index.js.map +1 -1
- package/dist/components/ai/CommandSearch/index.js.map +1 -1
- package/dist/components/ai/ContextCards/index.js.map +1 -1
- package/dist/components/ai/DiffTable/index.js.map +1 -1
- package/dist/components/ai/FilterTable/index.js.map +1 -1
- package/dist/components/ai/FineTuneCard/index.js.map +1 -1
- package/dist/components/ai/InsightCards/index.js.map +1 -1
- package/dist/components/ai/IssueCard/index.js.map +1 -1
- package/dist/components/ai/LoadingState/index.js.map +1 -1
- package/dist/components/ai/PromptBar/index.js.map +1 -1
- package/dist/components/ai/RecommendationCard/index.js.map +1 -1
- package/dist/components/ai/RecordsTable/index.js.map +1 -1
- package/dist/components/ai/SelectionActions/index.js.map +1 -1
- package/dist/components/ai/StateFlow/index.js.map +1 -1
- package/dist/components/ai/StreamingText/index.js.map +1 -1
- package/dist/components/ai/TaskRows/index.js.map +1 -1
- package/dist/components/ai/Thinking/index.js.map +1 -1
- package/dist/components/ai/ToolChips/index.js.map +1 -1
- package/dist/components/ai/shared.js.map +1 -1
- package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
- package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
- package/dist/components/pro/ArticleControl/buildHeadingTree.js.map +1 -1
- package/dist/components/pro/ArticleControl/useArticleToc.js.map +1 -1
- package/dist/components/pro/Calendar/Calendar.js +165 -160
- package/dist/components/pro/Calendar/Calendar.js.map +1 -1
- package/dist/components/pro/Calendar/hooks/useCalendarDrag.js.map +1 -1
- package/dist/components/pro/Calendar/hooks/useCalendarState.js +31 -31
- package/dist/components/pro/Calendar/hooks/useCalendarState.js.map +1 -1
- package/dist/components/pro/Calendar/utils.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/markdownExtensions.js.map +1 -1
- package/dist/components/pro/CodeEditor/extensions/contextMenu.js.map +1 -1
- package/dist/components/pro/CodeEditor/extensions/index.js.map +1 -1
- package/dist/components/pro/CodeEditor/langs/index.js.map +1 -1
- package/dist/components/pro/CodeEditor/langs/javascript.js.map +1 -1
- package/dist/components/pro/CodeEditor/langs/python.js.map +1 -1
- package/dist/components/pro/CodeEditor/langs/snippets.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/HistoryPanel.js +65 -59
- package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/themes.js.map +1 -1
- package/dist/components/pro/CodeEditor/utils.js.map +1 -1
- package/dist/components/pro/DataTable/DataTable.js.map +1 -1
- package/dist/components/pro/DataTable/Filters.js.map +1 -1
- package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
- package/dist/components/pro/DataTable/PivotView.js.map +1 -1
- package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
- package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
- package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
- package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
- package/dist/components/pro/DataTable/extension.js.map +1 -1
- package/dist/components/pro/DataTable/pivotEngine.js.map +1 -1
- package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
- package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
- package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
- package/dist/components/pro/DataTable/treeDataUtils.js.map +1 -1
- package/dist/components/pro/DataTable/useColumnDragReorder.js.map +1 -1
- package/dist/components/pro/DataTable/useDataTableModel.js +119 -104
- package/dist/components/pro/DataTable/useDataTableModel.js.map +1 -1
- package/dist/components/pro/DataTable/utils.js.map +1 -1
- package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
- package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
- package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
- package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
- package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
- package/dist/components/pro/Flow/archify/build.js.map +1 -1
- package/dist/components/pro/Flow/archify/convert.js.map +1 -1
- package/dist/components/pro/Flow/archify/palette.js.map +1 -1
- package/dist/components/pro/Flow/archify/presets.js.map +1 -1
- package/dist/components/pro/Flow/archify/spec.js.map +1 -1
- package/dist/components/pro/Flow/canvas/AlignmentGuides.js.map +1 -1
- package/dist/components/pro/Flow/canvas/GridRenderer.js.map +1 -1
- package/dist/components/pro/Flow/canvas/MiniMapRenderer.js.map +1 -1
- package/dist/components/pro/Flow/canvas/PixiApp.js.map +1 -1
- package/dist/components/pro/Flow/canvas/SelectionOverlay.js.map +1 -1
- package/dist/components/pro/Flow/canvas/ViewportContainer.js.map +1 -1
- package/dist/components/pro/Flow/constants.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowAIContext.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowContext.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
- package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/edges/edgeMarkers.js.map +1 -1
- package/dist/components/pro/Flow/edges/edgePaths.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useAlignmentGuides.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useCompactMode.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useDraggablePanel.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useFlowImportExport.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useKeyboardShortcuts.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/usePdfExport.js.map +1 -1
- package/dist/components/pro/Flow/hooks/usePixiApp.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useResizablePanel.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useSelection.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useUndoRedo.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useViewport.js.map +1 -1
- package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
- package/dist/components/pro/Flow/lines/GeometricLineTool.js.map +1 -1
- package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
- package/dist/components/pro/Flow/lines/lineSmoothing.js.map +1 -1
- package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/NodeHandles.js.map +1 -1
- package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/NodeText.js.map +1 -1
- package/dist/components/pro/Flow/nodes/aiClient.js.map +1 -1
- package/dist/components/pro/Flow/nodes/animAnchors.js.map +1 -1
- package/dist/components/pro/Flow/nodes/chartGeometryBudget.js.map +1 -1
- package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
- package/dist/components/pro/Flow/nodes/demandRender.js.map +1 -1
- package/dist/components/pro/Flow/nodes/nodeUtils.js.map +1 -1
- package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
- package/dist/components/pro/Flow/nodes/svgIconTexture.js.map +1 -1
- package/dist/components/pro/Flow/nodes/svgIcons.js.map +1 -1
- package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
- package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
- package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
- package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
- package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
- package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
- package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
- package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
- package/dist/components/pro/Flow/types.js.map +1 -1
- package/dist/components/pro/Flow/utils/dashedLine.js.map +1 -1
- package/dist/components/pro/Flow/utils/gradient.js.map +1 -1
- package/dist/components/pro/Flow/utils/pdfExport.js.map +1 -1
- package/dist/components/pro/Flow/utils/themeColor.js.map +1 -1
- package/dist/components/pro/Gantt/Gantt.js.map +1 -1
- package/dist/components/pro/Gantt/hooks/useGanttDrag.js.map +1 -1
- package/dist/components/pro/Gantt/hooks/useGanttState.js +79 -71
- package/dist/components/pro/Gantt/hooks/useGanttState.js.map +1 -1
- package/dist/components/pro/Gantt/utils.js.map +1 -1
- package/dist/components/pro/Kanban/Kanban.js.map +1 -1
- package/dist/components/pro/Kanban/Swimlanes.js.map +1 -1
- package/dist/components/pro/Kanban/useKanbanDrag.js.map +1 -1
- package/dist/components/pro/Kanban/utils.js.map +1 -1
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
- package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CommentMark.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/FontSize.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/ResizableImage.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/legacyMermaid.js.map +1 -1
- package/dist/components/pro/RichTextEditor/types.js.map +1 -1
- package/dist/components/pro/Sprite/Molly/animations.d.ts +6 -0
- package/dist/components/pro/Sprite/Molly/animations.js +52 -0
- package/dist/components/pro/Sprite/Molly/animations.js.map +1 -0
- package/dist/components/pro/Sprite/Molly/events.d.ts +2 -0
- package/dist/components/pro/Sprite/Molly/events.js +46 -0
- package/dist/components/pro/Sprite/Molly/events.js.map +1 -0
- package/dist/components/pro/Sprite/Molly/index.d.ts +1 -0
- package/dist/components/pro/Sprite/Molly/index.js +12 -0
- package/dist/components/pro/Sprite/Molly/index.js.map +1 -0
- package/dist/components/pro/Sprite/Molly/legFlexion.d.ts +3 -0
- package/dist/components/pro/Sprite/Molly/legFlexion.js +48 -0
- package/dist/components/pro/Sprite/Molly/legFlexion.js.map +1 -0
- package/dist/components/pro/Sprite/Molly/locomotion.d.ts +4 -0
- package/dist/components/pro/Sprite/Molly/locomotion.js +51 -0
- package/dist/components/pro/Sprite/Molly/locomotion.js.map +1 -0
- package/dist/components/pro/Sprite/Molly/model.d.ts +23 -0
- package/dist/components/pro/Sprite/Molly/model.js +614 -0
- package/dist/components/pro/Sprite/Molly/model.js.map +1 -0
- package/dist/components/pro/Sprite/Molly/rig.d.ts +25 -0
- package/dist/components/pro/Sprite/Molly/rig.js +102 -0
- package/dist/components/pro/Sprite/Molly/rig.js.map +1 -0
- package/dist/components/pro/Sprite/Ruby/animations.d.ts +6 -0
- package/dist/components/pro/Sprite/Ruby/animations.js +58 -0
- package/dist/components/pro/Sprite/Ruby/animations.js.map +1 -0
- package/dist/components/pro/Sprite/Ruby/events.d.ts +2 -0
- package/dist/components/pro/Sprite/Ruby/events.js +46 -0
- package/dist/components/pro/Sprite/Ruby/events.js.map +1 -0
- package/dist/components/pro/Sprite/Ruby/index.d.ts +1 -0
- package/dist/components/pro/Sprite/Ruby/index.js +12 -0
- package/dist/components/pro/Sprite/Ruby/index.js.map +1 -0
- package/dist/components/pro/Sprite/Ruby/locomotion.d.ts +4 -0
- package/dist/components/pro/Sprite/Ruby/locomotion.js +41 -0
- package/dist/components/pro/Sprite/Ruby/locomotion.js.map +1 -0
- package/dist/components/pro/Sprite/Ruby/model.d.ts +23 -0
- package/dist/components/pro/Sprite/Ruby/model.js +605 -0
- package/dist/components/pro/Sprite/Ruby/model.js.map +1 -0
- package/dist/components/pro/Sprite/Ruby/rig.d.ts +26 -0
- package/dist/components/pro/Sprite/Ruby/rig.js +112 -0
- package/dist/components/pro/Sprite/Ruby/rig.js.map +1 -0
- package/dist/components/pro/Sprite/Sprite.d.ts +23 -0
- package/dist/components/pro/Sprite/Sprite2.js +224 -0
- package/dist/components/pro/Sprite/Sprite2.js.map +1 -0
- package/dist/components/pro/Sprite/actions.d.ts +3 -0
- package/dist/components/pro/Sprite/actions.js +16 -0
- package/dist/components/pro/Sprite/actions.js.map +1 -0
- package/dist/components/pro/Sprite/createSpriteScene.d.ts +4 -0
- package/dist/components/pro/Sprite/createSpriteScene.js +14 -0
- package/dist/components/pro/Sprite/createSpriteScene.js.map +1 -0
- package/dist/components/pro/Sprite/index.d.ts +4 -0
- package/dist/components/pro/Sprite/shared/animation.d.ts +33 -0
- package/dist/components/pro/Sprite/shared/animation.js +39 -0
- package/dist/components/pro/Sprite/shared/animation.js.map +1 -0
- package/dist/components/pro/Sprite/shared/createSpriteStage.d.ts +14 -0
- package/dist/components/pro/Sprite/shared/createSpriteStage.js +127 -0
- package/dist/components/pro/Sprite/shared/createSpriteStage.js.map +1 -0
- package/dist/components/pro/Sprite/shared/events.d.ts +5 -0
- package/dist/components/pro/Sprite/shared/events.js +21 -0
- package/dist/components/pro/Sprite/shared/events.js.map +1 -0
- package/dist/components/pro/Sprite/shared/face.d.ts +15 -0
- package/dist/components/pro/Sprite/shared/face.js +33 -0
- package/dist/components/pro/Sprite/shared/face.js.map +1 -0
- package/dist/components/pro/Sprite/shared/faceSurface.d.ts +6 -0
- package/dist/components/pro/Sprite/shared/faceSurface.js +66 -0
- package/dist/components/pro/Sprite/shared/faceSurface.js.map +1 -0
- package/dist/components/pro/Sprite/shared/gait.d.ts +5 -0
- package/dist/components/pro/Sprite/shared/gait.js +19 -0
- package/dist/components/pro/Sprite/shared/gait.js.map +1 -0
- package/dist/components/pro/Sprite/shared/geometry.d.ts +8 -0
- package/dist/components/pro/Sprite/shared/geometry.js +59 -0
- package/dist/components/pro/Sprite/shared/geometry.js.map +1 -0
- package/dist/components/pro/Sprite/shared/magicEffect.d.ts +27 -0
- package/dist/components/pro/Sprite/shared/magicEffect.js +61 -0
- package/dist/components/pro/Sprite/shared/magicEffect.js.map +1 -0
- package/dist/components/pro/Sprite/shared/playback.d.ts +8 -0
- package/dist/components/pro/Sprite/shared/playback.js +74 -0
- package/dist/components/pro/Sprite/shared/playback.js.map +1 -0
- package/dist/components/pro/Sprite/shared/rig.d.ts +6 -0
- package/dist/components/pro/Sprite/shared/rig.js +48 -0
- package/dist/components/pro/Sprite/shared/rig.js.map +1 -0
- package/dist/components/pro/Sprite/shared/scene.d.ts +9 -0
- package/dist/components/pro/Sprite/shared/scene.js +21 -0
- package/dist/components/pro/Sprite/shared/scene.js.map +1 -0
- package/dist/components/pro/Sprite/shared/sculptor.d.ts +14 -0
- package/dist/components/pro/Sprite/shared/sculptor.js +78 -0
- package/dist/components/pro/Sprite/shared/sculptor.js.map +1 -0
- package/dist/components/pro/Sprite/shared/speechBubble.d.ts +15 -0
- package/dist/components/pro/Sprite/shared/speechBubble.js +129 -0
- package/dist/components/pro/Sprite/shared/speechBubble.js.map +1 -0
- package/dist/components/pro/Sprite/types.d.ts +40 -0
- package/dist/contexts/AppContext.js.map +1 -1
- package/dist/contexts/authentication.js.map +1 -1
- package/dist/data-table.js +3 -3
- package/dist/data-table.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/hooks/useClickOutside.js.map +1 -1
- package/dist/hooks/useContainerElement.js.map +1 -1
- package/dist/hooks/useControllableState.js.map +1 -1
- package/dist/hooks/useCopyToClipboard.js.map +1 -1
- package/dist/hooks/useDebounce.js.map +1 -1
- package/dist/hooks/useDraggable.js.map +1 -1
- package/dist/hooks/useTableColumns.js.map +1 -1
- package/dist/hooks/useTableData.js.map +1 -1
- package/dist/index-nostyled.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +116 -115
- package/dist/layouts/MainLayout.js.map +1 -1
- package/dist/layouts/Navbar.js.map +1 -1
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/layouts/headbar/Headbar.js.map +1 -1
- package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
- package/dist/sprite.js +2 -0
- package/dist/styles/themeStyles.js.map +1 -1
- package/dist/utils/cn.js.map +1 -1
- package/dist/utils/flexLayout.js.map +1 -1
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js.map +1 -1
- package/dist/utils/rehype-code-meta.js.map +1 -1
- package/dist/utils/remark-code-meta.js.map +1 -1
- package/dist/utils/routerBuilder.js.map +1 -1
- package/dist/utils/safeStorage.js.map +1 -1
- package/dist/utils/selection.js +29 -20
- package/dist/utils/selection.js.map +1 -1
- package/dist/utils/themes.js.map +1 -1
- package/package.json +15 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Navbar.js","names":[],"sources":["../../src/layouts/Navbar.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { ThemeType, useAppContext } from '../contexts/AppContext';\nimport { getTranslations } from '../utils/i18n';\nimport { ThemeConfig, getThemes as defaultGetThemes } from '../utils/themes';\n\nexport type SearchResult = {\n title: string;\n path: string;\n description: string;\n};\n\nexport type SearchConfig = {\n enabled: boolean;\n searchFunction?: (term: string, language: 'zh' | 'en') => SearchResult[];\n placeholder?: { zh: string; en: string };\n shortcut?: string;\n};\n\ntype NavbarProps = {\n onToggleSidebar: () => void;\n searchConfig?: SearchConfig;\n themes?: ThemeConfig[];\n height?: number; // Navbar 高度(像素)\n};\n\nconst Navbar: React.FC<NavbarProps> = ({ onToggleSidebar, searchConfig, themes: propThemes, height = 64 }) => {\n const { title = 'DiShUI', language, setLanguage, theme, setTheme } = useAppContext();\n const t = getTranslations(language);\n\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [searchResults, setSearchResults] = useState<SearchResult[]>([]);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDialogElement>(null);\n\n // 获取主题配置:优先使用 propThemes,否则使用默认的\n const themes = propThemes || defaultGetThemes();\n\n // 获取当前主题\n const currentTheme = themes.find(t => t.id === theme) || themes[0];\n\n // 搜索是否启用\n const isSearchEnabled = searchConfig?.enabled ?? true;\n\n const toggleSearch = () => {\n setIsSearchOpen(!isSearchOpen);\n if (!isSearchOpen && modalRef.current) {\n modalRef.current.showModal();\n setTimeout(() => {\n searchInputRef.current?.focus();\n }, 100);\n } else if (modalRef.current) {\n modalRef.current.close();\n }\n };\n\n const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearchTerm(value);\n // 使用外部提供的搜索函数\n const searchFn = searchConfig?.searchFunction;\n if (searchFn) {\n setSearchResults(searchFn(value, language));\n }\n };\n\n useEffect(() => {\n if (!isSearchEnabled) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault();\n toggleSearch();\n }\n\n if (e.key === 'Escape' && isSearchOpen) {\n toggleSearch();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isSearchOpen, isSearchEnabled]);\n\n // 当语言改变时,更新搜索结果\n useEffect(() => {\n if (searchTerm && isSearchEnabled && searchConfig?.searchFunction) {\n setSearchResults(searchConfig.searchFunction(searchTerm, language));\n }\n }, [language, searchConfig, isSearchEnabled, searchTerm]);\n\n return (\n <div className=\"navbar bg-base-100 shadow-md\" style={{ height: `${height}px`, minHeight: `${height}px`, maxHeight: `${height}px` }}>\n <div className=\"navbar-start\">\n <div className=\"flex-none lg:hidden\">\n <button className=\"btn btn-square btn-ghost\" onClick={onToggleSidebar}>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" className=\"inline-block w-5 h-5 stroke-current\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M4 6h16M4 12h16M4 18h16\"></path>\n </svg>\n </button>\n </div>\n <a href=\"/\" className=\"btn btn-ghost normal-case text-xl\">{title}</a>\n </div>\n\n {isSearchEnabled && (\n <div className=\"navbar-center hidden lg:flex\">\n <button\n className=\"btn btn-ghost gap-2\"\n onClick={toggleSearch}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n {searchConfig?.placeholder?.[language] || t.navbar.search} ({searchConfig?.shortcut || t.navbar.searchShortcut})\n </button>\n </div>\n )}\n\n <div className=\"navbar-end\">\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost gap-1\">\n {language === 'zh' ? '中文' : 'English'}\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=\"M19 9l-7 7-7-7\" />\n </svg>\n </label>\n <ul tabIndex={0} className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-40 mt-4\">\n <li>\n <a\n className={language === 'zh' ? 'active' : ''}\n onClick={() => setLanguage('zh')}\n >\n 中文\n </a>\n </li>\n <li>\n <a\n className={language === 'en' ? 'active' : ''}\n onClick={() => setLanguage('en')}\n >\n English\n </a>\n </li>\n </ul>\n </div>\n\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost\">\n {currentTheme.icon}\n </label>\n <ul tabIndex={0} className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-52 mt-4\">\n {themes.map((themeOption) => (\n <li key={themeOption.id}>\n <a\n className={theme === themeOption.id ? 'active' : ''}\n onClick={() => setTheme(themeOption.id)}\n >\n <span className=\"mr-2\">{themeOption.icon}</span>\n {language === 'zh' ? themeOption.name.zh : themeOption.name.en}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n\n {/* 搜索对话框 */}\n {isSearchEnabled && (\n <dialog ref={modalRef} className=\"modal modal-bottom sm:modal-middle\" onClick={(e) => {\n if (e.target === modalRef.current) toggleSearch();\n }}>\n <div className=\"modal-box bg-base-100\">\n <div className=\"relative mb-4\">\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={searchConfig?.placeholder?.[language] || t.navbar.searchPlaceholder}\n className=\"input input-bordered w-full pr-10\"\n value={searchTerm}\n onChange={handleSearch}\n />\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5 absolute top-3 right-3 opacity-50\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n </div>\n\n <div className=\"search-results max-h-80 overflow-y-auto\">\n {searchResults.length > 0 ? (\n <ul className=\"menu bg-base-100 rounded-box\">\n {searchResults.map((result, index) => (\n <li key={index}>\n <a\n href={result.path}\n className=\"flex flex-col items-start\"\n onClick={() => toggleSearch()}\n >\n <div className=\"font-medium\">{result.title}</div>\n <div className=\"text-sm opacity-70\">{result.description}</div>\n </a>\n </li>\n ))}\n </ul>\n ) : searchTerm ? (\n <div className=\"py-4 text-center text-base-content/70\">\n {t.navbar.noResults}\n </div>\n ) : null}\n </div>\n\n <div className=\"modal-action\">\n <form method=\"dialog\">\n <button className=\"btn\" onClick={toggleSearch}>ESC</button>\n </form>\n </div>\n </div>\n </dialog>\n )}\n </div>\n );\n};\n\nexport default Navbar; "],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Navbar.js","names":["defaultGetThemes","Navbar","propThemes","useAppContext","t","getTranslations","language","isSearchOpen","setIsSearchOpen","useState","searchTerm","setSearchTerm","searchResults","setSearchResults","searchInputRef","useRef","modalRef","themes","getThemes","currentTheme","theme","isSearchEnabled","searchConfig","toggleSearch","useEffect","handleKeyDown","height","onToggleSidebar","title","setLanguage","themeOption","setTheme","value","searchFn","result","index"],"sources":["../../src/layouts/Navbar.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { ThemeType, useAppContext } from '../contexts/AppContext';\nimport { getTranslations } from '../utils/i18n';\nimport { ThemeConfig, getThemes as defaultGetThemes } from '../utils/themes';\n\nexport type SearchResult = {\n title: string;\n path: string;\n description: string;\n};\n\nexport type SearchConfig = {\n enabled: boolean;\n searchFunction?: (term: string, language: 'zh' | 'en') => SearchResult[];\n placeholder?: { zh: string; en: string };\n shortcut?: string;\n};\n\ntype NavbarProps = {\n onToggleSidebar: () => void;\n searchConfig?: SearchConfig;\n themes?: ThemeConfig[];\n height?: number; // Navbar 高度(像素)\n};\n\nconst Navbar: React.FC<NavbarProps> = ({ onToggleSidebar, searchConfig, themes: propThemes, height = 64 }) => {\n const { title = 'DiShUI', language, setLanguage, theme, setTheme } = useAppContext();\n const t = getTranslations(language);\n\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [searchResults, setSearchResults] = useState<SearchResult[]>([]);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDialogElement>(null);\n\n // 获取主题配置:优先使用 propThemes,否则使用默认的\n const themes = propThemes || defaultGetThemes();\n\n // 获取当前主题\n const currentTheme = themes.find(t => t.id === theme) || themes[0];\n\n // 搜索是否启用\n const isSearchEnabled = searchConfig?.enabled ?? true;\n\n const toggleSearch = () => {\n setIsSearchOpen(!isSearchOpen);\n if (!isSearchOpen && modalRef.current) {\n modalRef.current.showModal();\n setTimeout(() => {\n searchInputRef.current?.focus();\n }, 100);\n } else if (modalRef.current) {\n modalRef.current.close();\n }\n };\n\n const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearchTerm(value);\n // 使用外部提供的搜索函数\n const searchFn = searchConfig?.searchFunction;\n if (searchFn) {\n setSearchResults(searchFn(value, language));\n }\n };\n\n useEffect(() => {\n if (!isSearchEnabled) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault();\n toggleSearch();\n }\n\n if (e.key === 'Escape' && isSearchOpen) {\n toggleSearch();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isSearchOpen, isSearchEnabled]);\n\n // 当语言改变时,更新搜索结果\n useEffect(() => {\n if (searchTerm && isSearchEnabled && searchConfig?.searchFunction) {\n setSearchResults(searchConfig.searchFunction(searchTerm, language));\n }\n }, [language, searchConfig, isSearchEnabled, searchTerm]);\n\n return (\n <div className=\"navbar bg-base-100 shadow-md\" style={{ height: `${height}px`, minHeight: `${height}px`, maxHeight: `${height}px` }}>\n <div className=\"navbar-start\">\n <div className=\"flex-none lg:hidden\">\n <button className=\"btn btn-square btn-ghost\" onClick={onToggleSidebar}>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" className=\"inline-block w-5 h-5 stroke-current\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M4 6h16M4 12h16M4 18h16\"></path>\n </svg>\n </button>\n </div>\n <a href=\"/\" className=\"btn btn-ghost normal-case text-xl\">{title}</a>\n </div>\n\n {isSearchEnabled && (\n <div className=\"navbar-center hidden lg:flex\">\n <button\n className=\"btn btn-ghost gap-2\"\n onClick={toggleSearch}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n {searchConfig?.placeholder?.[language] || t.navbar.search} ({searchConfig?.shortcut || t.navbar.searchShortcut})\n </button>\n </div>\n )}\n\n <div className=\"navbar-end\">\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost gap-1\">\n {language === 'zh' ? '中文' : 'English'}\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=\"M19 9l-7 7-7-7\" />\n </svg>\n </label>\n <ul tabIndex={0} className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-40 mt-4\">\n <li>\n <a\n className={language === 'zh' ? 'active' : ''}\n onClick={() => setLanguage('zh')}\n >\n 中文\n </a>\n </li>\n <li>\n <a\n className={language === 'en' ? 'active' : ''}\n onClick={() => setLanguage('en')}\n >\n English\n </a>\n </li>\n </ul>\n </div>\n\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost\">\n {currentTheme.icon}\n </label>\n <ul tabIndex={0} className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-52 mt-4\">\n {themes.map((themeOption) => (\n <li key={themeOption.id}>\n <a\n className={theme === themeOption.id ? 'active' : ''}\n onClick={() => setTheme(themeOption.id)}\n >\n <span className=\"mr-2\">{themeOption.icon}</span>\n {language === 'zh' ? themeOption.name.zh : themeOption.name.en}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n\n {/* 搜索对话框 */}\n {isSearchEnabled && (\n <dialog ref={modalRef} className=\"modal modal-bottom sm:modal-middle\" onClick={(e) => {\n if (e.target === modalRef.current) toggleSearch();\n }}>\n <div className=\"modal-box bg-base-100\">\n <div className=\"relative mb-4\">\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={searchConfig?.placeholder?.[language] || t.navbar.searchPlaceholder}\n className=\"input input-bordered w-full pr-10\"\n value={searchTerm}\n onChange={handleSearch}\n />\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5 absolute top-3 right-3 opacity-50\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n </div>\n\n <div className=\"search-results max-h-80 overflow-y-auto\">\n {searchResults.length > 0 ? (\n <ul className=\"menu bg-base-100 rounded-box\">\n {searchResults.map((result, index) => (\n <li key={index}>\n <a\n href={result.path}\n className=\"flex flex-col items-start\"\n onClick={() => toggleSearch()}\n >\n <div className=\"font-medium\">{result.title}</div>\n <div className=\"text-sm opacity-70\">{result.description}</div>\n </a>\n </li>\n ))}\n </ul>\n ) : searchTerm ? (\n <div className=\"py-4 text-center text-base-content/70\">\n {t.navbar.noResults}\n </div>\n ) : null}\n </div>\n\n <div className=\"modal-action\">\n <form method=\"dialog\">\n <button className=\"btn\" onClick={toggleSearch}>ESC</button>\n </form>\n </div>\n </div>\n </dialog>\n )}\n </div>\n );\n};\n\nexport default Navbar; "],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.js","names":[],"sources":["../../src/layouts/Sidebar.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Link, useNavigate, useRouterState } from '@tanstack/react-router';\nimport { MenuItem } from '../types/menu';\nimport { getMenuItems as defaultGetMenuItems } from '../utils/menu';\nimport { Tree, TreeNode } from '../components/Tree';\nimport { generateSidebarActiveStyles } from '../styles/themeStyles';\nimport { DesktopSidebarToggleButton } from '../components/SidebarToggleButton';\nimport Text, { type TextProps } from '../components/Text';\n\nexport type SidebarLevelText = Pick<TextProps, 'size' | 'weight' | 'color'>;\n\nexport type SidebarHeader = {\n name: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nexport type SidebarAction = {\n label: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nconst DefaultMenuIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"3\" />\n <path d=\"M8 9h8M8 13h8M8 17h5\" />\n </svg>\n);\n\nconst DefaultWorkspaceIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\" />\n <path d=\"M9 3v18M9 10h12\" />\n </svg>\n);\n\nconst DefaultActionIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\">\n <path d=\"M12 5v14M5 12h14\" />\n </svg>\n);\n\ntype RailTooltip = { target: HTMLElement; text: string; top: number; left: number; maxWidth: number; alignRight: boolean };\n\nconst getRailTooltip = (target: HTMLElement, sidebarElement: HTMLElement | null, side: 'left' | 'right', text: string): RailTooltip => {\n const rect = target.getBoundingClientRect();\n const sidebar = sidebarElement?.getBoundingClientRect() ?? rect;\n const spaceLeft = sidebar.left - 16;\n const spaceRight = window.innerWidth - sidebar.right - 16;\n const alignRight = side === 'right' ? spaceLeft >= 200 || spaceLeft > spaceRight : spaceRight < 200 && spaceLeft > spaceRight;\n return {\n target,\n text,\n top: Math.max(8, Math.min(rect.top, window.innerHeight - 48)),\n left: alignRight ? sidebar.left - 8 : sidebar.right + 8,\n maxWidth: Math.max(0, Math.min(320, alignRight ? spaceLeft : spaceRight)),\n alignRight,\n };\n};\n\nconst DEFAULT_LEVEL_TEXT = [\n { size: 'base', weight: 'semibold' },\n { size: 'sm', weight: 'medium' },\n { size: 'sm', weight: 'normal' },\n] as const satisfies readonly SidebarLevelText[];\n\n// 组件属性\nexport type SidebarProps = {\n isCollapsed: boolean;\n /** 侧栏所在侧,控制内侧 pill 的位置与调宽方向。 */\n side?: 'left' | 'right';\n language: 'zh' | 'en';\n items?: MenuItem[];\n /**\n * Opt-in typography for levels 1–3; deeper nodes reuse level 3.\n * Omitted: preserve legacy Sidebar/LayoutSuite typography. When supplied,\n * missing values default to base/sm/sm and semibold/medium/normal.\n * Levels 3+ default to theme-adaptive neutral gray, even without levelText.\n * Explicit colors retain Text semantics (secondary may be a theme accent).\n * Selected labels always inherit the active row color.\n */\n levelText?: readonly [SidebarLevelText?, SidebarLevelText?, SidebarLevelText?];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n onWidthChange?: (width: number) => void;\n initialWidth?: number;\n collapsedWidth?: number;\n /**\n * 折叠 / 展开切换回调。传入后,侧边栏会在其边缘渲染统一的悬浮 pill 控制条\n * (点击折叠、拖拽调节宽度),无需再在外层单独渲染 SidebarToggleButtons。\n */\n onToggle?: () => void;\n /** 拖拽调节宽度的最小值(px) */\n minWidth?: number;\n /** 拖拽调节宽度的最大值(px) */\n maxWidth?: number;\n /** Optional AI-style workspace header shown above the tree. */\n workspace?: SidebarHeader;\n /** Optional primary sidebar action, such as “New chat”. */\n primaryAction?: SidebarAction;\n /** Optional footer rendered below the scrollable multi-level menu. */\n footer?: React.ReactNode;\n};\n\nconst Sidebar: React.FC<SidebarProps> = ({\n isCollapsed,\n side = 'left',\n language,\n items: propItems,\n levelText,\n getMenuItems,\n onWidthChange,\n initialWidth = 280,\n collapsedWidth = 64,\n onToggle,\n minWidth = 160,\n maxWidth = 400,\n workspace,\n primaryAction,\n footer,\n}) => {\n const [items, setItems] = useState<MenuItem[]>([]);\n const [activeNodeId, setActiveNodeId] = useState<string | number>('');\n const [sidebarWidth, setSidebarWidth] = useState(() => Math.max(minWidth, Math.min(initialWidth, maxWidth)));\n const sidebarRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const [railTooltip, setRailTooltip] = useState<RailTooltip | null>(null);\n const routerState = useRouterState({ select: (s: { location: { pathname: string } }) => s.location });\n const navigate = useNavigate();\n\n // 当 initialWidth 改变时,更新侧边栏宽度\n useEffect(() => {\n setSidebarWidth(Math.max(minWidth, Math.min(initialWidth, maxWidth)));\n }, [initialWidth, minWidth, maxWidth]);\n\n // 统一的宽度变更处理:同步内部状态并通知父组件。\n // pill 拖拽与外部同步都通过此入口,避免必须回传 initialWidth 才能生效。\n const handleInternalWidthChange = (width: number) => {\n const next = Math.max(minWidth, Math.min(width, maxWidth));\n setSidebarWidth(next);\n onWidthChange?.(next);\n };\n\n // 当语言改变或传入items prop时,更新菜单项\n useEffect(() => {\n if (propItems !== undefined) {\n setItems(propItems);\n } else if (getMenuItems) {\n setItems(getMenuItems(language));\n } else {\n setItems(defaultGetMenuItems(language));\n }\n }, [language, propItems, getMenuItems]);\n\n // 活跃节点变化时,自动滚动到可见区域(菜单过长时保证当前页可见)。\n // 延迟 350ms:Tree 展开动画(max-height 0.3s)期间布局仍在变化,立即\n // scrollIntoView 会计算到动画中途的位置而滚动不到位。\n useEffect(() => {\n if (!activeNodeId) return;\n const t = setTimeout(() => {\n scrollRef.current\n ?.querySelector(isCollapsed ? '[aria-current=\"page\"]' : '.tree-node-content-active')\n ?.scrollIntoView({ block: 'nearest', behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'instant' : 'smooth' });\n }, 350);\n return () => clearTimeout(t);\n }, [activeNodeId, isCollapsed]);\n\n // 兜底:确保鼠标悬停在菜单任意位置都能滚轮滚动。\n // 部分浏览器/嵌套滚动场景下原生滚轮可能不作用于该容器,这里用非被动\n // 监听手动滚动;成功滚动后 preventDefault,避免浏览器默认行为造成双重滚动。\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n if (el.scrollHeight <= el.clientHeight) return;\n const dy = e.deltaMode === 1 ? e.deltaY * 16 : e.deltaY; // 行模式 → 像素\n if (dy === 0) return;\n const before = el.scrollTop;\n el.scrollTop = before + dy;\n if (el.scrollTop !== before) e.preventDefault();\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [isCollapsed]);\n\n const showRailTooltip = (target: HTMLElement, text: string) => {\n setRailTooltip(getRailTooltip(target, sidebarRef.current, side, text));\n };\n\n const hideTooltipOnMouseLeave = (target: HTMLElement) => {\n if (document.activeElement !== target) setRailTooltip(current => current?.target === target ? null : current);\n };\n\n const hideTooltipOnBlur = (target: HTMLElement) => {\n if (!target.matches(':hover')) setRailTooltip(current => current?.target === target ? null : current);\n };\n\n useEffect(() => {\n if (!isCollapsed) return;\n const update = () => {\n setRailTooltip(current => current?.target.isConnected\n ? getRailTooltip(current.target, sidebarRef.current, side, current.text)\n : null);\n };\n window.addEventListener('resize', update);\n return () => window.removeEventListener('resize', update);\n }, [isCollapsed, side, sidebarRef]);\n\n // 将 MenuItem 转换为 TreeNode\n const convertToTreeNodes = (menuItems: MenuItem[]): TreeNode[] => {\n return menuItems.map(item => ({\n id: item.id,\n label: item.label,\n icon: item.icon ?? <DefaultMenuIcon />,\n children: item.children ? convertToTreeNodes(item.children) : undefined,\n meta: {\n path: item.path,\n },\n }));\n };\n\n // 转换后的树形数据\n const treeData = useMemo(() => convertToTreeNodes(items), [items]);\n\n // 获取默认展开的节点ID(默认全部展开)\n const defaultExpandedIds = useMemo(() => {\n if (items.length === 0) return [];\n\n // 收集所有有子节点的项的ID,使其默认全展开\n const collectAllExpandableIds = (menuItems: MenuItem[]): string[] => {\n let result: string[] = [];\n for (const item of menuItems) {\n if (item.children?.length) {\n result.push(item.id);\n result = [...result, ...collectAllExpandableIds(item.children)];\n }\n }\n return result;\n };\n\n return collectAllExpandableIds(items);\n }, [items]);\n\n // 更新活跃节点ID\n useEffect(() => {\n const currentPath = routerState.pathname;\n const findNodeByPath = (menuItems: MenuItem[]): string | null => {\n for (const item of menuItems) {\n if (item.path === currentPath) {\n return item.id;\n }\n if (item.children) {\n const found = findNodeByPath(item.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n const nodeId = findNodeByPath(items);\n setActiveNodeId(nodeId ?? '');\n }, [items, routerState.pathname]);\n\n\n\n // 处理节点点击\n const handleNodeClick = (node: TreeNode) => {\n // 如果节点有路径,直接导航\n if (node.meta?.path) {\n setActiveNodeId(node.id);\n navigate({ to: node.meta.path });\n return;\n }\n\n // 如果没有路径但有子节点,寻找第一个有路径的后代节点\n if (node.children && node.children.length > 0) {\n const findFirstPath = (nodes: TreeNode[]): TreeNode | null => {\n for (const n of nodes) {\n if (n.meta?.path) return n;\n if (n.children && n.children.length > 0) {\n const found = findFirstPath(n.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n const firstNodeWithPath = findFirstPath(node.children);\n if (firstNodeWithPath) {\n setActiveNodeId(firstNodeWithPath.id);\n navigate({ to: firstNodeWithPath.meta!.path });\n } else {\n // 全都没有路径则激活当前节点\n setActiveNodeId(node.id);\n }\n } else {\n setActiveNodeId(node.id);\n }\n };\n\n const collectLinks = (nodes: MenuItem[], parents: string[] = []): { item: MenuItem; trail: string }[] =>\n nodes.flatMap(item => {\n const trail = [...parents, item.label];\n return [\n ...(item.path ? [{ item, trail: trail.join(' / ') }] : []),\n ...collectLinks(item.children ?? [], trail),\n ];\n });\n\n /* Keep Tree mounted so rail toggles do not reset the user's expanded branches. */\n const rail = isCollapsed ? (\n <nav ref={scrollRef} className=\"sidebar-rail\" aria-label={language === 'zh' ? '侧边导航' : 'Sidebar navigation'} onScroll={() => {\n if (railTooltip?.target.isConnected) showRailTooltip(railTooltip.target, railTooltip.text);\n }}>\n {items.map(group => {\n const links = collectLinks([group]);\n return links.length > 0 ? (\n <div key={group.id} role=\"group\" aria-label={group.label} className=\"sidebar-rail-group\">\n {links.map(({ item, trail }) => (\n <Link\n key={item.id}\n to={item.path!}\n className=\"sidebar-rail-link\"\n aria-label={trail}\n title={trail}\n aria-current={routerState.pathname === item.path ? 'page' : undefined}\n onMouseEnter={event => showRailTooltip(event.currentTarget, trail)}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onFocus={event => showRailTooltip(event.currentTarget, trail)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span aria-hidden=\"true\">{item.icon ?? <DefaultMenuIcon />}</span>\n </Link>\n ))}\n </div>\n ) : null;\n })}\n </nav>\n ) : null;\n\n return (\n <div\n ref={sidebarRef}\n className=\"dishui-sidebar sidebar-container h-full bg-base-200 overflow-visible flex flex-col transition-colors duration-200 ease-in-out relative\"\n style={isCollapsed ? { width: collapsedWidth } : { width: sidebarWidth, maxWidth, minWidth }}\n >\n {onToggle && (\n <DesktopSidebarToggleButton\n isCollapsed={isCollapsed}\n side={side}\n onToggle={onToggle}\n sidebarWidth={sidebarWidth}\n collapsedWidth={collapsedWidth}\n onWidthChange={onWidthChange ? handleInternalWidthChange : undefined}\n minWidth={minWidth}\n maxWidth={maxWidth}\n anchorRef={sidebarRef}\n />\n )}\n {(workspace || primaryAction) && (\n <div className=\"dishui-sidebar-ai-header\">\n {workspace && (\n <button\n type=\"button\"\n className=\"dishui-sidebar-ai-workspace\"\n onClick={workspace.onClick}\n aria-label={isCollapsed && typeof workspace.name === 'string' ? workspace.name : undefined}\n title={isCollapsed && typeof workspace.name === 'string' ? workspace.name : undefined}\n onMouseEnter={event => { if (isCollapsed && typeof workspace.name === 'string') showRailTooltip(event.currentTarget, workspace.name); }}\n onFocus={event => { if (isCollapsed && typeof workspace.name === 'string') showRailTooltip(event.currentTarget, workspace.name); }}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span className=\"dishui-sidebar-ai-avatar\" aria-hidden=\"true\">{workspace.icon ?? <DefaultWorkspaceIcon />}</span>\n {!isCollapsed && <span className=\"dishui-sidebar-ai-workspace-name\">{workspace.name}</span>}\n </button>\n )}\n {primaryAction && (\n <button\n type=\"button\"\n className=\"dishui-sidebar-ai-action\"\n onClick={primaryAction.onClick}\n aria-label={isCollapsed && typeof primaryAction.label === 'string' ? primaryAction.label : undefined}\n title={isCollapsed && typeof primaryAction.label === 'string' ? primaryAction.label : undefined}\n onMouseEnter={event => { if (isCollapsed && typeof primaryAction.label === 'string') showRailTooltip(event.currentTarget, primaryAction.label); }}\n onFocus={event => { if (isCollapsed && typeof primaryAction.label === 'string') showRailTooltip(event.currentTarget, primaryAction.label); }}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span aria-hidden=\"true\">{primaryAction.icon ?? <DefaultActionIcon />}</span>\n {!isCollapsed && <span>{primaryAction.label}</span>}\n </button>\n )}\n </div>\n )}\n {rail}\n {isCollapsed && railTooltip?.target.isConnected && createPortal(\n <div className=\"dishui-sidebar-rail-tooltip\" role=\"tooltip\" aria-hidden=\"true\" style={{ top: railTooltip.top, left: railTooltip.left, maxWidth: railTooltip.maxWidth, transform: railTooltip.alignRight ? 'translateX(-100%)' : undefined }}>\n {railTooltip.text}\n </div>,\n document.body,\n )}\n <div hidden={isCollapsed} style={isCollapsed ? { display: 'none' } : undefined} ref={isCollapsed ? undefined : scrollRef} className=\"sidebar-scroll min-h-0 flex-grow overflow-y-auto scrollbar-thin scrollbar-thumb-base-300 scrollbar-track-transparent\">\n <Tree\n data={treeData}\n activeNodeId={activeNodeId}\n defaultExpandedIds={defaultExpandedIds}\n showSearch={false}\n showExpandAll={false}\n showIcon={true}\n showCount={false}\n showLine={true}\n indent={1}\n togglePosition=\"right\"\n maxHeight=\"100%\"\n className={`sidebar-tree${levelText !== undefined ? ' sidebar-tree-level-text' : ''}`}\n renderLabel={(node, depth) => {\n const level = Math.min(depth, 2);\n const text = levelText?.[level];\n const defaults = DEFAULT_LEVEL_TEXT[level];\n return (\n <Text\n size={text?.size ?? defaults.size}\n weight={text?.weight ?? defaults.weight}\n color={activeNodeId === node.id ? 'inherit' : text?.color ?? 'inherit'}\n style={{\n ...(levelText === undefined ? { fontSize: 'inherit', lineHeight: 'inherit', fontWeight: 'inherit' } : {}),\n ...(level === 2 && text?.color === undefined && activeNodeId !== node.id\n ? { color: 'var(--sidebar-level-muted)' } : {}),\n }}\n >\n {node.label}\n {typeof node.id === 'string' && node.id.startsWith('ai-') && (\n <span className=\"dishui-sidebar-ai-native-badge\">AI</span>\n )}\n </Text>\n );\n }}\n onNodeClick={handleNodeClick}\n />\n </div>\n {footer && !isCollapsed && <div className=\"dishui-sidebar-ai-footer\">{footer}</div>}\n\n <style>{`\n .sidebar-container {\n --sidebar-level-muted: oklch(from color-mix(in oklab, var(--color-base-content) 76%, var(--color-base-200)) l 0 0);\n }\n /* LayoutSuite uses semantic surfaces even in colorful themes. Match its text luminance. */\n .dishui-layout-suite-sidebar > .sidebar-container {\n --sidebar-level-muted: oklch(from var(--dishui-text-tertiary) l 0 0);\n }\n .sidebar-rail { min-height: 0; height: 100%; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: 6px; }\n .sidebar-rail-group { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 4px 2px; margin-bottom: 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 10px; }\n .sidebar-rail-link { display: flex; align-items: center; justify-content: center; width: 100%; max-width: 36px; min-height: 36px; flex-shrink: 0; border-radius: 6px; color: var(--sidebar-level-muted); text-decoration: none; transition: background-color 150ms, color 150ms; }\n .sidebar-rail-link > span { display: flex; align-items: center; justify-content: center; }\n .sidebar-rail-link svg { width: 16px; height: 16px; }\n .dishui-sidebar-ai-avatar svg, .dishui-sidebar-ai-action svg { width: 18px; height: 18px; }\n .dishui-sidebar-rail-tooltip { position: fixed; z-index: 1000; padding: 6px 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 6px; background: var(--color-base-100); color: var(--color-base-content); box-shadow: 0 2px 8px color-mix(in oklab, var(--color-base-content) 15%, transparent); font-size: 12px; line-height: 1.4; overflow-wrap: anywhere; max-height: calc(100vh - 16px); overflow-y: auto; pointer-events: none; }\n .sidebar-rail-link:hover { background: var(--color-base-300); }\n .sidebar-rail-link[aria-current=\"page\"] { color: var(--color-primary); background: color-mix(in oklab, var(--color-primary) 12%, var(--color-base-200)); box-shadow: inset 2px 0 var(--color-primary); }\n .sidebar-rail-link:focus-visible { outline: 2px solid var(--dishui-ring, var(--color-primary)); outline-offset: -2px; }\n @media (prefers-reduced-motion: reduce) { .sidebar-rail-link { transition: none; } }\n /* Sidebar Tree 自定义样式 */\n .sidebar-tree {\n background: transparent;\n border: none;\n padding: 0.5rem;\n }\n \n .sidebar-tree .tree-node-content {\n padding: 0.5rem 1rem;\n border-radius: var(--dishui-radius-sm);\n transition: background-color var(--dishui-duration-normal) var(--dishui-ease-out), color var(--dishui-duration-normal) var(--dishui-ease-out), transform var(--dishui-duration-normal) var(--dishui-ease-out);\n }\n \n /* 活跃状态 - 为每个主题设置匹配的配色 */\n .sidebar-tree .tree-node-content-active {\n font-weight: 600 !important;\n padding-left: calc(1rem - 4px) !important;\n }\n \n /* 主题活跃状态样式 - 从共用配置生成 */\n ${generateSidebarActiveStyles()}\n \n /* 悬停状态 */\n .sidebar-tree .tree-node-content:hover:not(.tree-node-active .tree-node-content):not(.tree-node-content-active) {\n background-color: var(--color-base-200);\n }\n \n /* 右侧展开按钮样式 */\n .sidebar-tree .tree-node-toggle-right {\n width: auto;\n height: auto;\n min-width: auto;\n min-height: auto;\n padding: 0.25rem;\n opacity: 0.6;\n transition: opacity var(--dishui-duration-normal) var(--dishui-ease-out), background-color var(--dishui-duration-normal) var(--dishui-ease-out);\n border-radius: var(--dishui-radius-xs);\n }\n \n .sidebar-tree .tree-node-toggle-right:hover {\n opacity: 1;\n background-color: var(--color-base-300);\n }\n \n /* 右侧按钮图标旋转 */\n .sidebar-tree .tree-node-toggle-right svg {\n width: 1rem;\n height: 1rem;\n transition: transform var(--dishui-duration-normal) var(--dishui-ease-out);\n }\n \n .sidebar-tree .tree-node-toggle-right.tree-node-toggle-expanded svg {\n transform: rotate(90deg);\n }\n \n /* 图标样式 */\n .sidebar-tree .tree-node-icon {\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: color 0.2s ease;\n }\n \n .sidebar-tree .tree-node-icon svg {\n width: 20px;\n height: 20px;\n }\n \n /* 子节点图标稍小 */\n .sidebar-tree .tree-node-children .tree-node-icon svg {\n width: 18px;\n height: 18px;\n opacity: 0.8;\n }\n \n /* Preserve the legacy all-level appearance only when typography is not configured. */\n .sidebar-tree:not(.sidebar-tree-level-text) .tree-node-label {\n font-size: 1rem;\n line-height: 1.4rem;\n font-weight: 500;\n }\n \n /* 连接线样式 - 强制显示!向右移动并加粗,增加整体左边距 */\n /* 使用双重选择器增加优先级,避免被其他 Tree 组件样式覆盖 */\n .sidebar-tree.sidebar-tree .tree-show-line .tree-node-children-expanded,\n .sidebar-tree.sidebar-tree .tree-node-children.tree-node-children-expanded,\n div.sidebar-tree .tree-show-line .tree-node-children-expanded,\n div.sidebar-tree .tree-node-children.tree-node-children-expanded {\n border-left: 3px solid rgba(128, 128, 128, 0.35) !important;\n margin-left: 24px !important;\n padding-left: 8px !important;\n box-sizing: border-box !important;\n }\n \n /* 隐藏 Tree 组件的圆点装饰 - 避免与 Sidebar 样式冲突 */\n .sidebar-tree.sidebar-tree .tree-show-line .tree-node-children-expanded::before,\n div.sidebar-tree .tree-show-line .tree-node-children-expanded::before {\n display: none !important;\n }\n \n /* 隐藏 Tree 组件的标题和操作按钮 */\n .sidebar-tree .tree-header,\n .sidebar-tree .tree-search,\n .sidebar-tree .tree-actions {\n display: none;\n }\n \n /* 移除内边距 */\n .sidebar-tree > div:first-child {\n padding: 0;\n }\n \n /* 子节点动画优化 - 减小间距 */\n .sidebar-tree .tree-node-children {\n margin-top: 0.125rem !important;\n }\n \n /* 一级菜单项间距 */\n .sidebar-tree > div > .tree-nodes > .tree-node {\n margin-bottom: 0.375rem;\n }\n \n /* 二级菜单项间距 */\n .sidebar-tree .tree-node-children > .tree-node {\n margin-bottom: 0.125rem;\n }\n `}</style>\n </div>\n );\n};\n\nexport default Sidebar; "],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Sidebar.js","names":["getMenuItems","defaultGetMenuItems","Text","Tree","DefaultMenuIcon","DefaultWorkspaceIcon","DefaultActionIcon","getRailTooltip","rect","target","sidebar","sidebarElement","spaceLeft","spaceRight","alignRight","side","DEFAULT_LEVEL_TEXT","Sidebar","propItems","getMenuItems$1","items","setItems","useState","activeNodeId","setActiveNodeId","sidebarWidth","setSidebarWidth","minWidth","initialWidth","maxWidth","sidebarRef","useRef","scrollRef","railTooltip","setRailTooltip","routerState","useRouterState","s","navigate","useNavigate","handleInternalWidthChange","next","width","onWidthChange","useEffect","language","getMenuItems","t","isCollapsed","el","onWheel","dy","e","before","showRailTooltip","text","hideTooltipOnMouseLeave","current","hideTooltipOnBlur","update","convertToTreeNodes","menuItems","item","treeData","useMemo","defaultExpandedIds","collectAllExpandableIds","result","currentPath","findNodeByPath","found","nodeId","handleNodeClick","node","findFirstPath","nodes","firstNodeWithPath","collectLinks","trail","parents","rail","links","group","Link","event","collapsedWidth","onToggle","DesktopSidebarToggleButton","workspace","primaryAction","createPortal","levelText","level","depth","defaults","footer","generateSidebarActiveStyles"],"sources":["../../src/layouts/Sidebar.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Link, useNavigate, useRouterState } from '@tanstack/react-router';\nimport { MenuItem } from '../types/menu';\nimport { getMenuItems as defaultGetMenuItems } from '../utils/menu';\nimport { Tree, TreeNode } from '../components/Tree';\nimport { generateSidebarActiveStyles } from '../styles/themeStyles';\nimport { DesktopSidebarToggleButton } from '../components/SidebarToggleButton';\nimport Text, { type TextProps } from '../components/Text';\n\nexport type SidebarLevelText = Pick<TextProps, 'size' | 'weight' | 'color'>;\n\nexport type SidebarHeader = {\n name: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nexport type SidebarAction = {\n label: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nconst DefaultMenuIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"3\" />\n <path d=\"M8 9h8M8 13h8M8 17h5\" />\n </svg>\n);\n\nconst DefaultWorkspaceIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\" />\n <path d=\"M9 3v18M9 10h12\" />\n </svg>\n);\n\nconst DefaultActionIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\">\n <path d=\"M12 5v14M5 12h14\" />\n </svg>\n);\n\ntype RailTooltip = { target: HTMLElement; text: string; top: number; left: number; maxWidth: number; alignRight: boolean };\n\nconst getRailTooltip = (target: HTMLElement, sidebarElement: HTMLElement | null, side: 'left' | 'right', text: string): RailTooltip => {\n const rect = target.getBoundingClientRect();\n const sidebar = sidebarElement?.getBoundingClientRect() ?? rect;\n const spaceLeft = sidebar.left - 16;\n const spaceRight = window.innerWidth - sidebar.right - 16;\n const alignRight = side === 'right' ? spaceLeft >= 200 || spaceLeft > spaceRight : spaceRight < 200 && spaceLeft > spaceRight;\n return {\n target,\n text,\n top: Math.max(8, Math.min(rect.top, window.innerHeight - 48)),\n left: alignRight ? sidebar.left - 8 : sidebar.right + 8,\n maxWidth: Math.max(0, Math.min(320, alignRight ? spaceLeft : spaceRight)),\n alignRight,\n };\n};\n\nconst DEFAULT_LEVEL_TEXT = [\n { size: 'base', weight: 'semibold' },\n { size: 'sm', weight: 'medium' },\n { size: 'sm', weight: 'normal' },\n] as const satisfies readonly SidebarLevelText[];\n\n// 组件属性\nexport type SidebarProps = {\n isCollapsed: boolean;\n /** 侧栏所在侧,控制内侧 pill 的位置与调宽方向。 */\n side?: 'left' | 'right';\n language: 'zh' | 'en';\n items?: MenuItem[];\n /**\n * Opt-in typography for levels 1–3; deeper nodes reuse level 3.\n * Omitted: preserve legacy Sidebar/LayoutSuite typography. When supplied,\n * missing values default to base/sm/sm and semibold/medium/normal.\n * Levels 3+ default to theme-adaptive neutral gray, even without levelText.\n * Explicit colors retain Text semantics (secondary may be a theme accent).\n * Selected labels always inherit the active row color.\n */\n levelText?: readonly [SidebarLevelText?, SidebarLevelText?, SidebarLevelText?];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n onWidthChange?: (width: number) => void;\n initialWidth?: number;\n collapsedWidth?: number;\n /**\n * 折叠 / 展开切换回调。传入后,侧边栏会在其边缘渲染统一的悬浮 pill 控制条\n * (点击折叠、拖拽调节宽度),无需再在外层单独渲染 SidebarToggleButtons。\n */\n onToggle?: () => void;\n /** 拖拽调节宽度的最小值(px) */\n minWidth?: number;\n /** 拖拽调节宽度的最大值(px) */\n maxWidth?: number;\n /** Optional AI-style workspace header shown above the tree. */\n workspace?: SidebarHeader;\n /** Optional primary sidebar action, such as “New chat”. */\n primaryAction?: SidebarAction;\n /** Optional footer rendered below the scrollable multi-level menu. */\n footer?: React.ReactNode;\n};\n\nconst Sidebar: React.FC<SidebarProps> = ({\n isCollapsed,\n side = 'left',\n language,\n items: propItems,\n levelText,\n getMenuItems,\n onWidthChange,\n initialWidth = 280,\n collapsedWidth = 64,\n onToggle,\n minWidth = 160,\n maxWidth = 400,\n workspace,\n primaryAction,\n footer,\n}) => {\n const [items, setItems] = useState<MenuItem[]>([]);\n const [activeNodeId, setActiveNodeId] = useState<string | number>('');\n const [sidebarWidth, setSidebarWidth] = useState(() => Math.max(minWidth, Math.min(initialWidth, maxWidth)));\n const sidebarRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const [railTooltip, setRailTooltip] = useState<RailTooltip | null>(null);\n const routerState = useRouterState({ select: (s: { location: { pathname: string } }) => s.location });\n const navigate = useNavigate();\n\n // 当 initialWidth 改变时,更新侧边栏宽度\n useEffect(() => {\n setSidebarWidth(Math.max(minWidth, Math.min(initialWidth, maxWidth)));\n }, [initialWidth, minWidth, maxWidth]);\n\n // 统一的宽度变更处理:同步内部状态并通知父组件。\n // pill 拖拽与外部同步都通过此入口,避免必须回传 initialWidth 才能生效。\n const handleInternalWidthChange = (width: number) => {\n const next = Math.max(minWidth, Math.min(width, maxWidth));\n setSidebarWidth(next);\n onWidthChange?.(next);\n };\n\n // 当语言改变或传入items prop时,更新菜单项\n useEffect(() => {\n if (propItems !== undefined) {\n setItems(propItems);\n } else if (getMenuItems) {\n setItems(getMenuItems(language));\n } else {\n setItems(defaultGetMenuItems(language));\n }\n }, [language, propItems, getMenuItems]);\n\n // 活跃节点变化时,自动滚动到可见区域(菜单过长时保证当前页可见)。\n // 延迟 350ms:Tree 展开动画(max-height 0.3s)期间布局仍在变化,立即\n // scrollIntoView 会计算到动画中途的位置而滚动不到位。\n useEffect(() => {\n if (!activeNodeId) return;\n const t = setTimeout(() => {\n scrollRef.current\n ?.querySelector(isCollapsed ? '[aria-current=\"page\"]' : '.tree-node-content-active')\n ?.scrollIntoView({ block: 'nearest', behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'instant' : 'smooth' });\n }, 350);\n return () => clearTimeout(t);\n }, [activeNodeId, isCollapsed]);\n\n // 兜底:确保鼠标悬停在菜单任意位置都能滚轮滚动。\n // 部分浏览器/嵌套滚动场景下原生滚轮可能不作用于该容器,这里用非被动\n // 监听手动滚动;成功滚动后 preventDefault,避免浏览器默认行为造成双重滚动。\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n if (el.scrollHeight <= el.clientHeight) return;\n const dy = e.deltaMode === 1 ? e.deltaY * 16 : e.deltaY; // 行模式 → 像素\n if (dy === 0) return;\n const before = el.scrollTop;\n el.scrollTop = before + dy;\n if (el.scrollTop !== before) e.preventDefault();\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [isCollapsed]);\n\n const showRailTooltip = (target: HTMLElement, text: string) => {\n setRailTooltip(getRailTooltip(target, sidebarRef.current, side, text));\n };\n\n const hideTooltipOnMouseLeave = (target: HTMLElement) => {\n if (document.activeElement !== target) setRailTooltip(current => current?.target === target ? null : current);\n };\n\n const hideTooltipOnBlur = (target: HTMLElement) => {\n if (!target.matches(':hover')) setRailTooltip(current => current?.target === target ? null : current);\n };\n\n useEffect(() => {\n if (!isCollapsed) return;\n const update = () => {\n setRailTooltip(current => current?.target.isConnected\n ? getRailTooltip(current.target, sidebarRef.current, side, current.text)\n : null);\n };\n window.addEventListener('resize', update);\n return () => window.removeEventListener('resize', update);\n }, [isCollapsed, side, sidebarRef]);\n\n // 将 MenuItem 转换为 TreeNode\n const convertToTreeNodes = (menuItems: MenuItem[]): TreeNode[] => {\n return menuItems.map(item => ({\n id: item.id,\n label: item.label,\n icon: item.icon ?? <DefaultMenuIcon />,\n children: item.children ? convertToTreeNodes(item.children) : undefined,\n meta: {\n path: item.path,\n },\n }));\n };\n\n // 转换后的树形数据\n const treeData = useMemo(() => convertToTreeNodes(items), [items]);\n\n // 获取默认展开的节点ID(默认全部展开)\n const defaultExpandedIds = useMemo(() => {\n if (items.length === 0) return [];\n\n // 收集所有有子节点的项的ID,使其默认全展开\n const collectAllExpandableIds = (menuItems: MenuItem[]): string[] => {\n let result: string[] = [];\n for (const item of menuItems) {\n if (item.children?.length) {\n result.push(item.id);\n result = [...result, ...collectAllExpandableIds(item.children)];\n }\n }\n return result;\n };\n\n return collectAllExpandableIds(items);\n }, [items]);\n\n // 更新活跃节点ID\n useEffect(() => {\n const currentPath = routerState.pathname;\n const findNodeByPath = (menuItems: MenuItem[]): string | null => {\n for (const item of menuItems) {\n if (item.path === currentPath) {\n return item.id;\n }\n if (item.children) {\n const found = findNodeByPath(item.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n const nodeId = findNodeByPath(items);\n setActiveNodeId(nodeId ?? '');\n }, [items, routerState.pathname]);\n\n\n\n // 处理节点点击\n const handleNodeClick = (node: TreeNode) => {\n // 如果节点有路径,直接导航\n if (node.meta?.path) {\n setActiveNodeId(node.id);\n navigate({ to: node.meta.path });\n return;\n }\n\n // 如果没有路径但有子节点,寻找第一个有路径的后代节点\n if (node.children && node.children.length > 0) {\n const findFirstPath = (nodes: TreeNode[]): TreeNode | null => {\n for (const n of nodes) {\n if (n.meta?.path) return n;\n if (n.children && n.children.length > 0) {\n const found = findFirstPath(n.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n const firstNodeWithPath = findFirstPath(node.children);\n if (firstNodeWithPath) {\n setActiveNodeId(firstNodeWithPath.id);\n navigate({ to: firstNodeWithPath.meta!.path });\n } else {\n // 全都没有路径则激活当前节点\n setActiveNodeId(node.id);\n }\n } else {\n setActiveNodeId(node.id);\n }\n };\n\n const collectLinks = (nodes: MenuItem[], parents: string[] = []): { item: MenuItem; trail: string }[] =>\n nodes.flatMap(item => {\n const trail = [...parents, item.label];\n return [\n ...(item.path ? [{ item, trail: trail.join(' / ') }] : []),\n ...collectLinks(item.children ?? [], trail),\n ];\n });\n\n /* Keep Tree mounted so rail toggles do not reset the user's expanded branches. */\n const rail = isCollapsed ? (\n <nav ref={scrollRef} className=\"sidebar-rail\" aria-label={language === 'zh' ? '侧边导航' : 'Sidebar navigation'} onScroll={() => {\n if (railTooltip?.target.isConnected) showRailTooltip(railTooltip.target, railTooltip.text);\n }}>\n {items.map(group => {\n const links = collectLinks([group]);\n return links.length > 0 ? (\n <div key={group.id} role=\"group\" aria-label={group.label} className=\"sidebar-rail-group\">\n {links.map(({ item, trail }) => (\n <Link\n key={item.id}\n to={item.path!}\n className=\"sidebar-rail-link\"\n aria-label={trail}\n title={trail}\n aria-current={routerState.pathname === item.path ? 'page' : undefined}\n onMouseEnter={event => showRailTooltip(event.currentTarget, trail)}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onFocus={event => showRailTooltip(event.currentTarget, trail)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span aria-hidden=\"true\">{item.icon ?? <DefaultMenuIcon />}</span>\n </Link>\n ))}\n </div>\n ) : null;\n })}\n </nav>\n ) : null;\n\n return (\n <div\n ref={sidebarRef}\n className=\"dishui-sidebar sidebar-container h-full bg-base-200 overflow-visible flex flex-col transition-colors duration-200 ease-in-out relative\"\n style={isCollapsed ? { width: collapsedWidth } : { width: sidebarWidth, maxWidth, minWidth }}\n >\n {onToggle && (\n <DesktopSidebarToggleButton\n isCollapsed={isCollapsed}\n side={side}\n onToggle={onToggle}\n sidebarWidth={sidebarWidth}\n collapsedWidth={collapsedWidth}\n onWidthChange={onWidthChange ? handleInternalWidthChange : undefined}\n minWidth={minWidth}\n maxWidth={maxWidth}\n anchorRef={sidebarRef}\n />\n )}\n {(workspace || primaryAction) && (\n <div className=\"dishui-sidebar-ai-header\">\n {workspace && (\n <button\n type=\"button\"\n className=\"dishui-sidebar-ai-workspace\"\n onClick={workspace.onClick}\n aria-label={isCollapsed && typeof workspace.name === 'string' ? workspace.name : undefined}\n title={isCollapsed && typeof workspace.name === 'string' ? workspace.name : undefined}\n onMouseEnter={event => { if (isCollapsed && typeof workspace.name === 'string') showRailTooltip(event.currentTarget, workspace.name); }}\n onFocus={event => { if (isCollapsed && typeof workspace.name === 'string') showRailTooltip(event.currentTarget, workspace.name); }}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span className=\"dishui-sidebar-ai-avatar\" aria-hidden=\"true\">{workspace.icon ?? <DefaultWorkspaceIcon />}</span>\n {!isCollapsed && <span className=\"dishui-sidebar-ai-workspace-name\">{workspace.name}</span>}\n </button>\n )}\n {primaryAction && (\n <button\n type=\"button\"\n className=\"dishui-sidebar-ai-action\"\n onClick={primaryAction.onClick}\n aria-label={isCollapsed && typeof primaryAction.label === 'string' ? primaryAction.label : undefined}\n title={isCollapsed && typeof primaryAction.label === 'string' ? primaryAction.label : undefined}\n onMouseEnter={event => { if (isCollapsed && typeof primaryAction.label === 'string') showRailTooltip(event.currentTarget, primaryAction.label); }}\n onFocus={event => { if (isCollapsed && typeof primaryAction.label === 'string') showRailTooltip(event.currentTarget, primaryAction.label); }}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span aria-hidden=\"true\">{primaryAction.icon ?? <DefaultActionIcon />}</span>\n {!isCollapsed && <span>{primaryAction.label}</span>}\n </button>\n )}\n </div>\n )}\n {rail}\n {isCollapsed && railTooltip?.target.isConnected && createPortal(\n <div className=\"dishui-sidebar-rail-tooltip\" role=\"tooltip\" aria-hidden=\"true\" style={{ top: railTooltip.top, left: railTooltip.left, maxWidth: railTooltip.maxWidth, transform: railTooltip.alignRight ? 'translateX(-100%)' : undefined }}>\n {railTooltip.text}\n </div>,\n document.body,\n )}\n <div hidden={isCollapsed} style={isCollapsed ? { display: 'none' } : undefined} ref={isCollapsed ? undefined : scrollRef} className=\"sidebar-scroll min-h-0 flex-grow overflow-y-auto scrollbar-thin scrollbar-thumb-base-300 scrollbar-track-transparent\">\n <Tree\n data={treeData}\n activeNodeId={activeNodeId}\n defaultExpandedIds={defaultExpandedIds}\n showSearch={false}\n showExpandAll={false}\n showIcon={true}\n showCount={false}\n showLine={true}\n indent={1}\n togglePosition=\"right\"\n maxHeight=\"100%\"\n className={`sidebar-tree${levelText !== undefined ? ' sidebar-tree-level-text' : ''}`}\n renderLabel={(node, depth) => {\n const level = Math.min(depth, 2);\n const text = levelText?.[level];\n const defaults = DEFAULT_LEVEL_TEXT[level];\n return (\n <Text\n size={text?.size ?? defaults.size}\n weight={text?.weight ?? defaults.weight}\n color={activeNodeId === node.id ? 'inherit' : text?.color ?? 'inherit'}\n style={{\n ...(levelText === undefined ? { fontSize: 'inherit', lineHeight: 'inherit', fontWeight: 'inherit' } : {}),\n ...(level === 2 && text?.color === undefined && activeNodeId !== node.id\n ? { color: 'var(--sidebar-level-muted)' } : {}),\n }}\n >\n {node.label}\n {typeof node.id === 'string' && node.id.startsWith('ai-') && (\n <span className=\"dishui-sidebar-ai-native-badge\">AI</span>\n )}\n </Text>\n );\n }}\n onNodeClick={handleNodeClick}\n />\n </div>\n {footer && !isCollapsed && <div className=\"dishui-sidebar-ai-footer\">{footer}</div>}\n\n <style>{`\n .sidebar-container {\n --sidebar-level-muted: oklch(from color-mix(in oklab, var(--color-base-content) 76%, var(--color-base-200)) l 0 0);\n }\n /* LayoutSuite uses semantic surfaces even in colorful themes. Match its text luminance. */\n .dishui-layout-suite-sidebar > .sidebar-container {\n --sidebar-level-muted: oklch(from var(--dishui-text-tertiary) l 0 0);\n }\n .sidebar-rail { min-height: 0; height: 100%; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: 6px; }\n .sidebar-rail-group { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 4px 2px; margin-bottom: 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 10px; }\n .sidebar-rail-link { display: flex; align-items: center; justify-content: center; width: 100%; max-width: 36px; min-height: 36px; flex-shrink: 0; border-radius: 6px; color: var(--sidebar-level-muted); text-decoration: none; transition: background-color 150ms, color 150ms; }\n .sidebar-rail-link > span { display: flex; align-items: center; justify-content: center; }\n .sidebar-rail-link svg { width: 16px; height: 16px; }\n .dishui-sidebar-ai-avatar svg, .dishui-sidebar-ai-action svg { width: 18px; height: 18px; }\n .dishui-sidebar-rail-tooltip { position: fixed; z-index: 1000; padding: 6px 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 6px; background: var(--color-base-100); color: var(--color-base-content); box-shadow: 0 2px 8px color-mix(in oklab, var(--color-base-content) 15%, transparent); font-size: 12px; line-height: 1.4; overflow-wrap: anywhere; max-height: calc(100vh - 16px); overflow-y: auto; pointer-events: none; }\n .sidebar-rail-link:hover { background: var(--color-base-300); }\n .sidebar-rail-link[aria-current=\"page\"] { color: var(--color-primary); background: color-mix(in oklab, var(--color-primary) 12%, var(--color-base-200)); box-shadow: inset 2px 0 var(--color-primary); }\n .sidebar-rail-link:focus-visible { outline: 2px solid var(--dishui-ring, var(--color-primary)); outline-offset: -2px; }\n @media (prefers-reduced-motion: reduce) { .sidebar-rail-link { transition: none; } }\n /* Sidebar Tree 自定义样式 */\n .sidebar-tree {\n background: transparent;\n border: none;\n padding: 0.5rem;\n }\n \n .sidebar-tree .tree-node-content {\n padding: 0.5rem 1rem;\n border-radius: var(--dishui-radius-sm);\n transition: background-color var(--dishui-duration-normal) var(--dishui-ease-out), color var(--dishui-duration-normal) var(--dishui-ease-out), transform var(--dishui-duration-normal) var(--dishui-ease-out);\n }\n \n /* 活跃状态 - 为每个主题设置匹配的配色 */\n .sidebar-tree .tree-node-content-active {\n font-weight: 600 !important;\n padding-left: calc(1rem - 4px) !important;\n }\n \n /* 主题活跃状态样式 - 从共用配置生成 */\n ${generateSidebarActiveStyles()}\n \n /* 悬停状态 */\n .sidebar-tree .tree-node-content:hover:not(.tree-node-active .tree-node-content):not(.tree-node-content-active) {\n background-color: var(--color-base-200);\n }\n \n /* 右侧展开按钮样式 */\n .sidebar-tree .tree-node-toggle-right {\n width: auto;\n height: auto;\n min-width: auto;\n min-height: auto;\n padding: 0.25rem;\n opacity: 0.6;\n transition: opacity var(--dishui-duration-normal) var(--dishui-ease-out), background-color var(--dishui-duration-normal) var(--dishui-ease-out);\n border-radius: var(--dishui-radius-xs);\n }\n \n .sidebar-tree .tree-node-toggle-right:hover {\n opacity: 1;\n background-color: var(--color-base-300);\n }\n \n /* 右侧按钮图标旋转 */\n .sidebar-tree .tree-node-toggle-right svg {\n width: 1rem;\n height: 1rem;\n transition: transform var(--dishui-duration-normal) var(--dishui-ease-out);\n }\n \n .sidebar-tree .tree-node-toggle-right.tree-node-toggle-expanded svg {\n transform: rotate(90deg);\n }\n \n /* 图标样式 */\n .sidebar-tree .tree-node-icon {\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: color 0.2s ease;\n }\n \n .sidebar-tree .tree-node-icon svg {\n width: 20px;\n height: 20px;\n }\n \n /* 子节点图标稍小 */\n .sidebar-tree .tree-node-children .tree-node-icon svg {\n width: 18px;\n height: 18px;\n opacity: 0.8;\n }\n \n /* Preserve the legacy all-level appearance only when typography is not configured. */\n .sidebar-tree:not(.sidebar-tree-level-text) .tree-node-label {\n font-size: 1rem;\n line-height: 1.4rem;\n font-weight: 500;\n }\n \n /* 连接线样式 - 强制显示!向右移动并加粗,增加整体左边距 */\n /* 使用双重选择器增加优先级,避免被其他 Tree 组件样式覆盖 */\n .sidebar-tree.sidebar-tree .tree-show-line .tree-node-children-expanded,\n .sidebar-tree.sidebar-tree .tree-node-children.tree-node-children-expanded,\n div.sidebar-tree .tree-show-line .tree-node-children-expanded,\n div.sidebar-tree .tree-node-children.tree-node-children-expanded {\n border-left: 3px solid rgba(128, 128, 128, 0.35) !important;\n margin-left: 24px !important;\n padding-left: 8px !important;\n box-sizing: border-box !important;\n }\n \n /* 隐藏 Tree 组件的圆点装饰 - 避免与 Sidebar 样式冲突 */\n .sidebar-tree.sidebar-tree .tree-show-line .tree-node-children-expanded::before,\n div.sidebar-tree .tree-show-line .tree-node-children-expanded::before {\n display: none !important;\n }\n \n /* 隐藏 Tree 组件的标题和操作按钮 */\n .sidebar-tree .tree-header,\n .sidebar-tree .tree-search,\n .sidebar-tree .tree-actions {\n display: none;\n }\n \n /* 移除内边距 */\n .sidebar-tree > div:first-child {\n padding: 0;\n }\n \n /* 子节点动画优化 - 减小间距 */\n .sidebar-tree .tree-node-children {\n margin-top: 0.125rem !important;\n }\n \n /* 一级菜单项间距 */\n .sidebar-tree > div > .tree-nodes > .tree-node {\n margin-bottom: 0.375rem;\n }\n \n /* 二级菜单项间距 */\n .sidebar-tree .tree-node-children > .tree-node {\n margin-bottom: 0.125rem;\n }\n `}</style>\n </div>\n );\n};\n\nexport default Sidebar; "],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Headbar.js","names":[],"sources":["../../../src/layouts/headbar/Headbar.tsx"],"sourcesContent":["import React from 'react';\n\nexport type HeadbarProps = {\n /** 左侧插槽内容 */\n left?: React.ReactNode;\n /** 中间插槽内容 */\n middle?: React.ReactNode;\n /** 右侧插槽内容 */\n right?: React.ReactNode;\n /** 高度(像素),默认 52 */\n height?: number;\n /** 自定义 className */\n className?: string;\n};\n\n/**\n * Headbar - 纯布局容器,提供 left / middle / right 三个插槽。\n * 不包含任何业务逻辑,所有内容通过 props 注入。\n */\nconst Headbar: React.FC<HeadbarProps> = ({\n left,\n middle,\n right,\n height = 52,\n className,\n}) => {\n return (\n <div\n className={`navbar bg-base-100 border-b border-base-300 ${className || ''}`}\n style={{\n height: `${height}px`,\n minHeight: `${height}px`,\n maxHeight: `${height}px`,\n }}\n >\n <div className=\"navbar-start\">{left}</div>\n <div className=\"navbar-center hidden lg:flex\">{middle}</div>\n <div className=\"navbar-end\">{right}</div>\n </div>\n );\n};\n\nexport default Headbar;\n"],"mappings":";;;AAmBA,
|
|
1
|
+
{"version":3,"file":"Headbar.js","names":["Headbar","className","height","left","middle","right"],"sources":["../../../src/layouts/headbar/Headbar.tsx"],"sourcesContent":["import React from 'react';\n\nexport type HeadbarProps = {\n /** 左侧插槽内容 */\n left?: React.ReactNode;\n /** 中间插槽内容 */\n middle?: React.ReactNode;\n /** 右侧插槽内容 */\n right?: React.ReactNode;\n /** 高度(像素),默认 52 */\n height?: number;\n /** 自定义 className */\n className?: string;\n};\n\n/**\n * Headbar - 纯布局容器,提供 left / middle / right 三个插槽。\n * 不包含任何业务逻辑,所有内容通过 props 注入。\n */\nconst Headbar: React.FC<HeadbarProps> = ({\n left,\n middle,\n right,\n height = 52,\n className,\n}) => {\n return (\n <div\n className={`navbar bg-base-100 border-b border-base-300 ${className || ''}`}\n style={{\n height: `${height}px`,\n minHeight: `${height}px`,\n maxHeight: `${height}px`,\n }}\n >\n <div className=\"navbar-start\">{left}</div>\n <div className=\"navbar-center hidden lg:flex\">{middle}</div>\n <div className=\"navbar-end\">{right}</div>\n </div>\n );\n};\n\nexport default Headbar;\n"],"mappings":";;;AAmBA,IAAMA,KAAmC,EACvC,SACA,WACA,UACA,YAAS,IACT,mBAGE,kBAAC,OAAD;CACE,WAAW,+CAA+CC,KAAa;CACvE,OAAO;EACL,QAAQ,GAAGC,EAAO;EAClB,WAAW,GAAGA,EAAO;EACrB,WAAW,GAAGA,EAAO;CACvB;CANF,UAAA;EAQE,kBAAC,OAAD;GAAK,WAAU;GAAgB,UAAAC;EAAU,CAAA;EACzC,kBAAC,OAAD;GAAK,WAAU;GAAgC,UAAAC;EAAY,CAAA;EAC3D,kBAAC,OAAD;GAAK,WAAU;GAAc,UAAAC;EAAW,CAAA;CACrC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadbarLangSwitcher.js","names":[],"sources":["../../../src/layouts/headbar/HeadbarLangSwitcher.tsx"],"sourcesContent":["import React from 'react';\nimport { useAppContext } from '../../contexts/AppContext';\n\n/**\n * HeadbarLangSwitcher - 语言切换下拉菜单\n */\nconst HeadbarLangSwitcher: React.FC = () => {\n const { language, setLanguage } = useAppContext();\n\n return (\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost gap-1\">\n {language === 'zh' ? '中文' : 'English'}\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </label>\n <ul\n tabIndex={0}\n className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-40 mt-4\"\n >\n <li>\n <a\n className={language === 'zh' ? 'active' : ''}\n onClick={() => setLanguage('zh')}\n >\n 中文\n </a>\n </li>\n <li>\n <a\n className={language === 'en' ? 'active' : ''}\n onClick={() => setLanguage('en')}\n >\n English\n </a>\n </li>\n </ul>\n </div>\n );\n};\n\nexport default HeadbarLangSwitcher;\n"],"mappings":";;;;AAMA,
|
|
1
|
+
{"version":3,"file":"HeadbarLangSwitcher.js","names":["HeadbarLangSwitcher","useAppContext","language","setLanguage"],"sources":["../../../src/layouts/headbar/HeadbarLangSwitcher.tsx"],"sourcesContent":["import React from 'react';\nimport { useAppContext } from '../../contexts/AppContext';\n\n/**\n * HeadbarLangSwitcher - 语言切换下拉菜单\n */\nconst HeadbarLangSwitcher: React.FC = () => {\n const { language, setLanguage } = useAppContext();\n\n return (\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost gap-1\">\n {language === 'zh' ? '中文' : 'English'}\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </label>\n <ul\n tabIndex={0}\n className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-40 mt-4\"\n >\n <li>\n <a\n className={language === 'zh' ? 'active' : ''}\n onClick={() => setLanguage('zh')}\n >\n 中文\n </a>\n </li>\n <li>\n <a\n className={language === 'en' ? 'active' : ''}\n onClick={() => setLanguage('en')}\n >\n English\n </a>\n </li>\n </ul>\n </div>\n );\n};\n\nexport default HeadbarLangSwitcher;\n"],"mappings":";;;;AAMA,IAAMA,UAAsC;CAC1C,IAAM,EAAE,aAAU,mBAAgBC,EAAc;CAEhD,OACE,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,kBAAC,SAAD;GAAO,UAAU;GAAG,WAAU;GAA9B,UAAA,CACGC,MAAa,OAAO,OAAO,WAC5B,kBAAC,OAAD;IACE,OAAM;IACN,WAAU;IACV,MAAK;IACL,SAAQ;IACR,QAAO;IAEP,UAAA,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAY;KACZ,GAAE;IACH,CAAA;GACE,CAAA,CACA;EACP,CAAA,GAAA,kBAAC,MAAD;GACE,UAAU;GACV,WAAU;GAFZ,UAAA,CAIE,kBAAC,MAAD,EAAA,UACE,kBAAC,KAAD;IACE,WAAWA,MAAa,OAAO,WAAW;IAC1C,eAAeC,EAAY,IAAI;IAChC,UAAA;GAEE,CAAA,EACD,CAAA,GACJ,kBAAC,MAAD,EAAA,UACE,kBAAC,KAAD;IACE,WAAWD,MAAa,OAAO,WAAW;IAC1C,eAAeC,EAAY,IAAI;IAChC,UAAA;GAEE,CAAA,EACD,CAAA,CACF;EACD,CAAA,CAAA;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadbarSearch.js","names":[],"sources":["../../../src/layouts/headbar/HeadbarSearch.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { useAppContext } from '../../contexts/AppContext';\nimport { getTranslations } from '../../utils/i18n';\n\nexport type SearchResult = {\n title: string;\n path: string;\n description: string;\n};\n\nexport type SearchConfig = {\n enabled: boolean;\n searchFunction?: (term: string, language: 'zh' | 'en') => SearchResult[];\n placeholder?: { zh: string; en: string };\n shortcut?: string;\n};\n\nexport type HeadbarSearchProps = {\n /** 搜索配置 */\n searchConfig?: SearchConfig;\n};\n\n/**\n * HeadbarSearch - 搜索按钮 + 搜索对话框\n */\nconst HeadbarSearch: React.FC<HeadbarSearchProps> = ({ searchConfig }) => {\n const { language } = useAppContext();\n const t = getTranslations(language);\n\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [searchResults, setSearchResults] = useState<SearchResult[]>([]);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDialogElement>(null);\n\n const isSearchEnabled = searchConfig?.enabled ?? true;\n\n const toggleSearch = () => {\n setIsSearchOpen(!isSearchOpen);\n if (!isSearchOpen && modalRef.current) {\n modalRef.current.showModal();\n setTimeout(() => {\n searchInputRef.current?.focus();\n }, 100);\n } else if (modalRef.current) {\n modalRef.current.close();\n }\n };\n\n const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearchTerm(value);\n const searchFn = searchConfig?.searchFunction;\n if (searchFn) {\n setSearchResults(searchFn(value, language));\n }\n };\n\n useEffect(() => {\n if (!isSearchEnabled) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault();\n toggleSearch();\n }\n if (e.key === 'Escape' && isSearchOpen) {\n toggleSearch();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isSearchOpen, isSearchEnabled]);\n\n // 当语言改变时,更新搜索结果\n useEffect(() => {\n if (searchTerm && isSearchEnabled && searchConfig?.searchFunction) {\n setSearchResults(searchConfig.searchFunction(searchTerm, language));\n }\n }, [language, searchConfig, isSearchEnabled, searchTerm]);\n\n if (!isSearchEnabled) return null;\n\n return (\n <>\n <button className=\"btn btn-ghost gap-2\" onClick={toggleSearch}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-5 w-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n {searchConfig?.placeholder?.[language] || t.navbar.search} (\n {searchConfig?.shortcut || t.navbar.searchShortcut})\n </button>\n\n {/* 搜索对话框 */}\n <dialog\n ref={modalRef}\n className=\"modal modal-bottom sm:modal-middle\"\n onClick={(e) => {\n if (e.target === modalRef.current) toggleSearch();\n }}\n >\n <div className=\"modal-box bg-base-100\">\n <div className=\"relative mb-4\">\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={\n searchConfig?.placeholder?.[language] ||\n t.navbar.searchPlaceholder\n }\n className=\"input input-bordered w-full pr-10\"\n value={searchTerm}\n onChange={handleSearch}\n />\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-5 w-5 absolute top-3 right-3 opacity-50\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n </div>\n\n <div className=\"search-results max-h-80 overflow-y-auto\">\n {searchResults.length > 0 ? (\n <ul className=\"menu bg-base-100 rounded-box\">\n {searchResults.map((result, index) => (\n <li key={index}>\n <a\n href={result.path}\n className=\"flex flex-col items-start\"\n onClick={() => toggleSearch()}\n >\n <div className=\"font-medium\">{result.title}</div>\n <div className=\"text-sm opacity-70\">\n {result.description}\n </div>\n </a>\n </li>\n ))}\n </ul>\n ) : searchTerm ? (\n <div className=\"py-4 text-center text-base-content/70\">\n {t.navbar.noResults}\n </div>\n ) : null}\n </div>\n\n <div className=\"modal-action\">\n <form method=\"dialog\">\n <button className=\"btn\" onClick={toggleSearch}>\n ESC\n </button>\n </form>\n </div>\n </div>\n </dialog>\n </>\n );\n};\n\nexport default HeadbarSearch;\n"],"mappings":";;;;;AAyBA,
|
|
1
|
+
{"version":3,"file":"HeadbarSearch.js","names":["_Fragment","HeadbarSearch","useAppContext","t","getTranslations","language","isSearchOpen","setIsSearchOpen","useState","searchTerm","setSearchTerm","searchResults","setSearchResults","searchInputRef","useRef","modalRef","isSearchEnabled","searchConfig","toggleSearch","useEffect","handleKeyDown","Fragment","value","searchFn","result","index"],"sources":["../../../src/layouts/headbar/HeadbarSearch.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { useAppContext } from '../../contexts/AppContext';\nimport { getTranslations } from '../../utils/i18n';\n\nexport type SearchResult = {\n title: string;\n path: string;\n description: string;\n};\n\nexport type SearchConfig = {\n enabled: boolean;\n searchFunction?: (term: string, language: 'zh' | 'en') => SearchResult[];\n placeholder?: { zh: string; en: string };\n shortcut?: string;\n};\n\nexport type HeadbarSearchProps = {\n /** 搜索配置 */\n searchConfig?: SearchConfig;\n};\n\n/**\n * HeadbarSearch - 搜索按钮 + 搜索对话框\n */\nconst HeadbarSearch: React.FC<HeadbarSearchProps> = ({ searchConfig }) => {\n const { language } = useAppContext();\n const t = getTranslations(language);\n\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [searchResults, setSearchResults] = useState<SearchResult[]>([]);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDialogElement>(null);\n\n const isSearchEnabled = searchConfig?.enabled ?? true;\n\n const toggleSearch = () => {\n setIsSearchOpen(!isSearchOpen);\n if (!isSearchOpen && modalRef.current) {\n modalRef.current.showModal();\n setTimeout(() => {\n searchInputRef.current?.focus();\n }, 100);\n } else if (modalRef.current) {\n modalRef.current.close();\n }\n };\n\n const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearchTerm(value);\n const searchFn = searchConfig?.searchFunction;\n if (searchFn) {\n setSearchResults(searchFn(value, language));\n }\n };\n\n useEffect(() => {\n if (!isSearchEnabled) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault();\n toggleSearch();\n }\n if (e.key === 'Escape' && isSearchOpen) {\n toggleSearch();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isSearchOpen, isSearchEnabled]);\n\n // 当语言改变时,更新搜索结果\n useEffect(() => {\n if (searchTerm && isSearchEnabled && searchConfig?.searchFunction) {\n setSearchResults(searchConfig.searchFunction(searchTerm, language));\n }\n }, [language, searchConfig, isSearchEnabled, searchTerm]);\n\n if (!isSearchEnabled) return null;\n\n return (\n <>\n <button className=\"btn btn-ghost gap-2\" onClick={toggleSearch}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-5 w-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n {searchConfig?.placeholder?.[language] || t.navbar.search} (\n {searchConfig?.shortcut || t.navbar.searchShortcut})\n </button>\n\n {/* 搜索对话框 */}\n <dialog\n ref={modalRef}\n className=\"modal modal-bottom sm:modal-middle\"\n onClick={(e) => {\n if (e.target === modalRef.current) toggleSearch();\n }}\n >\n <div className=\"modal-box bg-base-100\">\n <div className=\"relative mb-4\">\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={\n searchConfig?.placeholder?.[language] ||\n t.navbar.searchPlaceholder\n }\n className=\"input input-bordered w-full pr-10\"\n value={searchTerm}\n onChange={handleSearch}\n />\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-5 w-5 absolute top-3 right-3 opacity-50\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n </div>\n\n <div className=\"search-results max-h-80 overflow-y-auto\">\n {searchResults.length > 0 ? (\n <ul className=\"menu bg-base-100 rounded-box\">\n {searchResults.map((result, index) => (\n <li key={index}>\n <a\n href={result.path}\n className=\"flex flex-col items-start\"\n onClick={() => toggleSearch()}\n >\n <div className=\"font-medium\">{result.title}</div>\n <div className=\"text-sm opacity-70\">\n {result.description}\n </div>\n </a>\n </li>\n ))}\n </ul>\n ) : searchTerm ? (\n <div className=\"py-4 text-center text-base-content/70\">\n {t.navbar.noResults}\n </div>\n ) : null}\n </div>\n\n <div className=\"modal-action\">\n <form method=\"dialog\">\n <button className=\"btn\" onClick={toggleSearch}>\n ESC\n </button>\n </form>\n </div>\n </div>\n </dialog>\n </>\n );\n};\n\nexport default HeadbarSearch;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadbarThemeSwitcher.js","names":[],"sources":["../../../src/layouts/headbar/HeadbarThemeSwitcher.tsx"],"sourcesContent":["import React from 'react';\nimport { useAppContext } from '../../contexts/AppContext';\nimport { ThemeConfig, getThemes as defaultGetThemes } from '../../utils/themes';\n\nexport type HeadbarThemeSwitcherProps = {\n /** 可选的主题配置列表,不传则使用默认主题列表 */\n themes?: ThemeConfig[];\n};\n\n/**\n * HeadbarThemeSwitcher - 主题切换下拉菜单\n */\nconst HeadbarThemeSwitcher: React.FC<HeadbarThemeSwitcherProps> = ({\n themes: propThemes,\n}) => {\n const { language, theme, setTheme } = useAppContext();\n\n const themes = propThemes || defaultGetThemes();\n const currentTheme = themes.find((t) => t.id === theme) || themes[0];\n\n return (\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost\">\n {currentTheme.icon}\n </label>\n <ul\n tabIndex={0}\n className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-52 mt-4\"\n >\n {themes.map((themeOption) => (\n <li key={themeOption.id}>\n <a\n className={theme === themeOption.id ? 'active' : ''}\n onClick={() => setTheme(themeOption.id)}\n >\n <span className=\"mr-2\">{themeOption.icon}</span>\n {language === 'zh' ? themeOption.name.zh : themeOption.name.en}\n </a>\n </li>\n ))}\n </ul>\n </div>\n );\n};\n\nexport default HeadbarThemeSwitcher;\n"],"mappings":";;;;;AAYA,
|
|
1
|
+
{"version":3,"file":"HeadbarThemeSwitcher.js","names":["defaultGetThemes","HeadbarThemeSwitcher","propThemes","useAppContext","themes","getThemes","currentTheme","t","theme","themeOption","setTheme","language"],"sources":["../../../src/layouts/headbar/HeadbarThemeSwitcher.tsx"],"sourcesContent":["import React from 'react';\nimport { useAppContext } from '../../contexts/AppContext';\nimport { ThemeConfig, getThemes as defaultGetThemes } from '../../utils/themes';\n\nexport type HeadbarThemeSwitcherProps = {\n /** 可选的主题配置列表,不传则使用默认主题列表 */\n themes?: ThemeConfig[];\n};\n\n/**\n * HeadbarThemeSwitcher - 主题切换下拉菜单\n */\nconst HeadbarThemeSwitcher: React.FC<HeadbarThemeSwitcherProps> = ({\n themes: propThemes,\n}) => {\n const { language, theme, setTheme } = useAppContext();\n\n const themes = propThemes || defaultGetThemes();\n const currentTheme = themes.find((t) => t.id === theme) || themes[0];\n\n return (\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost\">\n {currentTheme.icon}\n </label>\n <ul\n tabIndex={0}\n className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-52 mt-4\"\n >\n {themes.map((themeOption) => (\n <li key={themeOption.id}>\n <a\n className={theme === themeOption.id ? 'active' : ''}\n onClick={() => setTheme(themeOption.id)}\n >\n <span className=\"mr-2\">{themeOption.icon}</span>\n {language === 'zh' ? themeOption.name.zh : themeOption.name.en}\n </a>\n </li>\n ))}\n </ul>\n </div>\n );\n};\n\nexport default HeadbarThemeSwitcher;\n"],"mappings":";;;;;AAYA,IAAMC,KAA6D,EACjE,QAAQC,QACJ;CACJ,IAAM,EAAE,aAAU,UAAO,gBAAaC,EAAc,GAE9CC,IAASF,KAAcF,EAAiB,GACxCM,IAAeF,EAAO,MAAM,MAAMG,EAAE,OAAOC,CAAK,KAAKJ,EAAO;CAElE,OACE,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,kBAAC,SAAD;GAAO,UAAU;GAAG,WAAU;GAC3B,UAAAE,EAAa;EACT,CAAA,GACP,kBAAC,MAAD;GACE,UAAU;GACV,WAAU;GAET,UAAAF,EAAO,KAAK,MACX,kBAAC,MAAD,EAAA,UACE,kBAAC,KAAD;IACE,WAAWI,MAAUC,EAAY,KAAK,WAAW;IACjD,eAAeC,EAASD,EAAY,EAAE;IAFxC,UAAA,CAIE,kBAAC,QAAD;KAAM,WAAU;KAAQ,UAAAA,EAAY;IAAW,CAAA,GAC9CE,MAAa,OAAOF,EAAY,KAAK,KAAKA,EAAY,KAAK,EAC3D;GACD,CAAA,EAAA,GARKA,EAAY,EAQjB,CACL;EACC,CAAA,CACD;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadbarTitle.js","names":[],"sources":["../../../src/layouts/headbar/HeadbarTitle.tsx"],"sourcesContent":["import React from 'react';\n\nexport type HeadbarTitleProps = {\n /** 显示的标题 */\n title?: string;\n /** 点击 hamburger 按钮时的回调(移动端切换侧边栏) */\n onToggleSidebar?: () => void;\n};\n\n/**\n * HeadbarTitle - 左侧标题区域,包含移动端 hamburger 按钮 + 应用标题链接\n */\nconst HeadbarTitle: React.FC<HeadbarTitleProps> = ({\n title = 'DiShUI',\n onToggleSidebar,\n}) => {\n return (\n <>\n {onToggleSidebar && (\n <div className=\"flex-none lg:hidden\">\n <button className=\"btn btn-square btn-ghost\" onClick={onToggleSidebar}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className=\"inline-block w-5 h-5 stroke-current\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M4 6h16M4 12h16M4 18h16\"\n />\n </svg>\n </button>\n </div>\n )}\n <a href=\"/\" className=\"btn btn-ghost normal-case text-xl\">\n {title}\n </a>\n </>\n );\n};\n\nexport default HeadbarTitle;\n"],"mappings":";;;AAYA,
|
|
1
|
+
{"version":3,"file":"HeadbarTitle.js","names":["_Fragment","HeadbarTitle","Fragment","onToggleSidebar","title"],"sources":["../../../src/layouts/headbar/HeadbarTitle.tsx"],"sourcesContent":["import React from 'react';\n\nexport type HeadbarTitleProps = {\n /** 显示的标题 */\n title?: string;\n /** 点击 hamburger 按钮时的回调(移动端切换侧边栏) */\n onToggleSidebar?: () => void;\n};\n\n/**\n * HeadbarTitle - 左侧标题区域,包含移动端 hamburger 按钮 + 应用标题链接\n */\nconst HeadbarTitle: React.FC<HeadbarTitleProps> = ({\n title = 'DiShUI',\n onToggleSidebar,\n}) => {\n return (\n <>\n {onToggleSidebar && (\n <div className=\"flex-none lg:hidden\">\n <button className=\"btn btn-square btn-ghost\" onClick={onToggleSidebar}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className=\"inline-block w-5 h-5 stroke-current\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M4 6h16M4 12h16M4 18h16\"\n />\n </svg>\n </button>\n </div>\n )}\n <a href=\"/\" className=\"btn btn-ghost normal-case text-xl\">\n {title}\n </a>\n </>\n );\n};\n\nexport default HeadbarTitle;\n"],"mappings":";;;AAYA,IAAMC,KAA6C,EACjD,WAAQ,UACR,yBAGE,kBAAAD,GAAA,EAAA,UAAA,CACGG,KACC,kBAAC,OAAD;CAAK,WAAU;CACb,UAAA,kBAAC,UAAD;EAAQ,WAAU;EAA2B,SAASA;EACpD,UAAA,kBAAC,OAAD;GACE,OAAM;GACN,MAAK;GACL,SAAQ;GACR,WAAU;GAEV,UAAA,kBAAC,QAAD;IACE,eAAc;IACd,gBAAe;IACf,aAAY;IACZ,GAAE;GACH,CAAA;EACE,CAAA;CACC,CAAA;AACL,CAAA,GAEP,kBAAC,KAAD;CAAG,MAAK;CAAI,WAAU;CACnB,UAAAC;AACA,CAAA,CACH,EAAA,CAAA"}
|
package/dist/sprite.js
ADDED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themeStyles.js","names":[],"sources":["../../src/styles/themeStyles.ts"],"sourcesContent":["// 共用主题样式配置\n// 用于 Tree 组件和 Sidebar 组件的活跃状态样式\n\nexport interface ThemeActiveStyle {\n backgroundColor: string;\n borderColor: string;\n textColor: string;\n}\n\n// 主题配色映射\nexport const themeActiveStyles: Record<string, ThemeActiveStyle> = {\n light: {\n backgroundColor: 'var(--dishui-accent)',\n borderColor: 'var(--dishui-accent)',\n textColor: 'var(--dishui-accent-fg)',\n },\n dark: {\n backgroundColor: 'var(--dishui-accent)',\n borderColor: 'var(--dishui-accent)',\n textColor: 'var(--dishui-accent-fg)',\n },\n cursor: {\n backgroundColor: 'rgba(96, 165, 250, 0.16)',\n borderColor: 'rgb(96, 165, 250)',\n textColor: 'rgb(147, 197, 253)',\n },\n retro: {\n backgroundColor: 'rgba(239, 68, 68, 0.15)',\n borderColor: 'rgb(239, 68, 68)',\n textColor: 'rgb(239, 68, 68)',\n },\n cyberpunk: {\n backgroundColor: 'rgba(255, 221, 0, 0.18)',\n borderColor: 'rgb(255, 221, 0)',\n textColor: 'rgb(255, 221, 0)',\n },\n matrix: {\n backgroundColor: 'rgba(0, 255, 65, 0.15)',\n borderColor: 'rgb(0, 255, 65)',\n textColor: 'rgb(0, 255, 65)',\n },\n oceanblue: {\n backgroundColor: 'rgba(6, 95, 212, 0.18)',\n borderColor: 'rgb(6, 95, 212)',\n textColor: 'rgb(6, 95, 212)',\n },\n eyecare: {\n backgroundColor: 'rgba(34, 139, 34, 0.18)',\n borderColor: 'rgb(34, 139, 34)',\n textColor: 'rgb(34, 139, 34)',\n },\n ghibli: {\n backgroundColor: 'rgba(249, 115, 22, 0.18)',\n borderColor: 'rgb(249, 115, 22)',\n textColor: 'rgb(249, 115, 22)',\n },\n pinkgirl: {\n backgroundColor: 'rgba(236, 72, 153, 0.15)',\n borderColor: 'rgb(236, 72, 153)',\n textColor: 'rgb(236, 72, 153)',\n },\n mintgirl: {\n backgroundColor: 'rgba(52, 211, 153, 0.15)',\n borderColor: 'rgb(52, 211, 153)',\n textColor: 'rgb(52, 211, 153)',\n },\n\n wuxing: {\n backgroundColor: 'rgba(180, 120, 60, 0.15)',\n borderColor: 'rgb(180, 120, 60)',\n textColor: 'rgb(140, 90, 40)',\n },\n jukebox: {\n backgroundColor: 'rgba(147, 51, 234, 0.18)',\n borderColor: 'rgb(147, 51, 234)',\n textColor: 'rgb(167, 139, 250)',\n },\n};\n\n// 生成 Tree 组件的主题活跃状态 CSS\nexport const generateTreeActiveStyles = (): string => {\n return Object.entries(themeActiveStyles)\n .map(([theme, style]) => `\n /* ${theme.charAt(0).toUpperCase() + theme.slice(1)} 主题 */\n [data-theme=\"${theme}\"] .tree-node-content-active {\n background-color: ${style.backgroundColor} !important;\n border-left: 4px solid ${style.borderColor} !important;\n color: ${style.textColor} !important;\n }\n [data-theme=\"${theme}\"] .tree-node-content-active .tree-node-icon,\n [data-theme=\"${theme}\"] .tree-node-content-active .tree-node-label {\n color: ${style.textColor} !important;\n }`)\n .join('\\n');\n};\n\n// 生成 Sidebar 组件的主题活跃状态 CSS\nexport const generateSidebarActiveStyles = (): string => {\n return Object.entries(themeActiveStyles)\n .map(([theme, style]) => `\n /* ${theme.charAt(0).toUpperCase() + theme.slice(1)} 主题 */\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active {\n background-color: ${style.backgroundColor} !important;\n border-left: 4px solid ${style.borderColor} !important;\n }\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active .tree-node-label,\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active .tree-node-icon svg {\n color: ${style.textColor} !important;\n stroke: ${style.textColor} !important;\n }`)\n .join('\\n');\n};\n\n"],"mappings":";AAUA,
|
|
1
|
+
{"version":3,"file":"themeStyles.js","names":["themeActiveStyles","generateTreeActiveStyles","theme","style","generateSidebarActiveStyles"],"sources":["../../src/styles/themeStyles.ts"],"sourcesContent":["// 共用主题样式配置\n// 用于 Tree 组件和 Sidebar 组件的活跃状态样式\n\nexport interface ThemeActiveStyle {\n backgroundColor: string;\n borderColor: string;\n textColor: string;\n}\n\n// 主题配色映射\nexport const themeActiveStyles: Record<string, ThemeActiveStyle> = {\n light: {\n backgroundColor: 'var(--dishui-accent)',\n borderColor: 'var(--dishui-accent)',\n textColor: 'var(--dishui-accent-fg)',\n },\n dark: {\n backgroundColor: 'var(--dishui-accent)',\n borderColor: 'var(--dishui-accent)',\n textColor: 'var(--dishui-accent-fg)',\n },\n cursor: {\n backgroundColor: 'rgba(96, 165, 250, 0.16)',\n borderColor: 'rgb(96, 165, 250)',\n textColor: 'rgb(147, 197, 253)',\n },\n retro: {\n backgroundColor: 'rgba(239, 68, 68, 0.15)',\n borderColor: 'rgb(239, 68, 68)',\n textColor: 'rgb(239, 68, 68)',\n },\n cyberpunk: {\n backgroundColor: 'rgba(255, 221, 0, 0.18)',\n borderColor: 'rgb(255, 221, 0)',\n textColor: 'rgb(255, 221, 0)',\n },\n matrix: {\n backgroundColor: 'rgba(0, 255, 65, 0.15)',\n borderColor: 'rgb(0, 255, 65)',\n textColor: 'rgb(0, 255, 65)',\n },\n oceanblue: {\n backgroundColor: 'rgba(6, 95, 212, 0.18)',\n borderColor: 'rgb(6, 95, 212)',\n textColor: 'rgb(6, 95, 212)',\n },\n eyecare: {\n backgroundColor: 'rgba(34, 139, 34, 0.18)',\n borderColor: 'rgb(34, 139, 34)',\n textColor: 'rgb(34, 139, 34)',\n },\n ghibli: {\n backgroundColor: 'rgba(249, 115, 22, 0.18)',\n borderColor: 'rgb(249, 115, 22)',\n textColor: 'rgb(249, 115, 22)',\n },\n pinkgirl: {\n backgroundColor: 'rgba(236, 72, 153, 0.15)',\n borderColor: 'rgb(236, 72, 153)',\n textColor: 'rgb(236, 72, 153)',\n },\n mintgirl: {\n backgroundColor: 'rgba(52, 211, 153, 0.15)',\n borderColor: 'rgb(52, 211, 153)',\n textColor: 'rgb(52, 211, 153)',\n },\n\n wuxing: {\n backgroundColor: 'rgba(180, 120, 60, 0.15)',\n borderColor: 'rgb(180, 120, 60)',\n textColor: 'rgb(140, 90, 40)',\n },\n jukebox: {\n backgroundColor: 'rgba(147, 51, 234, 0.18)',\n borderColor: 'rgb(147, 51, 234)',\n textColor: 'rgb(167, 139, 250)',\n },\n};\n\n// 生成 Tree 组件的主题活跃状态 CSS\nexport const generateTreeActiveStyles = (): string => {\n return Object.entries(themeActiveStyles)\n .map(([theme, style]) => `\n /* ${theme.charAt(0).toUpperCase() + theme.slice(1)} 主题 */\n [data-theme=\"${theme}\"] .tree-node-content-active {\n background-color: ${style.backgroundColor} !important;\n border-left: 4px solid ${style.borderColor} !important;\n color: ${style.textColor} !important;\n }\n [data-theme=\"${theme}\"] .tree-node-content-active .tree-node-icon,\n [data-theme=\"${theme}\"] .tree-node-content-active .tree-node-label {\n color: ${style.textColor} !important;\n }`)\n .join('\\n');\n};\n\n// 生成 Sidebar 组件的主题活跃状态 CSS\nexport const generateSidebarActiveStyles = (): string => {\n return Object.entries(themeActiveStyles)\n .map(([theme, style]) => `\n /* ${theme.charAt(0).toUpperCase() + theme.slice(1)} 主题 */\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active {\n background-color: ${style.backgroundColor} !important;\n border-left: 4px solid ${style.borderColor} !important;\n }\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active .tree-node-label,\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active .tree-node-icon svg {\n color: ${style.textColor} !important;\n stroke: ${style.textColor} !important;\n }`)\n .join('\\n');\n};\n\n"],"mappings":";AAUA,IAAaA,IAAsD;CACjE,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,MAAM;EACJ,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,WAAW;EACT,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,WAAW;EACT,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,SAAS;EACP,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,UAAU;EACR,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,UAAU;EACR,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CAEA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,SAAS;EACP,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;AACF,GAGaC,UACJ,OAAO,QAAQD,CAAiB,CAAC,CACrC,KAAK,CAACE,GAAOC,OAAW;aAChBD,EAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAM,MAAM,CAAC,EAAE;uBACrCA,EAAM;8BACCC,EAAM,gBAAgB;mCACjBA,EAAM,YAAY;mBAClCA,EAAM,UAAU;;uBAEZD,EAAM;uBACNA,EAAM;mBACVC,EAAM,UAAU;UACzB,CAAC,CACN,KAAK,IAAI,GAIDC,UACJ,OAAO,QAAQJ,CAAiB,CAAC,CACrC,KAAK,CAACE,GAAOC,OAAW;aAChBD,EAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAM,MAAM,CAAC,EAAE;uBACrCA,EAAM;8BACCC,EAAM,gBAAgB;mCACjBA,EAAM,YAAY;;uBAE9BD,EAAM;uBACNA,EAAM;mBACVC,EAAM,UAAU;oBACfA,EAAM,UAAU;UAC1B,CAAC,CACN,KAAK,IAAI"}
|
package/dist/utils/cn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cn.js","names":[],"sources":["../../src/utils/cn.ts"],"sourcesContent":["/**\n * cn - 轻量级 className 合并工具(零依赖)。\n *\n * 统一替代代码库中散落的 `[a, b, c].filter(Boolean).join(' ')` 写法。\n * 支持字符串、数字、数组以及对象(`{ 'foo': cond }`)形式的条件类名。\n *\n * @example\n * cn('btn', isActive && 'btn-active', { 'btn-lg': large })\n * // => 'btn btn-active btn-lg'\n */\nexport type ClassValue =\n | string\n | number\n | null\n | undefined\n | false\n | ClassValue[]\n | Record<string, boolean | null | undefined>;\n\nexport function cn(...inputs: ClassValue[]): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === 'string' || typeof input === 'number') {\n classes.push(String(input));\n } else if (Array.isArray(input)) {\n const nested = cn(...input);\n if (nested) classes.push(nested);\n } else if (typeof input === 'object') {\n for (const key in input) {\n if (input[key]) classes.push(key);\n }\n }\n }\n\n return classes.join(' ');\n}\n\nexport default cn;\n"],"mappings":";AAmBA,
|
|
1
|
+
{"version":3,"file":"cn.js","names":["cn","inputs","classes","input","nested","key"],"sources":["../../src/utils/cn.ts"],"sourcesContent":["/**\n * cn - 轻量级 className 合并工具(零依赖)。\n *\n * 统一替代代码库中散落的 `[a, b, c].filter(Boolean).join(' ')` 写法。\n * 支持字符串、数字、数组以及对象(`{ 'foo': cond }`)形式的条件类名。\n *\n * @example\n * cn('btn', isActive && 'btn-active', { 'btn-lg': large })\n * // => 'btn btn-active btn-lg'\n */\nexport type ClassValue =\n | string\n | number\n | null\n | undefined\n | false\n | ClassValue[]\n | Record<string, boolean | null | undefined>;\n\nexport function cn(...inputs: ClassValue[]): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === 'string' || typeof input === 'number') {\n classes.push(String(input));\n } else if (Array.isArray(input)) {\n const nested = cn(...input);\n if (nested) classes.push(nested);\n } else if (typeof input === 'object') {\n for (const key in input) {\n if (input[key]) classes.push(key);\n }\n }\n }\n\n return classes.join(' ');\n}\n\nexport default cn;\n"],"mappings":";AAmBA,SAAgBA,EAAG,GAAGC,GAA8B;CAClD,IAAMC,IAAoB,CAAC;CAE3B,KAAK,IAAMC,KAASF,GAClB,IAAKE,GAEL;MAAI,OAAOA,KAAU,YAAY,OAAOA,KAAU,UAChD,EAAQ,KAAK,OAAOA,CAAK,CAAC;OACrB,IAAI,MAAM,QAAQA,CAAK,GAAG;GAC/B,IAAMC,IAASJ,EAAG,GAAGG,CAAK;GAC1B,AAAIC,KAAQF,EAAQ,KAAKE,CAAM;EACjC,OAAO,IAAI,OAAOD,KAAU,UACrB,KAAA,IAAME,KAAOF,GAChB,AAAIA,EAAME,MAAMH,EAAQ,KAAKG,CAAG;CAClC;CAIJ,OAAOH,EAAQ,KAAK,GAAG;AACzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flexLayout.js","names":[],"sources":["../../src/utils/flexLayout.ts"],"sourcesContent":["export type FlexAlign = 'start' | 'center' | 'end' | 'baseline' | 'stretch';\nexport type FlexJustify = 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';\n\nexport const FLEX_ALIGN_CLASS: Record<FlexAlign, string> = {\n start: 'items-start',\n center: 'items-center',\n end: 'items-end',\n baseline: 'items-baseline',\n stretch: 'items-stretch',\n};\n\nexport const FLEX_JUSTIFY_CLASS: Record<FlexJustify, string> = {\n start: 'justify-start',\n center: 'justify-center',\n end: 'justify-end',\n between: 'justify-between',\n around: 'justify-around',\n evenly: 'justify-evenly',\n};\n\nexport const flexGap = (value: number | string | undefined): string | undefined =>\n typeof value === 'number' ? `${value}px` : value;\n"],"mappings":";AAGA,
|
|
1
|
+
{"version":3,"file":"flexLayout.js","names":["FLEX_ALIGN_CLASS","FLEX_JUSTIFY_CLASS","flexGap","value"],"sources":["../../src/utils/flexLayout.ts"],"sourcesContent":["export type FlexAlign = 'start' | 'center' | 'end' | 'baseline' | 'stretch';\nexport type FlexJustify = 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';\n\nexport const FLEX_ALIGN_CLASS: Record<FlexAlign, string> = {\n start: 'items-start',\n center: 'items-center',\n end: 'items-end',\n baseline: 'items-baseline',\n stretch: 'items-stretch',\n};\n\nexport const FLEX_JUSTIFY_CLASS: Record<FlexJustify, string> = {\n start: 'justify-start',\n center: 'justify-center',\n end: 'justify-end',\n between: 'justify-between',\n around: 'justify-around',\n evenly: 'justify-evenly',\n};\n\nexport const flexGap = (value: number | string | undefined): string | undefined =>\n typeof value === 'number' ? `${value}px` : value;\n"],"mappings":";AAGA,IAAaA,IAA8C;CACzD,OAAO;CACP,QAAQ;CACR,KAAK;CACL,UAAU;CACV,SAAS;AACX,GAEaC,IAAkD;CAC7D,OAAO;CACP,QAAQ;CACR,KAAK;CACL,SAAS;CACT,QAAQ;CACR,QAAQ;AACV,GAEaC,KAAW,MACtB,OAAOC,KAAU,WAAW,GAAGA,EAAM,MAAMA"}
|