dishui 0.0.106 → 0.0.110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/AIRewrite.js +109 -88
- 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 +133 -132
- 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.d.ts +2 -0
- 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":"index.js","names":[],"sources":["../../../src/components/Accordion/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type AccordionItemType = {\n /** 唯一标识(用于展开状态管理)。 */\n key: string;\n /** 标题。 */\n title: React.ReactNode;\n /** 展开区域内容。 */\n content: React.ReactNode;\n /** 标题左侧图标。 */\n icon?: React.ReactNode;\n /** 标题行右侧、展开指示器之前的附加内容。 */\n extra?: React.ReactNode;\n /** 禁用该项。 */\n disabled?: boolean;\n};\n\nexport type AccordionProps = {\n /** 手风琴项(数据驱动,可动态增删)。 */\n items: AccordionItemType[];\n /** 受控:当前展开项的 key 列表。 */\n openKeys?: string[];\n /** 非受控:默认展开项的 key 列表。 */\n defaultOpenKeys?: string[];\n /** 是否允许同时展开多项;默认 false(互斥展开,展开新项时收起其它项)。 */\n multiple?: boolean;\n /** 展开状态变化回调。 */\n onChange?: (openKeys: string[]) => void;\n /** 是否显示右侧展开指示箭头,默认 true。 */\n indicator?: boolean;\n /** 是否显示外层边框,默认 true。 */\n bordered?: boolean;\n className?: string;\n};\n\nconst ChevronGlyph: React.FC<{ className?: string }> = ({ className }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n\n/**\n * Accordion —— 手风琴组件:动态交互式的聚合展开列表。\n * 数据驱动(items 可动态增删),支持受控 / 非受控、互斥或多开、\n * 禁用项、图标与自定义内容,展开 / 收起带平滑过渡动画。\n */\nconst Accordion: React.FC<AccordionProps> = ({\n items,\n openKeys,\n defaultOpenKeys = [],\n multiple = false,\n onChange,\n indicator = true,\n bordered = true,\n className = '',\n}) => {\n const [innerKeys, setInnerKeys] = React.useState<string[]>(defaultOpenKeys);\n const isControlled = openKeys !== undefined;\n const currentKeys = isControlled ? (openKeys ?? []) : innerKeys;\n\n const toggle = (key: string, disabled?: boolean) => {\n if (disabled) return;\n const nextKeys = currentKeys.includes(key)\n ? currentKeys.filter((k) => k !== key)\n : multiple\n ? [...currentKeys, key]\n : [key];\n if (!isControlled) setInnerKeys(nextKeys);\n onChange?.(nextKeys);\n };\n\n return (\n <div\n className={cn(\n 'dishui-accordion w-full divide-y divide-base-300 overflow-hidden bg-base-100 text-body leading-5 text-base-content',\n bordered && 'rounded-lg border border-base-300',\n className,\n )}\n >\n {items.map((item) => {\n const open = currentKeys.includes(item.key);\n return (\n <div key={item.key} className={cn(open && !item.disabled && 'bg-base-200/40')}>\n <button\n type=\"button\"\n disabled={item.disabled}\n aria-expanded={open}\n onClick={() => toggle(item.key, item.disabled)}\n className={cn(\n 'flex min-h-10 w-full items-center gap-2 px-4 py-2 text-left text-body font-medium transition-colors duration-150 motion-reduce:transition-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-current',\n item.disabled\n ? 'cursor-not-allowed opacity-50'\n : 'cursor-pointer hover:bg-base-200/60',\n open && !item.disabled && 'text-base-content',\n )}\n >\n {item.icon && <span className=\"flex shrink-0 items-center text-base-content/70 [&>svg]:h-4 [&>svg]:w-4\">{item.icon}</span>}\n <span className=\"min-w-0 flex-1 truncate\">{item.title}</span>\n {item.extra && <span className=\"flex shrink-0 items-center\">{item.extra}</span>}\n {indicator && (\n <span className={cn('shrink-0 text-base-content/70 transition-transform duration-200 motion-reduce:transition-none', open && 'rotate-180')}>\n <ChevronGlyph />\n </span>\n )}\n </button>\n <div\n className=\"grid transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none\"\n style={{ gridTemplateRows: open ? '1fr' : '0fr' }}\n >\n <div className=\"overflow-hidden\">\n <div className=\"px-4 pb-3 pt-1 text-body leading-5 text-base-content/70\">\n {item.content}\n </div>\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n};\n\nexport default Accordion;\n"],"mappings":";;;;AAoCA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["React","ChevronGlyph","cn","className","Accordion","innerKeys","setInnerKeys","defaultOpenKeys","isControlled","openKeys","currentKeys","toggle","disabled","nextKeys","key","k","multiple","onChange","bordered","items","open","item","indicator"],"sources":["../../../src/components/Accordion/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type AccordionItemType = {\n /** 唯一标识(用于展开状态管理)。 */\n key: string;\n /** 标题。 */\n title: React.ReactNode;\n /** 展开区域内容。 */\n content: React.ReactNode;\n /** 标题左侧图标。 */\n icon?: React.ReactNode;\n /** 标题行右侧、展开指示器之前的附加内容。 */\n extra?: React.ReactNode;\n /** 禁用该项。 */\n disabled?: boolean;\n};\n\nexport type AccordionProps = {\n /** 手风琴项(数据驱动,可动态增删)。 */\n items: AccordionItemType[];\n /** 受控:当前展开项的 key 列表。 */\n openKeys?: string[];\n /** 非受控:默认展开项的 key 列表。 */\n defaultOpenKeys?: string[];\n /** 是否允许同时展开多项;默认 false(互斥展开,展开新项时收起其它项)。 */\n multiple?: boolean;\n /** 展开状态变化回调。 */\n onChange?: (openKeys: string[]) => void;\n /** 是否显示右侧展开指示箭头,默认 true。 */\n indicator?: boolean;\n /** 是否显示外层边框,默认 true。 */\n bordered?: boolean;\n className?: string;\n};\n\nconst ChevronGlyph: React.FC<{ className?: string }> = ({ className }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n\n/**\n * Accordion —— 手风琴组件:动态交互式的聚合展开列表。\n * 数据驱动(items 可动态增删),支持受控 / 非受控、互斥或多开、\n * 禁用项、图标与自定义内容,展开 / 收起带平滑过渡动画。\n */\nconst Accordion: React.FC<AccordionProps> = ({\n items,\n openKeys,\n defaultOpenKeys = [],\n multiple = false,\n onChange,\n indicator = true,\n bordered = true,\n className = '',\n}) => {\n const [innerKeys, setInnerKeys] = React.useState<string[]>(defaultOpenKeys);\n const isControlled = openKeys !== undefined;\n const currentKeys = isControlled ? (openKeys ?? []) : innerKeys;\n\n const toggle = (key: string, disabled?: boolean) => {\n if (disabled) return;\n const nextKeys = currentKeys.includes(key)\n ? currentKeys.filter((k) => k !== key)\n : multiple\n ? [...currentKeys, key]\n : [key];\n if (!isControlled) setInnerKeys(nextKeys);\n onChange?.(nextKeys);\n };\n\n return (\n <div\n className={cn(\n 'dishui-accordion w-full divide-y divide-base-300 overflow-hidden bg-base-100 text-body leading-5 text-base-content',\n bordered && 'rounded-lg border border-base-300',\n className,\n )}\n >\n {items.map((item) => {\n const open = currentKeys.includes(item.key);\n return (\n <div key={item.key} className={cn(open && !item.disabled && 'bg-base-200/40')}>\n <button\n type=\"button\"\n disabled={item.disabled}\n aria-expanded={open}\n onClick={() => toggle(item.key, item.disabled)}\n className={cn(\n 'flex min-h-10 w-full items-center gap-2 px-4 py-2 text-left text-body font-medium transition-colors duration-150 motion-reduce:transition-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-current',\n item.disabled\n ? 'cursor-not-allowed opacity-50'\n : 'cursor-pointer hover:bg-base-200/60',\n open && !item.disabled && 'text-base-content',\n )}\n >\n {item.icon && <span className=\"flex shrink-0 items-center text-base-content/70 [&>svg]:h-4 [&>svg]:w-4\">{item.icon}</span>}\n <span className=\"min-w-0 flex-1 truncate\">{item.title}</span>\n {item.extra && <span className=\"flex shrink-0 items-center\">{item.extra}</span>}\n {indicator && (\n <span className={cn('shrink-0 text-base-content/70 transition-transform duration-200 motion-reduce:transition-none', open && 'rotate-180')}>\n <ChevronGlyph />\n </span>\n )}\n </button>\n <div\n className=\"grid transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none\"\n style={{ gridTemplateRows: open ? '1fr' : '0fr' }}\n >\n <div className=\"overflow-hidden\">\n <div className=\"px-4 pb-3 pt-1 text-body leading-5 text-base-content/70\">\n {item.content}\n </div>\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n};\n\nexport default Accordion;\n"],"mappings":";;;;AAoCA,IAAMC,KAAkD,EAAE,mBACxD,kBAAC,OAAD;CACE,OAAM;CACN,SAAQ;CACR,MAAK;CACL,QAAO;CACP,aAAa;CACb,eAAc;CACd,gBAAe;CACf,WAAWC,EAAG,WAAWC,CAAS;CAClC,eAAY;CAEZ,UAAA,kBAAC,QAAD,EAAM,GAAE,eAAgB,CAAA;AACrB,CAAA,GAQDC,KAAuC,EAC3C,UACA,aACA,qBAAkB,CAAC,GACnB,cAAW,IACX,aACA,eAAY,IACZ,cAAW,IACX,eAAY,SACR;CACJ,IAAM,CAACC,GAAWC,KAAgBN,EAAM,SAAmBO,CAAe,GACpEC,IAAeC,MAAa,KAAA,GAC5BC,IAAcF,IAAgBC,KAAY,CAAC,IAAKJ,GAEhDM,KAAU,GAAa,MAAuB;EAClD,IAAIC,GAAU;EACd,IAAMC,IAAWH,EAAY,SAASI,CAAG,IACrCJ,EAAY,QAAQ,MAAMK,MAAMD,CAAG,IACnCE,IACE,CAAC,GAAGN,GAAaI,CAAG,IACpB,CAACA,CAAG;EAEV,AADKN,KAAcF,EAAaO,CAAQ,GACxCI,IAAWJ,CAAQ;CACrB;CAEA,OACE,kBAAC,OAAD;EACE,WAAWX,EACT,sHACAgB,KAAY,qCACZf,CACF;EAEC,UAAAgB,EAAM,KAAK,MAAS;GACnB,IAAMC,IAAOV,EAAY,SAASW,EAAK,GAAG;GAC1C,OACE,kBAAC,OAAD;IAAoB,WAAWnB,EAAGkB,KAAQ,CAACC,EAAK,YAAY,gBAAgB;IAA5E,UAAA,CACE,kBAAC,UAAD;KACE,MAAK;KACL,UAAUA,EAAK;KACf,iBAAeD;KACf,eAAeT,EAAOU,EAAK,KAAKA,EAAK,QAAQ;KAC7C,WAAWnB,EACT,wOACAmB,EAAK,WACD,kCACA,uCACJD,KAAQ,CAACC,EAAK,YAAY,mBAC5B;KAXF,UAAA;MAaGA,EAAK,QAAQ,kBAAC,QAAD;OAAM,WAAU;OAA2E,UAAAA,EAAK;MAAW,CAAA;MACzH,kBAAC,QAAD;OAAM,WAAU;OAA2B,UAAAA,EAAK;MAAY,CAAA;MAC3DA,EAAK,SAAS,kBAAC,QAAD;OAAM,WAAU;OAA8B,UAAAA,EAAK;MAAY,CAAA;MAC7EC,KACC,kBAAC,QAAD;OAAM,WAAWpB,EAAG,iGAAiGkB,KAAQ,YAAY;OACvI,UAAA,kBAACnB,GAAD,CAAe,CAAA;MACX,CAAA;KAEF;IACR,CAAA,GAAA,kBAAC,OAAD;KACE,WAAU;KACV,OAAO,EAAE,kBAAkBmB,IAAO,QAAQ,MAAM;KAEhD,UAAA,kBAAC,OAAD;MAAK,WAAU;MACb,UAAA,kBAAC,OAAD;OAAK,WAAU;OACZ,UAAAC,EAAK;MACH,CAAA;KACF,CAAA;IACF,CAAA,CACF;GAjCK,GAAAA,EAAK,GAiCV;EAET,CAAC;CACE,CAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Avatar/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type AvatarShape = 'circle' | 'square' | 'squircle';\nexport type AvatarBorderStyle = 'solid' | 'dashed' | 'dotted';\nexport type AvatarNotificationPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n\nexport type AvatarProps = {\n /** 头像图片地址;缺省或加载失败时回退为 `name` 的关键字母。 */\n src?: string;\n /** 图片 alt 描述。 */\n alt?: string;\n /** 名称 / 描述:未配置头像时取其关键字母(两个单词取首字母,否则取前两个字符)作为回退展示。 */\n name?: string;\n /** 方形尺寸;数字按 px 处理。默认 40。 */\n size?: number | string;\n /** 边框(整体)形态:circle 圆形(默认)/ square 方形 / squircle 超椭圆圆角方。 */\n shape?: AvatarShape;\n /** shape=\"square\" 时的自定义圆角(数字按 px)。 */\n radius?: number | string;\n /** 边框宽度(数字按 px);默认 0,旧 maskBorder 模式默认 2。不改变 maskSrc 图片。 */\n borderWidth?: number | string;\n /** 边框颜色。 */\n borderColor?: string;\n /** 边框线型:solid(默认)/ dashed / dotted。 */\n borderStyle?: AvatarBorderStyle;\n /** 装饰图片 URL(SVG / PNG / WebP 等,需自带透明中心),按 contain 覆盖头像;不受 shape 裁剪。优先于 maskBorder,失败时隐藏装饰。 */\n maskSrc?: string;\n /** @deprecated 仅兼容旧 CSS 颜色 / 渐变环,并非图片 mask。图片覆盖请使用 maskSrc;两者同时传入时忽略 maskBorder。 */\n maskBorder?: string;\n /** 头像图片 / 字母内容透明度 0–1,默认 1;不影响装饰图片或通知角标。 */\n centerOpacity?: number;\n /** 角标通知位置,默认 top-right。 */\n notificationPosition?: AvatarNotificationPosition;\n /** 角标通知内容(如计数数值 / 短文本);传 `true` 显示小圆点,不传则不渲染角标。 */\n notification?: React.ReactNode;\n /** 角标背景色,默认 var(--color-error)。 */\n notificationColor?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Inline styles on the wrapper. */\n style?: React.CSSProperties;\n /** Click handler. */\n onClick?: (e: React.MouseEvent<HTMLSpanElement>) => void;\n};\n\n/** 从名称/描述中提取关键字母:两个单词取首字母,否则取前两个字符(统一大写)。 */\nconst initialsOf = (name: string): string => {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase();\n return name.trim().slice(0, 2).toUpperCase();\n};\n\nconst SHAPE_CLASS: Record<AvatarShape, string> = {\n circle: 'rounded-full',\n square: '',\n squircle: 'mask mask-squircle',\n};\n\nconst NOTIFICATION_POSITION_CLASS: Record<AvatarNotificationPosition, string> = {\n 'top-left': 'top-0 left-0 -translate-x-1/3 -translate-y-1/3',\n 'top-right': 'top-0 right-0 translate-x-1/3 -translate-y-1/3',\n 'bottom-left': 'bottom-0 left-0 -translate-x-1/3 translate-y-1/3',\n 'bottom-right': 'bottom-0 right-0 translate-x-1/3 translate-y-1/3',\n};\n\n/**\n * Avatar —— 头像组件。\n * 展示图片头像;未配置(或加载失败)时回退为 `name` 的关键字母。\n * 支持自定义边框形态 / 颜色 / 线型、透明中心装饰图片 overlay(maskSrc)\n * 以及四角 notification 短描述(计数 / 文本 / 圆点)。\n */\nconst Avatar: React.FC<AvatarProps> = ({\n src,\n alt,\n name,\n size = 40,\n shape = 'circle',\n radius,\n borderWidth,\n borderColor,\n borderStyle = 'solid',\n maskBorder,\n maskSrc,\n centerOpacity = 1,\n notificationPosition = 'top-right',\n notification,\n notificationColor = 'var(--color-error)',\n className = '',\n style,\n onClick,\n}) => {\n const px = typeof size === 'number' ? `${size}px` : size;\n const [imgFailed, setImgFailed] = React.useState(false);\n React.useEffect(() => setImgFailed(false), [src]);\n\n const showImage = Boolean(src) && !imgFailed;\n const initials = name ? initialsOf(name) : '';\n const fontSize = `calc(${px} * 0.36)`;\n\n const shapeStyle: React.CSSProperties = shape === 'square' ? { borderRadius: radius ?? '0.5rem' } : {};\n const legacyMaskBorder = maskSrc ? undefined : maskBorder;\n const ringWidth = borderWidth === undefined ? (legacyMaskBorder ? '2px' : '0px') : typeof borderWidth === 'number' ? `${borderWidth}px` : borderWidth;\n\n const showNotification = notification !== undefined && notification !== null && notification !== false;\n\n return (\n <span\n className={cn('relative inline-flex shrink-0 leading-none', onClick && 'cursor-pointer', className)}\n style={{ width: px, height: px, ...style }}\n onClick={onClick}\n >\n {/* 仅保留旧版 CSS 环兼容;图片 overlay 不使用 CSS mask。 */}\n {legacyMaskBorder && (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-0 z-10\"\n style={{\n padding: ringWidth,\n background: legacyMaskBorder,\n WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',\n WebkitMaskComposite: 'xor',\n mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',\n maskComposite: 'exclude',\n ...shapeStyle,\n } as React.CSSProperties}\n />\n )}\n <span\n className={cn(\n 'relative flex h-full w-full select-none items-center justify-center overflow-hidden bg-base-200 text-center font-semibold text-base-content/70',\n SHAPE_CLASS[shape],\n )}\n style={{\n fontSize,\n opacity: centerOpacity,\n borderWidth: legacyMaskBorder ? 0 : ringWidth,\n borderStyle: legacyMaskBorder ? undefined : borderStyle,\n borderColor: legacyMaskBorder ? undefined : borderColor,\n ...shapeStyle,\n }}\n >\n {showImage ? (\n <img\n src={src}\n alt={alt ?? name ?? ''}\n className=\"h-full w-full object-cover\"\n onError={() => setImgFailed(true)}\n />\n ) : (\n initials\n )}\n </span>\n {maskSrc && <AvatarMaskImage key={maskSrc} src={maskSrc} />}\n {showNotification && (\n <span\n className={cn(\n 'absolute z-20 flex items-center justify-center rounded-full border-2 border-base-100 font-bold leading-none text-white',\n NOTIFICATION_POSITION_CLASS[notificationPosition],\n notification === true ? 'h-3 w-3 p-0' : 'h-[18px] min-w-[18px] px-1 text-[10px]',\n )}\n style={{ backgroundColor: notificationColor }}\n >\n {notification === true ? '' : notification}\n </span>\n )}\n </span>\n );\n};\n\n// A new URL remounts this layer so a failed decoration can recover independently.\nconst AvatarMaskImage: React.FC<{ src: string }> = ({ src }) => {\n const [failed, setFailed] = React.useState(false);\n if (failed) return null;\n return (\n <img\n src={src}\n alt=\"\"\n aria-hidden=\"true\"\n draggable={false}\n className=\"pointer-events-none absolute inset-0 z-10 h-full w-full select-none object-contain\"\n onError={() => setFailed(true)}\n />\n );\n};\n\nexport default Avatar;\n"],"mappings":";;;;AA+CA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["React","initialsOf","parts","name","SHAPE_CLASS","NOTIFICATION_POSITION_CLASS","Avatar","px","size","imgFailed","setImgFailed","src","showImage","initials","fontSize","shapeStyle","shape","radius","legacyMaskBorder","maskSrc","maskBorder","ringWidth","borderWidth","showNotification","notification","cn","onClick","className","style","centerOpacity","borderStyle","borderColor","alt","AvatarMaskImage","notificationPosition","notificationColor","failed","setFailed"],"sources":["../../../src/components/Avatar/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type AvatarShape = 'circle' | 'square' | 'squircle';\nexport type AvatarBorderStyle = 'solid' | 'dashed' | 'dotted';\nexport type AvatarNotificationPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n\nexport type AvatarProps = {\n /** 头像图片地址;缺省或加载失败时回退为 `name` 的关键字母。 */\n src?: string;\n /** 图片 alt 描述。 */\n alt?: string;\n /** 名称 / 描述:未配置头像时取其关键字母(两个单词取首字母,否则取前两个字符)作为回退展示。 */\n name?: string;\n /** 方形尺寸;数字按 px 处理。默认 40。 */\n size?: number | string;\n /** 边框(整体)形态:circle 圆形(默认)/ square 方形 / squircle 超椭圆圆角方。 */\n shape?: AvatarShape;\n /** shape=\"square\" 时的自定义圆角(数字按 px)。 */\n radius?: number | string;\n /** 边框宽度(数字按 px);默认 0,旧 maskBorder 模式默认 2。不改变 maskSrc 图片。 */\n borderWidth?: number | string;\n /** 边框颜色。 */\n borderColor?: string;\n /** 边框线型:solid(默认)/ dashed / dotted。 */\n borderStyle?: AvatarBorderStyle;\n /** 装饰图片 URL(SVG / PNG / WebP 等,需自带透明中心),按 contain 覆盖头像;不受 shape 裁剪。优先于 maskBorder,失败时隐藏装饰。 */\n maskSrc?: string;\n /** @deprecated 仅兼容旧 CSS 颜色 / 渐变环,并非图片 mask。图片覆盖请使用 maskSrc;两者同时传入时忽略 maskBorder。 */\n maskBorder?: string;\n /** 头像图片 / 字母内容透明度 0–1,默认 1;不影响装饰图片或通知角标。 */\n centerOpacity?: number;\n /** 角标通知位置,默认 top-right。 */\n notificationPosition?: AvatarNotificationPosition;\n /** 角标通知内容(如计数数值 / 短文本);传 `true` 显示小圆点,不传则不渲染角标。 */\n notification?: React.ReactNode;\n /** 角标背景色,默认 var(--color-error)。 */\n notificationColor?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Inline styles on the wrapper. */\n style?: React.CSSProperties;\n /** Click handler. */\n onClick?: (e: React.MouseEvent<HTMLSpanElement>) => void;\n};\n\n/** 从名称/描述中提取关键字母:两个单词取首字母,否则取前两个字符(统一大写)。 */\nconst initialsOf = (name: string): string => {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase();\n return name.trim().slice(0, 2).toUpperCase();\n};\n\nconst SHAPE_CLASS: Record<AvatarShape, string> = {\n circle: 'rounded-full',\n square: '',\n squircle: 'mask mask-squircle',\n};\n\nconst NOTIFICATION_POSITION_CLASS: Record<AvatarNotificationPosition, string> = {\n 'top-left': 'top-0 left-0 -translate-x-1/3 -translate-y-1/3',\n 'top-right': 'top-0 right-0 translate-x-1/3 -translate-y-1/3',\n 'bottom-left': 'bottom-0 left-0 -translate-x-1/3 translate-y-1/3',\n 'bottom-right': 'bottom-0 right-0 translate-x-1/3 translate-y-1/3',\n};\n\n/**\n * Avatar —— 头像组件。\n * 展示图片头像;未配置(或加载失败)时回退为 `name` 的关键字母。\n * 支持自定义边框形态 / 颜色 / 线型、透明中心装饰图片 overlay(maskSrc)\n * 以及四角 notification 短描述(计数 / 文本 / 圆点)。\n */\nconst Avatar: React.FC<AvatarProps> = ({\n src,\n alt,\n name,\n size = 40,\n shape = 'circle',\n radius,\n borderWidth,\n borderColor,\n borderStyle = 'solid',\n maskBorder,\n maskSrc,\n centerOpacity = 1,\n notificationPosition = 'top-right',\n notification,\n notificationColor = 'var(--color-error)',\n className = '',\n style,\n onClick,\n}) => {\n const px = typeof size === 'number' ? `${size}px` : size;\n const [imgFailed, setImgFailed] = React.useState(false);\n React.useEffect(() => setImgFailed(false), [src]);\n\n const showImage = Boolean(src) && !imgFailed;\n const initials = name ? initialsOf(name) : '';\n const fontSize = `calc(${px} * 0.36)`;\n\n const shapeStyle: React.CSSProperties = shape === 'square' ? { borderRadius: radius ?? '0.5rem' } : {};\n const legacyMaskBorder = maskSrc ? undefined : maskBorder;\n const ringWidth = borderWidth === undefined ? (legacyMaskBorder ? '2px' : '0px') : typeof borderWidth === 'number' ? `${borderWidth}px` : borderWidth;\n\n const showNotification = notification !== undefined && notification !== null && notification !== false;\n\n return (\n <span\n className={cn('relative inline-flex shrink-0 leading-none', onClick && 'cursor-pointer', className)}\n style={{ width: px, height: px, ...style }}\n onClick={onClick}\n >\n {/* 仅保留旧版 CSS 环兼容;图片 overlay 不使用 CSS mask。 */}\n {legacyMaskBorder && (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-0 z-10\"\n style={{\n padding: ringWidth,\n background: legacyMaskBorder,\n WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',\n WebkitMaskComposite: 'xor',\n mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',\n maskComposite: 'exclude',\n ...shapeStyle,\n } as React.CSSProperties}\n />\n )}\n <span\n className={cn(\n 'relative flex h-full w-full select-none items-center justify-center overflow-hidden bg-base-200 text-center font-semibold text-base-content/70',\n SHAPE_CLASS[shape],\n )}\n style={{\n fontSize,\n opacity: centerOpacity,\n borderWidth: legacyMaskBorder ? 0 : ringWidth,\n borderStyle: legacyMaskBorder ? undefined : borderStyle,\n borderColor: legacyMaskBorder ? undefined : borderColor,\n ...shapeStyle,\n }}\n >\n {showImage ? (\n <img\n src={src}\n alt={alt ?? name ?? ''}\n className=\"h-full w-full object-cover\"\n onError={() => setImgFailed(true)}\n />\n ) : (\n initials\n )}\n </span>\n {maskSrc && <AvatarMaskImage key={maskSrc} src={maskSrc} />}\n {showNotification && (\n <span\n className={cn(\n 'absolute z-20 flex items-center justify-center rounded-full border-2 border-base-100 font-bold leading-none text-white',\n NOTIFICATION_POSITION_CLASS[notificationPosition],\n notification === true ? 'h-3 w-3 p-0' : 'h-[18px] min-w-[18px] px-1 text-[10px]',\n )}\n style={{ backgroundColor: notificationColor }}\n >\n {notification === true ? '' : notification}\n </span>\n )}\n </span>\n );\n};\n\n// A new URL remounts this layer so a failed decoration can recover independently.\nconst AvatarMaskImage: React.FC<{ src: string }> = ({ src }) => {\n const [failed, setFailed] = React.useState(false);\n if (failed) return null;\n return (\n <img\n src={src}\n alt=\"\"\n aria-hidden=\"true\"\n draggable={false}\n className=\"pointer-events-none absolute inset-0 z-10 h-full w-full select-none object-contain\"\n onError={() => setFailed(true)}\n />\n );\n};\n\nexport default Avatar;\n"],"mappings":";;;;AA+CA,IAAMC,KAAc,MAAyB;CAC3C,IAAMC,IAAQC,EAAK,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CAErD,OADID,EAAM,UAAU,KAAWA,EAAM,EAAE,CAAC,KAAKA,EAAM,EAAE,CAAC,GAAA,CAAI,YAAY,IAC/DC,EAAK,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY;AAC7C,GAEMC,IAA2C;CAC/C,QAAQ;CACR,QAAQ;CACR,UAAU;AACZ,GAEMC,IAA0E;CAC9E,YAAY;CACZ,aAAa;CACb,eAAe;CACf,gBAAgB;AAClB,GAQMC,KAAiC,EACrC,QACA,QACA,SACA,UAAO,IACP,WAAQ,UACR,WACA,gBACA,gBACA,iBAAc,SACd,eACA,YACA,mBAAgB,GAChB,0BAAuB,aACvB,iBACA,uBAAoB,sBACpB,eAAY,IACZ,UACA,iBACI;CACJ,IAAMC,IAAK,OAAOC,KAAS,WAAW,GAAGA,EAAK,MAAMA,GAC9C,CAACC,GAAWC,KAAgBV,EAAM,SAAS,EAAK;CACtD,EAAM,gBAAgBU,EAAa,EAAK,GAAG,CAACC,CAAG,CAAC;CAEhD,IAAMC,IAAY,EAAQD,KAAQ,CAACF,GAC7BI,IAAWV,IAAOF,EAAWE,CAAI,IAAI,IACrCW,IAAW,QAAQP,EAAG,WAEtBQ,IAAkCC,MAAU,WAAW,EAAE,cAAcC,KAAU,SAAS,IAAI,CAAC,GAC/FC,IAAmBC,IAAU,KAAA,IAAYC,GACzCC,IAAYC,MAAgB,KAAA,IAAaJ,IAAmB,QAAQ,QAAS,OAAOI,KAAgB,WAAW,GAAGA,EAAY,MAAMA,GAEpIC,IAAmBC,KAA+C,QAAQA,MAAiB;CAEjG,OACE,kBAAC,QAAD;EACE,WAAWC,EAAG,8CAA8CC,KAAW,kBAAkBC,CAAS;EAClG,OAAO;GAAE,OAAOpB;GAAI,QAAQA;GAAI,GAAGqB;EAAM;EAChC;EAHX,UAAA;GAMGV,KACC,kBAAC,QAAD;IACE,eAAY;IACZ,WAAU;IACV,OAAO;KACL,SAASG;KACT,YAAYH;KACZ,YAAY;KACZ,qBAAqB;KACrB,MAAM;KACN,eAAe;KACf,GAAGH;IACL;GACD,CAAA;GAEH,kBAAC,QAAD;IACE,WAAWU,EACT,kJACArB,EAAYY,EACd;IACA,OAAO;KACL;KACA,SAASa;KACT,aAAaX,IAAmB,IAAIG;KACpC,aAAaH,IAAmB,KAAA,IAAYY;KAC5C,aAAaZ,IAAmB,KAAA,IAAYa;KAC5C,GAAGhB;IACL;IAEC,UAAAH,IACC,kBAAC,OAAD;KACO;KACL,KAAKoB,KAAO7B,KAAQ;KACpB,WAAU;KACV,eAAeO,EAAa,EAAI;IACjC,CAAA,IAEDG;GAEE,CAAA;GACLM,KAAW,kBAACc,GAAD,EAA+B,KAAKd,EAAU,GAAxBA,CAAwB;GACzDI,KACC,kBAAC,QAAD;IACE,WAAWE,EACT,0HACApB,EAA4B6B,IAC5BV,MAAiB,KAAO,gBAAgB,wCAC1C;IACA,OAAO,EAAE,iBAAiBW,EAAkB;IAE3C,UAAAX,MAAiB,KAAO,KAAKA;GAC1B,CAAA;EAEJ;;AAEV,GAGMS,KAA8C,EAAE,aAAU;CAC9D,IAAM,CAACG,GAAQC,KAAarC,EAAM,SAAS,EAAK;CAEhD,OADIoC,IAAe,OAEjB,kBAAC,OAAD;EACO;EACL,KAAI;EACJ,eAAY;EACZ,WAAW;EACX,WAAU;EACV,eAAeC,EAAU,EAAI;CAC9B,CAAA;AAEL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Badge/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type BadgeProps = {\n children: React.ReactNode;\n variant?: 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'ghost';\n size?: 'xs' | 'sm' | 'md' | 'lg';\n outline?: boolean;\n className?: string;\n};\n\nconst Badge: React.FC<BadgeProps> = ({\n children,\n variant = 'primary',\n size = 'sm',\n outline = false,\n className = '',\n}) => {\n const baseClass = 'badge';\n const variantClass = variant ? `badge-${variant}` : '';\n const sizeClass = size ? `badge-${size}` : '';\n const outlineClass = outline ? 'badge-outline' : '';\n \n const badgeClasses = cn(\n baseClass,\n variantClass,\n sizeClass,\n outlineClass,\n className\n );\n\n return (\n <div className={badgeClasses}>\n {children}\n </div>\n );\n};\n\nexport default Badge; "],"mappings":";;;;AAWA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["Badge","variantClass","variant","sizeClass","size","badgeClasses","cn","outline","className"],"sources":["../../../src/components/Badge/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type BadgeProps = {\n children: React.ReactNode;\n variant?: 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'ghost';\n size?: 'xs' | 'sm' | 'md' | 'lg';\n outline?: boolean;\n className?: string;\n};\n\nconst Badge: React.FC<BadgeProps> = ({\n children,\n variant = 'primary',\n size = 'sm',\n outline = false,\n className = '',\n}) => {\n const baseClass = 'badge';\n const variantClass = variant ? `badge-${variant}` : '';\n const sizeClass = size ? `badge-${size}` : '';\n const outlineClass = outline ? 'badge-outline' : '';\n \n const badgeClasses = cn(\n baseClass,\n variantClass,\n sizeClass,\n outlineClass,\n className\n );\n\n return (\n <div className={badgeClasses}>\n {children}\n </div>\n );\n};\n\nexport default Badge; "],"mappings":";;;;AAWA,IAAMA,KAA+B,EACnC,aACA,aAAU,WACV,UAAO,MACP,aAAU,IACV,eAAY,SACR;CACJ,IACMC,IAAeC,IAAU,SAASA,MAAY,IAC9CC,IAAYC,IAAO,SAASA,MAAS,IAGrCC,IAAeC,EACnB,SACAL,GACAE,GALmBI,IAAU,kBAAkB,IAO/CC,CACF;CAEA,OACE,kBAAC,OAAD;EAAK,WAAWH;EACb;CACE,CAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Button/index.tsx"],"sourcesContent":["import React, { ReactElement, useState, useCallback } from 'react';\nimport { cn } from '../../utils/cn';\n\n// 状态项定义\nexport type ButtonState = {\n label: string; // 显示的字符/文本\n key: string; // 状态的唯一标识\n variant?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'destructive' | 'ghost' | 'link';\n icon?: React.ReactNode; // 可选的图标\n};\n\nexport type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {\n ref?: React.Ref<HTMLButtonElement>;\n children?: React.ReactNode;\n variant?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'destructive' | 'ghost' | 'link';\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n outline?: boolean;\n dash?: boolean;\n soft?: boolean;\n active?: boolean;\n disabled?: boolean;\n wide?: boolean;\n block?: boolean;\n square?: boolean;\n circle?: boolean;\n leftSection?: React.ReactNode;\n rightSection?: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n /** 原生 button type;不传时保持浏览器默认行为(表单内默认 submit) */\n type?: 'button' | 'submit' | 'reset';\n className?: string;\n\n // 状态切换相关\n states?: ButtonState[]; // 状态列表\n initialStateIndex?: number; // 初始状态索引\n onStateChange?: (state: ButtonState, clickCount: number, stateIndex: number) => void; // 状态改变回调\n};\n\nconst Button = ({\n children,\n variant = 'primary',\n size = 'sm',\n outline = false,\n dash = false,\n soft = false,\n active = false,\n disabled = false,\n wide = false,\n block = false,\n square = false,\n circle = false,\n leftSection,\n rightSection,\n onClick,\n type,\n className = '',\n states,\n initialStateIndex = 0,\n onStateChange,\n title,\n ...rest\n}: ButtonProps) => {\n // 状态管理\n const [currentStateIndex, setCurrentStateIndex] = useState(initialStateIndex);\n const [clickCount, setClickCount] = useState(0);\n\n // 是否是状态按钮\n const isStateful = states && states.length > 0;\n\n // 获取当前状态\n const currentState = isStateful ? states[currentStateIndex] : null;\n\n // 处理点击\n const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {\n if (isStateful) {\n const newClickCount = clickCount + 1;\n const newStateIndex = (currentStateIndex + 1) % states.length;\n const newState = states[newStateIndex];\n\n setClickCount(newClickCount);\n setCurrentStateIndex(newStateIndex);\n\n // 调用状态改变回调\n if (onStateChange) {\n onStateChange(newState, newClickCount, newStateIndex);\n }\n }\n\n // 调用原始 onClick\n if (onClick) {\n onClick(event);\n }\n }, [isStateful, states, currentStateIndex, clickCount, onStateChange, onClick]);\n\n // 确定使用的 variant\n const effectiveVariant = currentState?.variant || variant;\n\n // 确定显示的内容\n const displayContent = isStateful ? (\n <>\n {currentState?.icon && <span className=\"mr-1\">{currentState.icon}</span>}\n {currentState?.label}\n </>\n ) : children;\n\n const baseClass = 'btn';\n const variantClass = effectiveVariant === 'destructive' ? 'btn-error btn-destructive' : effectiveVariant ? `btn-${effectiveVariant}` : '';\n const sizeClass = size ? `btn-${size}` : '';\n const outlineClass = outline ? 'btn-outline' : '';\n const dashClass = dash ? 'btn-dash' : '';\n const softClass = soft ? 'btn-soft' : '';\n const activeClass = active || isStateful ? 'btn-active' : '';\n const wideClass = wide ? 'btn-wide' : '';\n const blockClass = block ? 'btn-block' : '';\n const squareClass = square ? 'btn-square' : '';\n const circleClass = circle ? 'btn-circle' : '';\n\n const buttonClasses = cn(\n baseClass,\n variantClass,\n sizeClass,\n outlineClass,\n dashClass,\n softClass,\n activeClass,\n wideClass,\n blockClass,\n squareClass,\n circleClass,\n className\n );\n\n return (\n <button\n {...rest}\n type={type}\n className={buttonClasses}\n disabled={disabled}\n onClick={handleClick}\n title={title ?? (isStateful ? `当前状态: ${currentState?.key} (点击次数: ${clickCount})` : undefined)}\n >\n {!isStateful && leftSection && <span className=\"mr-2\">{leftSection}</span>}\n {displayContent}\n {!isStateful && rightSection && <span className=\"ml-2\">{rightSection}</span>}\n </button>\n );\n};\n\n// Button.Group 组件\nexport type ButtonGroupProps = {\n children: React.ReactNode;\n vertical?: boolean;\n className?: string;\n rounded?: 'left' | 'right' | 'both' | 'none' | 'top' | 'bottom';\n radius?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full';\n roundedStyle?: {\n left?: string;\n right?: string;\n top?: string;\n bottom?: string;\n };\n};\n\nconst ButtonGroup = ({\n children,\n vertical = false,\n className = '',\n rounded = 'none',\n radius = 'full',\n roundedStyle,\n}: ButtonGroupProps) => {\n const joinClasses = cn(\n 'join',\n vertical ? 'join-vertical' : 'join-horizontal',\n className\n );\n\n // 当rounded不为'none'时,强制使用'full'作为radius值\n const effectiveRadius = rounded !== 'none' ? 'full' : radius;\n\n return (\n <div className={joinClasses}>\n {React.Children.map(children, (child, index) => {\n // 只处理有效的React元素\n if (!React.isValidElement(child)) return child;\n\n const childElement = child as ReactElement<{ className?: string }>;\n const childClassName = childElement.props.className || '';\n const isFirstChild = index === 0;\n const isLastChild = index === React.Children.count(children) - 1;\n\n // 根据rounded属性添加额外的圆角类\n let roundedClasses = '';\n\n if (roundedStyle) {\n // 使用自定义圆角样式\n if (vertical) {\n if ((rounded === 'left' || rounded === 'top') && isFirstChild && roundedStyle.top) {\n roundedClasses = roundedStyle.top;\n } else if ((rounded === 'right' || rounded === 'bottom') && isLastChild && roundedStyle.bottom) {\n roundedClasses = roundedStyle.bottom;\n } else if (rounded === 'both') {\n if (isFirstChild && roundedStyle.top) roundedClasses = roundedStyle.top;\n if (isLastChild && roundedStyle.bottom) roundedClasses = roundedStyle.bottom;\n }\n } else {\n if ((rounded === 'left' || rounded === 'top') && isFirstChild && roundedStyle.left) {\n roundedClasses = roundedStyle.left;\n } else if ((rounded === 'right' || rounded === 'bottom') && isLastChild && roundedStyle.right) {\n roundedClasses = roundedStyle.right;\n } else if (rounded === 'both') {\n if (isFirstChild && roundedStyle.left) roundedClasses = roundedStyle.left;\n if (isLastChild && roundedStyle.right) roundedClasses = roundedStyle.right;\n }\n }\n } else {\n // 使用默认的圆角大小\n if (vertical) {\n // 垂直布局时,圆角应用在上下方\n if (rounded === 'left' || rounded === 'top') {\n if (isFirstChild) roundedClasses = `rounded-t-${effectiveRadius}`;\n } else if (rounded === 'right' || rounded === 'bottom') {\n if (isLastChild) roundedClasses = `rounded-b-${effectiveRadius}`;\n } else if (rounded === 'both') {\n if (isFirstChild) roundedClasses = `rounded-t-${effectiveRadius}`;\n if (isLastChild) roundedClasses = `rounded-b-${effectiveRadius}`;\n }\n } else {\n // 水平布局时,圆角应用在左右方\n if (rounded === 'left' || rounded === 'top') {\n if (isFirstChild) roundedClasses = `rounded-l-${effectiveRadius}`;\n } else if (rounded === 'right' || rounded === 'bottom') {\n if (isLastChild) roundedClasses = `rounded-r-${effectiveRadius}`;\n } else if (rounded === 'both') {\n if (isFirstChild) roundedClasses = `rounded-l-${effectiveRadius}`;\n if (isLastChild) roundedClasses = `rounded-r-${effectiveRadius}`;\n }\n }\n }\n\n const newClassName = `${childClassName} join-item ${roundedClasses}`.trim();\n\n return React.cloneElement(childElement, {\n className: newClassName,\n });\n })}\n </div>\n );\n};\n\n// Button.GroupSection 组件\nexport type ButtonGroupSectionProps = {\n children: React.ReactNode;\n className?: string;\n};\n\nconst ButtonGroupSection = ({\n children,\n className = '',\n}: ButtonGroupSectionProps) => {\n const sectionClasses = cn(\n 'join-item',\n 'flex',\n 'items-center',\n 'px-4',\n 'bg-base-200',\n 'border',\n 'border-base-300',\n className\n );\n\n return (\n <div className={sectionClasses}>\n {children}\n </div>\n );\n};\n\n// 扩展Button组件,添加Group和GroupSection子组件\ninterface ButtonCompound extends React.FC<ButtonProps> {\n Group: React.FC<ButtonGroupProps>;\n GroupSection: React.FC<ButtonGroupSectionProps>;\n}\n\nconst ButtonWithCompounds = Button as ButtonCompound;\nButtonWithCompounds.Group = ButtonGroup;\nButtonWithCompounds.GroupSection = ButtonGroupSection;\n\nexport default ButtonWithCompounds; "],"mappings":";;;;AAsCA,IAAM,KAAU,EACd,aACA,aAAU,WACV,UAAO,MACP,aAAU,IACV,UAAO,IACP,UAAO,IACP,YAAS,IACT,cAAW,IACX,UAAO,IACP,WAAQ,IACR,YAAS,IACT,YAAS,IACT,gBACA,iBACA,YACA,SACA,eAAY,IACZ,WACA,uBAAoB,GACpB,kBACA,UACA,GAAG,QACc;CAEjB,IAAM,CAAC,GAAmB,KAAwB,EAAS,CAAiB,GACtE,CAAC,GAAY,KAAiB,EAAS,CAAC,GAGxC,IAAa,KAAU,EAAO,SAAS,GAGvC,IAAe,IAAa,EAAO,KAAqB,MAGxD,IAAc,GAAa,MAA+C;EAC9E,IAAI,GAAY;GACd,IAAM,IAAgB,IAAa,GAC7B,KAAiB,IAAoB,KAAK,EAAO,QACjD,IAAW,EAAO;GAMxB,AAJA,EAAc,CAAa,GAC3B,EAAqB,CAAa,GAG9B,KACF,EAAc,GAAU,GAAe,CAAa;EAExD;EAGA,AAAI,KACF,EAAQ,CAAK;CAEjB,GAAG;EAAC;EAAY;EAAQ;EAAmB;EAAY;EAAe;CAAO,CAAC,GAGxE,IAAmB,GAAc,WAAW,GAG5C,IAAiB,IACrB,kBAAA,GAAA,EAAA,UAAA,CACG,GAAc,QAAQ,kBAAC,QAAD;EAAM,WAAU;EAAQ,UAAA,EAAa;CAAW,CAAA,GACtE,GAAc,KACf,EAAA,CAAA,IACA,GAGE,IAAe,MAAqB,gBAAgB,8BAA8B,IAAmB,OAAO,MAAqB,IACjI,IAAY,IAAO,OAAO,MAAS,IAUnC,IAAgB,EACpB,OACA,GACA,GAZmB,IAAU,gBAAgB,IAC7B,IAAO,aAAa,IACpB,IAAO,aAAa,IAClB,KAAU,IAAa,eAAe,IACxC,IAAO,aAAa,IACnB,IAAQ,cAAc,IACrB,IAAS,eAAe,IACxB,IAAS,eAAe,IAc1C,CACF;CAEA,OACE,kBAAC,UAAD;EACE,GAAI;EACE;EACN,WAAW;EACD;EACV,SAAS;EACT,OAAO,MAAU,IAAa,SAAS,GAAc,IAAI,UAAU,EAAW,KAAK,KAAA;EANrF,UAAA;GAQG,CAAC,KAAc,KAAe,kBAAC,QAAD;IAAM,WAAU;IAAQ,UAAA;GAAkB,CAAA;GACxE;GACA,CAAC,KAAc,KAAgB,kBAAC,QAAD;IAAM,WAAU;IAAQ,UAAA;GAAmB,CAAA;EACrE;;AAEZ,GAiBM,KAAe,EACnB,aACA,cAAW,IACX,eAAY,IACZ,aAAU,QACV,YAAS,QACT,sBACsB;CACtB,IAAM,IAAc,EAClB,QACA,IAAW,kBAAkB,mBAC7B,CACF,GAGM,IAAkB,MAAY,SAAkB,IAAT;CAE7C,OACE,kBAAC,OAAD;EAAK,WAAW;EACb,UAAA,EAAM,SAAS,IAAI,IAAW,GAAO,MAAU;GAE9C,IAAI,CAAC,EAAM,eAAe,CAAK,GAAG,OAAO;GAEzC,IAAM,IAAe,GACf,IAAiB,EAAa,MAAM,aAAa,IACjD,IAAe,MAAU,GACzB,IAAc,MAAU,EAAM,SAAS,MAAM,CAAQ,IAAI,GAG3D,IAAiB;GAErB,AAAI,IAEE,KACG,MAAY,UAAU,MAAY,UAAU,KAAgB,EAAa,MAC5E,IAAiB,EAAa,OACpB,MAAY,WAAW,MAAY,aAAa,KAAe,EAAa,SACtF,IAAiB,EAAa,SACrB,MAAY,WACjB,KAAgB,EAAa,QAAK,IAAiB,EAAa,MAChE,KAAe,EAAa,WAAQ,IAAiB,EAAa,YAGnE,MAAY,UAAU,MAAY,UAAU,KAAgB,EAAa,OAC5E,IAAiB,EAAa,QACpB,MAAY,WAAW,MAAY,aAAa,KAAe,EAAa,QACtF,IAAiB,EAAa,QACrB,MAAY,WACjB,KAAgB,EAAa,SAAM,IAAiB,EAAa,OACjE,KAAe,EAAa,UAAO,IAAiB,EAAa,UAKrE,IAEE,MAAY,UAAU,MAAY,QAChC,MAAc,IAAiB,aAAa,OACvC,MAAY,WAAW,MAAY,WACxC,MAAa,IAAiB,aAAa,OACtC,MAAY,WACjB,MAAc,IAAiB,aAAa,MAC5C,MAAa,IAAiB,aAAa,QAI7C,MAAY,UAAU,MAAY,QAChC,MAAc,IAAiB,aAAa,OACvC,MAAY,WAAW,MAAY,WACxC,MAAa,IAAiB,aAAa,OACtC,MAAY,WACjB,MAAc,IAAiB,aAAa,MAC5C,MAAa,IAAiB,aAAa;GAKrD,IAAM,IAAe,GAAG,EAAe,aAAa,IAAiB,KAAK;GAE1E,OAAO,EAAM,aAAa,GAAc,EACtC,WAAW,EACb,CAAC;EACH,CAAC;CACE,CAAA;AAET,GAQM,KAAsB,EAC1B,aACA,eAAY,SACiB;CAC7B,IAAM,IAAiB,EACrB,aACA,QACA,gBACA,QACA,eACA,UACA,mBACA,CACF;CAEA,OACE,kBAAC,OAAD;EAAK,WAAW;EACb;CACE,CAAA;AAET,GAQM,IAAsB;AAC5B,EAAoB,QAAQ,GAC5B,EAAoB,eAAe"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_Fragment","React","Button","rest","currentStateIndex","setCurrentStateIndex","useState","initialStateIndex","clickCount","setClickCount","isStateful","states","currentState","handleClick","useCallback","newClickCount","newStateIndex","newState","onStateChange","onClick","event","effectiveVariant","variant","displayContent","Fragment","children","variantClass","sizeClass","size","buttonClasses","cn","outline","dash","soft","active","wide","block","square","circle","className","title","leftSection","rightSection","ButtonGroup","joinClasses","vertical","effectiveRadius","rounded","radius","child","childElement","childClassName","isFirstChild","index","isLastChild","roundedClasses","roundedStyle","newClassName","ButtonGroupSection","sectionClasses","ButtonWithCompounds"],"sources":["../../../src/components/Button/index.tsx"],"sourcesContent":["import React, { ReactElement, useState, useCallback } from 'react';\nimport { cn } from '../../utils/cn';\n\n// 状态项定义\nexport type ButtonState = {\n label: string; // 显示的字符/文本\n key: string; // 状态的唯一标识\n variant?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'destructive' | 'ghost' | 'link';\n icon?: React.ReactNode; // 可选的图标\n};\n\nexport type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {\n ref?: React.Ref<HTMLButtonElement>;\n children?: React.ReactNode;\n variant?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'destructive' | 'ghost' | 'link';\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n outline?: boolean;\n dash?: boolean;\n soft?: boolean;\n active?: boolean;\n disabled?: boolean;\n wide?: boolean;\n block?: boolean;\n square?: boolean;\n circle?: boolean;\n leftSection?: React.ReactNode;\n rightSection?: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n /** 原生 button type;不传时保持浏览器默认行为(表单内默认 submit) */\n type?: 'button' | 'submit' | 'reset';\n className?: string;\n\n // 状态切换相关\n states?: ButtonState[]; // 状态列表\n initialStateIndex?: number; // 初始状态索引\n onStateChange?: (state: ButtonState, clickCount: number, stateIndex: number) => void; // 状态改变回调\n};\n\nconst Button = ({\n children,\n variant = 'primary',\n size = 'sm',\n outline = false,\n dash = false,\n soft = false,\n active = false,\n disabled = false,\n wide = false,\n block = false,\n square = false,\n circle = false,\n leftSection,\n rightSection,\n onClick,\n type,\n className = '',\n states,\n initialStateIndex = 0,\n onStateChange,\n title,\n ...rest\n}: ButtonProps) => {\n // 状态管理\n const [currentStateIndex, setCurrentStateIndex] = useState(initialStateIndex);\n const [clickCount, setClickCount] = useState(0);\n\n // 是否是状态按钮\n const isStateful = states && states.length > 0;\n\n // 获取当前状态\n const currentState = isStateful ? states[currentStateIndex] : null;\n\n // 处理点击\n const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {\n if (isStateful) {\n const newClickCount = clickCount + 1;\n const newStateIndex = (currentStateIndex + 1) % states.length;\n const newState = states[newStateIndex];\n\n setClickCount(newClickCount);\n setCurrentStateIndex(newStateIndex);\n\n // 调用状态改变回调\n if (onStateChange) {\n onStateChange(newState, newClickCount, newStateIndex);\n }\n }\n\n // 调用原始 onClick\n if (onClick) {\n onClick(event);\n }\n }, [isStateful, states, currentStateIndex, clickCount, onStateChange, onClick]);\n\n // 确定使用的 variant\n const effectiveVariant = currentState?.variant || variant;\n\n // 确定显示的内容\n const displayContent = isStateful ? (\n <>\n {currentState?.icon && <span className=\"mr-1\">{currentState.icon}</span>}\n {currentState?.label}\n </>\n ) : children;\n\n const baseClass = 'btn';\n const variantClass = effectiveVariant === 'destructive' ? 'btn-error btn-destructive' : effectiveVariant ? `btn-${effectiveVariant}` : '';\n const sizeClass = size ? `btn-${size}` : '';\n const outlineClass = outline ? 'btn-outline' : '';\n const dashClass = dash ? 'btn-dash' : '';\n const softClass = soft ? 'btn-soft' : '';\n const activeClass = active || isStateful ? 'btn-active' : '';\n const wideClass = wide ? 'btn-wide' : '';\n const blockClass = block ? 'btn-block' : '';\n const squareClass = square ? 'btn-square' : '';\n const circleClass = circle ? 'btn-circle' : '';\n\n const buttonClasses = cn(\n baseClass,\n variantClass,\n sizeClass,\n outlineClass,\n dashClass,\n softClass,\n activeClass,\n wideClass,\n blockClass,\n squareClass,\n circleClass,\n className\n );\n\n return (\n <button\n {...rest}\n type={type}\n className={buttonClasses}\n disabled={disabled}\n onClick={handleClick}\n title={title ?? (isStateful ? `当前状态: ${currentState?.key} (点击次数: ${clickCount})` : undefined)}\n >\n {!isStateful && leftSection && <span className=\"mr-2\">{leftSection}</span>}\n {displayContent}\n {!isStateful && rightSection && <span className=\"ml-2\">{rightSection}</span>}\n </button>\n );\n};\n\n// Button.Group 组件\nexport type ButtonGroupProps = {\n children: React.ReactNode;\n vertical?: boolean;\n className?: string;\n rounded?: 'left' | 'right' | 'both' | 'none' | 'top' | 'bottom';\n radius?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full';\n roundedStyle?: {\n left?: string;\n right?: string;\n top?: string;\n bottom?: string;\n };\n};\n\nconst ButtonGroup = ({\n children,\n vertical = false,\n className = '',\n rounded = 'none',\n radius = 'full',\n roundedStyle,\n}: ButtonGroupProps) => {\n const joinClasses = cn(\n 'join',\n vertical ? 'join-vertical' : 'join-horizontal',\n className\n );\n\n // 当rounded不为'none'时,强制使用'full'作为radius值\n const effectiveRadius = rounded !== 'none' ? 'full' : radius;\n\n return (\n <div className={joinClasses}>\n {React.Children.map(children, (child, index) => {\n // 只处理有效的React元素\n if (!React.isValidElement(child)) return child;\n\n const childElement = child as ReactElement<{ className?: string }>;\n const childClassName = childElement.props.className || '';\n const isFirstChild = index === 0;\n const isLastChild = index === React.Children.count(children) - 1;\n\n // 根据rounded属性添加额外的圆角类\n let roundedClasses = '';\n\n if (roundedStyle) {\n // 使用自定义圆角样式\n if (vertical) {\n if ((rounded === 'left' || rounded === 'top') && isFirstChild && roundedStyle.top) {\n roundedClasses = roundedStyle.top;\n } else if ((rounded === 'right' || rounded === 'bottom') && isLastChild && roundedStyle.bottom) {\n roundedClasses = roundedStyle.bottom;\n } else if (rounded === 'both') {\n if (isFirstChild && roundedStyle.top) roundedClasses = roundedStyle.top;\n if (isLastChild && roundedStyle.bottom) roundedClasses = roundedStyle.bottom;\n }\n } else {\n if ((rounded === 'left' || rounded === 'top') && isFirstChild && roundedStyle.left) {\n roundedClasses = roundedStyle.left;\n } else if ((rounded === 'right' || rounded === 'bottom') && isLastChild && roundedStyle.right) {\n roundedClasses = roundedStyle.right;\n } else if (rounded === 'both') {\n if (isFirstChild && roundedStyle.left) roundedClasses = roundedStyle.left;\n if (isLastChild && roundedStyle.right) roundedClasses = roundedStyle.right;\n }\n }\n } else {\n // 使用默认的圆角大小\n if (vertical) {\n // 垂直布局时,圆角应用在上下方\n if (rounded === 'left' || rounded === 'top') {\n if (isFirstChild) roundedClasses = `rounded-t-${effectiveRadius}`;\n } else if (rounded === 'right' || rounded === 'bottom') {\n if (isLastChild) roundedClasses = `rounded-b-${effectiveRadius}`;\n } else if (rounded === 'both') {\n if (isFirstChild) roundedClasses = `rounded-t-${effectiveRadius}`;\n if (isLastChild) roundedClasses = `rounded-b-${effectiveRadius}`;\n }\n } else {\n // 水平布局时,圆角应用在左右方\n if (rounded === 'left' || rounded === 'top') {\n if (isFirstChild) roundedClasses = `rounded-l-${effectiveRadius}`;\n } else if (rounded === 'right' || rounded === 'bottom') {\n if (isLastChild) roundedClasses = `rounded-r-${effectiveRadius}`;\n } else if (rounded === 'both') {\n if (isFirstChild) roundedClasses = `rounded-l-${effectiveRadius}`;\n if (isLastChild) roundedClasses = `rounded-r-${effectiveRadius}`;\n }\n }\n }\n\n const newClassName = `${childClassName} join-item ${roundedClasses}`.trim();\n\n return React.cloneElement(childElement, {\n className: newClassName,\n });\n })}\n </div>\n );\n};\n\n// Button.GroupSection 组件\nexport type ButtonGroupSectionProps = {\n children: React.ReactNode;\n className?: string;\n};\n\nconst ButtonGroupSection = ({\n children,\n className = '',\n}: ButtonGroupSectionProps) => {\n const sectionClasses = cn(\n 'join-item',\n 'flex',\n 'items-center',\n 'px-4',\n 'bg-base-200',\n 'border',\n 'border-base-300',\n className\n );\n\n return (\n <div className={sectionClasses}>\n {children}\n </div>\n );\n};\n\n// 扩展Button组件,添加Group和GroupSection子组件\ninterface ButtonCompound extends React.FC<ButtonProps> {\n Group: React.FC<ButtonGroupProps>;\n GroupSection: React.FC<ButtonGroupSectionProps>;\n}\n\nconst ButtonWithCompounds = Button as ButtonCompound;\nButtonWithCompounds.Group = ButtonGroup;\nButtonWithCompounds.GroupSection = ButtonGroupSection;\n\nexport default ButtonWithCompounds; "],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/ButtonMenu/index.tsx"],"sourcesContent":["import React, { useCallback, useId, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport Button, { type ButtonProps } from '../Button';\nimport Text from '../Text';\nimport './style.css';\n\nexport type ButtonMenuItem = {\n id: string;\n label: string;\n icon?: React.ReactNode;\n disabled?: boolean;\n onSelect?: () => void;\n};\n\nexport type ButtonMenuProps = {\n label: string;\n icon?: React.ReactNode;\n iconOnly?: boolean;\n items: ButtonMenuItem[];\n selectedId?: string;\n onSelect?: (id: string) => void;\n align?: 'start' | 'end';\n disabled?: boolean;\n variant?: ButtonProps['variant'];\n size?: ButtonProps['size'];\n className?: string;\n 'aria-label'?: string;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n};\n\nconst Chevron = () => <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><path d=\"m4 6 4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>;\nconst Check = () => <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><path d=\"m3 8 3 3 7-7\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>;\n\n/** A button-triggered action menu, or a single-choice menu when selectedId is supplied. */\nexport default function ButtonMenu({\n label, icon, iconOnly = false, items, selectedId, onSelect, align = 'start',\n disabled = false, variant = 'ghost', size = 'sm', className = '',\n 'aria-label': ariaLabel, open, defaultOpen = false, onOpenChange,\n}: ButtonMenuProps) {\n const id = useId();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const initialFocus = useRef<'first' | 'last' | 'selected'>('selected');\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const unavailable = disabled || items.length === 0;\n const isOpen = (open ?? internalOpen) && !unavailable;\n const [activeId, setActiveId] = useState<string>();\n const wasOpen = useRef(false);\n const requestOpen = useCallback((next: boolean) => {\n if (open === undefined) setInternalOpen(next);\n if (next !== (open ?? internalOpen)) onOpenChange?.(next);\n }, [open, internalOpen, onOpenChange]);\n const focusTrigger = () => triggerRef.current?.focus({ preventScroll: true });\n const close = () => { requestOpen(false); focusTrigger(); };\n const enabledElements = () => Array.from(menuRef.current?.querySelectorAll<HTMLButtonElement>('button:not(:disabled)') ?? []);\n const focusItem = (element?: HTMLButtonElement) => {\n if (!element) { menuRef.current?.focus({ preventScroll: true }); return; }\n element.focus({ preventScroll: true });\n element.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n };\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n const trigger = triggerRef.current!;\n const menu = menuRef.current!;\n const position = () => {\n const theme = trigger.closest('[data-theme]')?.getAttribute('data-theme');\n if (theme !== null && theme !== undefined) menu.setAttribute('data-theme', theme);\n else menu.removeAttribute('data-theme');\n const rtl = getComputedStyle(trigger).direction === 'rtl';\n menu.dir = rtl ? 'rtl' : 'ltr';\n const viewport = window.visualViewport;\n const leftEdge = (viewport?.offsetLeft ?? 0) + 8;\n const topEdge = (viewport?.offsetTop ?? 0) + 8;\n const rightEdge = leftEdge + (viewport?.width ?? document.documentElement.clientWidth) - 16;\n const bottomEdge = topEdge + (viewport?.height ?? window.innerHeight) - 16;\n menu.style.maxWidth = `${Math.max(0, Math.min(320, rightEdge - leftEdge))}px`;\n const rect = trigger.getBoundingClientRect();\n const below = Math.max(0, bottomEdge - rect.bottom - 4);\n const above = Math.max(0, rect.top - topEdge - 4);\n const desiredHeight = Math.min(menu.scrollHeight + 2, 352);\n const upwards = below < desiredHeight && above > below;\n menu.style.maxHeight = `${Math.min(352, upwards ? above : below)}px`;\n const box = menu.getBoundingClientRect();\n const end = (align === 'end') !== rtl;\n const left = end ? rect.right - box.width : rect.left;\n const top = upwards ? rect.top - box.height - 4 : rect.bottom + 4;\n menu.style.left = `${Math.max(leftEdge, Math.min(left, rightEdge - box.width))}px`;\n menu.style.top = `${Math.max(topEdge, Math.min(top, bottomEdge - box.height))}px`;\n };\n position();\n const resize = new ResizeObserver(position);\n resize.observe(trigger);\n resize.observe(menu);\n const themeObserver = new MutationObserver(position);\n for (let ancestor: HTMLElement | null = trigger; ancestor; ancestor = ancestor.parentElement) {\n themeObserver.observe(ancestor, { attributes: true, attributeFilter: ['data-theme', 'dir'] });\n }\n window.addEventListener('resize', position);\n window.addEventListener('scroll', position, true);\n window.visualViewport?.addEventListener('resize', position);\n window.visualViewport?.addEventListener('scroll', position);\n return () => {\n resize.disconnect();\n themeObserver.disconnect();\n window.removeEventListener('resize', position);\n window.removeEventListener('scroll', position, true);\n window.visualViewport?.removeEventListener('resize', position);\n window.visualViewport?.removeEventListener('scroll', position);\n };\n }, [isOpen, align, items]);\n\n useLayoutEffect(() => {\n if (isOpen && !wasOpen.current) {\n const enabled = enabledElements();\n const target = initialFocus.current === 'last' ? enabled.at(-1)\n : initialFocus.current === 'first' ? enabled[0]\n : enabled.find(element => element.dataset.itemId === selectedId) ?? enabled[0];\n focusItem(target);\n initialFocus.current = 'selected';\n } else if (!isOpen && wasOpen.current && document.activeElement === document.body) {\n // External controlled closes should not strand focus on the removed portal.\n focusTrigger();\n } else if (isOpen && (document.activeElement === document.body || menuRef.current?.contains(document.activeElement))) {\n const focused = document.activeElement;\n if (focused === menuRef.current || focused?.matches(':disabled') || !menuRef.current?.contains(focused)) focusItem(enabledElements()[0]);\n }\n wasOpen.current = isOpen;\n });\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n const dismiss = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && !triggerRef.current?.contains(target) && !menuRef.current?.contains(target)) requestOpen(false);\n };\n document.addEventListener('pointerdown', dismiss, true);\n document.addEventListener('focusin', dismiss);\n return () => {\n document.removeEventListener('pointerdown', dismiss, true);\n document.removeEventListener('focusin', dismiss);\n };\n }, [isOpen, requestOpen]);\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n close();\n } else if (event.key === 'Tab') {\n // The portal is last in DOM order. Resume native traversal from its trigger,\n // without preventing Tab, so both directions reach the adjacent page control.\n focusTrigger();\n requestOpen(false);\n } else if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {\n event.preventDefault();\n const enabled = enabledElements();\n const index = enabled.indexOf(document.activeElement as HTMLButtonElement);\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? enabled.length - 1\n : (index + (event.key === 'ArrowDown' ? 1 : -1) + enabled.length) % enabled.length;\n focusItem(enabled[next]);\n }\n };\n\n return <>\n <Button ref={triggerRef} id={`${id}-trigger`} type=\"button\" variant={variant} size={size}\n square={iconOnly} disabled={unavailable}\n className={`dishui-button-menu-trigger ${className}`}\n aria-label={ariaLabel ?? label} title={iconOnly ? label : undefined}\n aria-haspopup=\"menu\" aria-expanded={isOpen} aria-controls={isOpen ? `${id}-menu` : undefined}\n onClick={() => { initialFocus.current = 'selected'; requestOpen(!isOpen); }}\n onKeyDown={event => {\n if (unavailable) return;\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n initialFocus.current = event.key === 'ArrowUp' ? 'last' : 'first';\n if (isOpen) focusItem(event.key === 'ArrowUp' ? enabledElements().at(-1) : enabledElements()[0]);\n else requestOpen(true);\n } else if (isOpen && event.key === 'Escape') handleKeyDown(event);\n }}>\n {icon != null && <span className=\"dishui-button-menu-icon\" aria-hidden=\"true\">{icon}</span>}\n {!iconOnly && <Text size=\"sm\" weight=\"medium\" color=\"inherit\" className=\"dishui-button-menu-label\">{label}</Text>}\n {(!iconOnly || icon == null) && <span className=\"dishui-button-menu-icon\" aria-hidden=\"true\"><Chevron /></span>}\n </Button>\n {isOpen && typeof document !== 'undefined' && createPortal(\n <div ref={menuRef} id={`${id}-menu`} role=\"menu\" aria-labelledby={`${id}-trigger`}\n tabIndex={-1} className=\"dishui-button-menu-surface\" onKeyDown={handleKeyDown}>\n {items.map(item => <button key={item.id} type=\"button\" data-item-id={item.id}\n role={selectedId === undefined ? 'menuitem' : 'menuitemradio'}\n aria-checked={selectedId === undefined ? undefined : selectedId === item.id}\n disabled={item.disabled} aria-disabled={item.disabled || undefined}\n tabIndex={!item.disabled && activeId === item.id ? 0 : -1}\n className=\"dishui-button-menu-item\" onFocus={() => setActiveId(item.id)}\n onClick={() => {\n if (item.disabled) return;\n close();\n item.onSelect?.();\n onSelect?.(item.id);\n }}>\n {item.icon != null && <span className=\"dishui-button-menu-icon\" aria-hidden=\"true\">{item.icon}</span>}\n <Text size=\"sm\" color=\"inherit\" className=\"dishui-button-menu-label\">{item.label}</Text>\n {selectedId !== undefined && <span className=\"dishui-button-menu-check\" aria-hidden=\"true\">{selectedId === item.id && <Check />}</span>}\n </button>)}\n </div>, document.body)}\n </>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_Fragment","Button","ButtonWithCompounds","Text","Chevron","Check","ButtonMenu","ariaLabel","id","useId","triggerRef","useRef","menuRef","initialFocus","internalOpen","setInternalOpen","useState","defaultOpen","unavailable","disabled","items","isOpen","open","activeId","setActiveId","wasOpen","requestOpen","useCallback","next","onOpenChange","focusTrigger","close","enabledElements","focusItem","element","useLayoutEffect","trigger","menu","position","theme","rtl","viewport","leftEdge","topEdge","rightEdge","bottomEdge","rect","below","above","upwards","box","left","align","top","resize","themeObserver","ancestor","enabled","target","selectedId","focused","dismiss","event","handleKeyDown","index","Fragment","iconOnly","className","label","icon","createPortal","item","onSelect"],"sources":["../../../src/components/ButtonMenu/index.tsx"],"sourcesContent":["import React, { useCallback, useId, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport Button, { type ButtonProps } from '../Button';\nimport Text from '../Text';\nimport './style.css';\n\nexport type ButtonMenuItem = {\n id: string;\n label: string;\n icon?: React.ReactNode;\n disabled?: boolean;\n onSelect?: () => void;\n};\n\nexport type ButtonMenuProps = {\n label: string;\n icon?: React.ReactNode;\n iconOnly?: boolean;\n items: ButtonMenuItem[];\n selectedId?: string;\n onSelect?: (id: string) => void;\n align?: 'start' | 'end';\n disabled?: boolean;\n variant?: ButtonProps['variant'];\n size?: ButtonProps['size'];\n className?: string;\n 'aria-label'?: string;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n};\n\nconst Chevron = () => <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><path d=\"m4 6 4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>;\nconst Check = () => <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><path d=\"m3 8 3 3 7-7\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>;\n\n/** A button-triggered action menu, or a single-choice menu when selectedId is supplied. */\nexport default function ButtonMenu({\n label, icon, iconOnly = false, items, selectedId, onSelect, align = 'start',\n disabled = false, variant = 'ghost', size = 'sm', className = '',\n 'aria-label': ariaLabel, open, defaultOpen = false, onOpenChange,\n}: ButtonMenuProps) {\n const id = useId();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const initialFocus = useRef<'first' | 'last' | 'selected'>('selected');\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const unavailable = disabled || items.length === 0;\n const isOpen = (open ?? internalOpen) && !unavailable;\n const [activeId, setActiveId] = useState<string>();\n const wasOpen = useRef(false);\n const requestOpen = useCallback((next: boolean) => {\n if (open === undefined) setInternalOpen(next);\n if (next !== (open ?? internalOpen)) onOpenChange?.(next);\n }, [open, internalOpen, onOpenChange]);\n const focusTrigger = () => triggerRef.current?.focus({ preventScroll: true });\n const close = () => { requestOpen(false); focusTrigger(); };\n const enabledElements = () => Array.from(menuRef.current?.querySelectorAll<HTMLButtonElement>('button:not(:disabled)') ?? []);\n const focusItem = (element?: HTMLButtonElement) => {\n if (!element) { menuRef.current?.focus({ preventScroll: true }); return; }\n element.focus({ preventScroll: true });\n element.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n };\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n const trigger = triggerRef.current!;\n const menu = menuRef.current!;\n const position = () => {\n const theme = trigger.closest('[data-theme]')?.getAttribute('data-theme');\n if (theme !== null && theme !== undefined) menu.setAttribute('data-theme', theme);\n else menu.removeAttribute('data-theme');\n const rtl = getComputedStyle(trigger).direction === 'rtl';\n menu.dir = rtl ? 'rtl' : 'ltr';\n const viewport = window.visualViewport;\n const leftEdge = (viewport?.offsetLeft ?? 0) + 8;\n const topEdge = (viewport?.offsetTop ?? 0) + 8;\n const rightEdge = leftEdge + (viewport?.width ?? document.documentElement.clientWidth) - 16;\n const bottomEdge = topEdge + (viewport?.height ?? window.innerHeight) - 16;\n menu.style.maxWidth = `${Math.max(0, Math.min(320, rightEdge - leftEdge))}px`;\n const rect = trigger.getBoundingClientRect();\n const below = Math.max(0, bottomEdge - rect.bottom - 4);\n const above = Math.max(0, rect.top - topEdge - 4);\n const desiredHeight = Math.min(menu.scrollHeight + 2, 352);\n const upwards = below < desiredHeight && above > below;\n menu.style.maxHeight = `${Math.min(352, upwards ? above : below)}px`;\n const box = menu.getBoundingClientRect();\n const end = (align === 'end') !== rtl;\n const left = end ? rect.right - box.width : rect.left;\n const top = upwards ? rect.top - box.height - 4 : rect.bottom + 4;\n menu.style.left = `${Math.max(leftEdge, Math.min(left, rightEdge - box.width))}px`;\n menu.style.top = `${Math.max(topEdge, Math.min(top, bottomEdge - box.height))}px`;\n };\n position();\n const resize = new ResizeObserver(position);\n resize.observe(trigger);\n resize.observe(menu);\n const themeObserver = new MutationObserver(position);\n for (let ancestor: HTMLElement | null = trigger; ancestor; ancestor = ancestor.parentElement) {\n themeObserver.observe(ancestor, { attributes: true, attributeFilter: ['data-theme', 'dir'] });\n }\n window.addEventListener('resize', position);\n window.addEventListener('scroll', position, true);\n window.visualViewport?.addEventListener('resize', position);\n window.visualViewport?.addEventListener('scroll', position);\n return () => {\n resize.disconnect();\n themeObserver.disconnect();\n window.removeEventListener('resize', position);\n window.removeEventListener('scroll', position, true);\n window.visualViewport?.removeEventListener('resize', position);\n window.visualViewport?.removeEventListener('scroll', position);\n };\n }, [isOpen, align, items]);\n\n useLayoutEffect(() => {\n if (isOpen && !wasOpen.current) {\n const enabled = enabledElements();\n const target = initialFocus.current === 'last' ? enabled.at(-1)\n : initialFocus.current === 'first' ? enabled[0]\n : enabled.find(element => element.dataset.itemId === selectedId) ?? enabled[0];\n focusItem(target);\n initialFocus.current = 'selected';\n } else if (!isOpen && wasOpen.current && document.activeElement === document.body) {\n // External controlled closes should not strand focus on the removed portal.\n focusTrigger();\n } else if (isOpen && (document.activeElement === document.body || menuRef.current?.contains(document.activeElement))) {\n const focused = document.activeElement;\n if (focused === menuRef.current || focused?.matches(':disabled') || !menuRef.current?.contains(focused)) focusItem(enabledElements()[0]);\n }\n wasOpen.current = isOpen;\n });\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n const dismiss = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && !triggerRef.current?.contains(target) && !menuRef.current?.contains(target)) requestOpen(false);\n };\n document.addEventListener('pointerdown', dismiss, true);\n document.addEventListener('focusin', dismiss);\n return () => {\n document.removeEventListener('pointerdown', dismiss, true);\n document.removeEventListener('focusin', dismiss);\n };\n }, [isOpen, requestOpen]);\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n close();\n } else if (event.key === 'Tab') {\n // The portal is last in DOM order. Resume native traversal from its trigger,\n // without preventing Tab, so both directions reach the adjacent page control.\n focusTrigger();\n requestOpen(false);\n } else if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) {\n event.preventDefault();\n const enabled = enabledElements();\n const index = enabled.indexOf(document.activeElement as HTMLButtonElement);\n const next = event.key === 'Home' ? 0 : event.key === 'End' ? enabled.length - 1\n : (index + (event.key === 'ArrowDown' ? 1 : -1) + enabled.length) % enabled.length;\n focusItem(enabled[next]);\n }\n };\n\n return <>\n <Button ref={triggerRef} id={`${id}-trigger`} type=\"button\" variant={variant} size={size}\n square={iconOnly} disabled={unavailable}\n className={`dishui-button-menu-trigger ${className}`}\n aria-label={ariaLabel ?? label} title={iconOnly ? label : undefined}\n aria-haspopup=\"menu\" aria-expanded={isOpen} aria-controls={isOpen ? `${id}-menu` : undefined}\n onClick={() => { initialFocus.current = 'selected'; requestOpen(!isOpen); }}\n onKeyDown={event => {\n if (unavailable) return;\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n initialFocus.current = event.key === 'ArrowUp' ? 'last' : 'first';\n if (isOpen) focusItem(event.key === 'ArrowUp' ? enabledElements().at(-1) : enabledElements()[0]);\n else requestOpen(true);\n } else if (isOpen && event.key === 'Escape') handleKeyDown(event);\n }}>\n {icon != null && <span className=\"dishui-button-menu-icon\" aria-hidden=\"true\">{icon}</span>}\n {!iconOnly && <Text size=\"sm\" weight=\"medium\" color=\"inherit\" className=\"dishui-button-menu-label\">{label}</Text>}\n {(!iconOnly || icon == null) && <span className=\"dishui-button-menu-icon\" aria-hidden=\"true\"><Chevron /></span>}\n </Button>\n {isOpen && typeof document !== 'undefined' && createPortal(\n <div ref={menuRef} id={`${id}-menu`} role=\"menu\" aria-labelledby={`${id}-trigger`}\n tabIndex={-1} className=\"dishui-button-menu-surface\" onKeyDown={handleKeyDown}>\n {items.map(item => <button key={item.id} type=\"button\" data-item-id={item.id}\n role={selectedId === undefined ? 'menuitem' : 'menuitemradio'}\n aria-checked={selectedId === undefined ? undefined : selectedId === item.id}\n disabled={item.disabled} aria-disabled={item.disabled || undefined}\n tabIndex={!item.disabled && activeId === item.id ? 0 : -1}\n className=\"dishui-button-menu-item\" onFocus={() => setActiveId(item.id)}\n onClick={() => {\n if (item.disabled) return;\n close();\n item.onSelect?.();\n onSelect?.(item.id);\n }}>\n {item.icon != null && <span className=\"dishui-button-menu-icon\" aria-hidden=\"true\">{item.icon}</span>}\n <Text size=\"sm\" color=\"inherit\" className=\"dishui-button-menu-label\">{item.label}</Text>\n {selectedId !== undefined && <span className=\"dishui-button-menu-check\" aria-hidden=\"true\">{selectedId === item.id && <Check />}</span>}\n </button>)}\n </div>, document.body)}\n </>;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Metric2.js","names":[],"sources":["../../../src/components/Card/Metric.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\nimport './Metric.css';\n\nexport type CardMetricItem = {\n /** Stable identity for items that may be reordered. */\n key?: React.Key;\n label: React.ReactNode;\n value: React.ReactNode;\n};\n\nexport type CardMetricProps = Omit<React.HTMLAttributes<HTMLElement>, 'title' | 'children'> & {\n title: React.ReactNode;\n meta?: React.ReactNode;\n period?: React.ReactNode;\n value: React.ReactNode;\n description?: React.ReactNode;\n items?: CardMetricItem[];\n loading?: boolean;\n};\n\nconst EMPTY_ITEMS: CardMetricItem[] = [];\n\nexport const CardMetric = ({\n title, meta, period, value, description, items = EMPTY_ITEMS, loading = false,\n className, ...rest\n}: CardMetricProps) => (\n <article {...rest} className={cn('dishui-card-metric', className)} aria-busy={loading || undefined}>\n <div className=\"dishui-card-metric__body\">\n {((meta !== null && meta !== undefined) || (period !== null && period !== undefined)) && (\n <div className=\"dishui-card-metric__meta\">\n <span>{meta}</span>\n <span className=\"dishui-card-metric__period\">{period}</span>\n </div>\n )}\n <h3 className=\"dishui-card-metric__title\">{title}</h3>\n <div className=\"dishui-card-metric__value\">\n {loading ? <span className=\"dishui-card-metric__skeleton\" aria-hidden=\"true\" /> : value}\n </div>\n {description !== null && description !== undefined && <div className=\"dishui-card-metric__description\">{description}</div>}\n </div>\n {items.length > 0 && (\n <dl className=\"dishui-card-metric__footer\">\n {items.map((item, index) => (\n <div className=\"dishui-card-metric__item\" key={item.key ?? index}>\n <dt>{item.label}</dt>\n <dd>{loading ? <span className=\"dishui-card-metric__skeleton\" aria-hidden=\"true\" /> : item.value}</dd>\n </div>\n ))}\n </dl>\n )}\n </article>\n);\n"],"mappings":";;;;;AAqBA,
|
|
1
|
+
{"version":3,"file":"Metric2.js","names":["EMPTY_ITEMS","CardMetric","rest","cn","className","loading","meta","period","title","value","description","items","item","index"],"sources":["../../../src/components/Card/Metric.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\nimport './Metric.css';\n\nexport type CardMetricItem = {\n /** Stable identity for items that may be reordered. */\n key?: React.Key;\n label: React.ReactNode;\n value: React.ReactNode;\n};\n\nexport type CardMetricProps = Omit<React.HTMLAttributes<HTMLElement>, 'title' | 'children'> & {\n title: React.ReactNode;\n meta?: React.ReactNode;\n period?: React.ReactNode;\n value: React.ReactNode;\n description?: React.ReactNode;\n items?: CardMetricItem[];\n loading?: boolean;\n};\n\nconst EMPTY_ITEMS: CardMetricItem[] = [];\n\nexport const CardMetric = ({\n title, meta, period, value, description, items = EMPTY_ITEMS, loading = false,\n className, ...rest\n}: CardMetricProps) => (\n <article {...rest} className={cn('dishui-card-metric', className)} aria-busy={loading || undefined}>\n <div className=\"dishui-card-metric__body\">\n {((meta !== null && meta !== undefined) || (period !== null && period !== undefined)) && (\n <div className=\"dishui-card-metric__meta\">\n <span>{meta}</span>\n <span className=\"dishui-card-metric__period\">{period}</span>\n </div>\n )}\n <h3 className=\"dishui-card-metric__title\">{title}</h3>\n <div className=\"dishui-card-metric__value\">\n {loading ? <span className=\"dishui-card-metric__skeleton\" aria-hidden=\"true\" /> : value}\n </div>\n {description !== null && description !== undefined && <div className=\"dishui-card-metric__description\">{description}</div>}\n </div>\n {items.length > 0 && (\n <dl className=\"dishui-card-metric__footer\">\n {items.map((item, index) => (\n <div className=\"dishui-card-metric__item\" key={item.key ?? index}>\n <dt>{item.label}</dt>\n <dd>{loading ? <span className=\"dishui-card-metric__skeleton\" aria-hidden=\"true\" /> : item.value}</dd>\n </div>\n ))}\n </dl>\n )}\n </article>\n);\n"],"mappings":";;;;;AAqBA,IAAMA,IAAgC,CAAC,GAE1BC,KAAc,EACzB,UAAO,SAAM,WAAQ,UAAO,gBAAa,WAAQD,GAAa,aAAU,IACxE,cAAW,GAAGE,QAEd,kBAAC,WAAD;CAAS,GAAIA;CAAM,WAAWC,EAAG,sBAAsBC,CAAS;CAAG,aAAWC,KAAW,KAAA;CAAzF,UAAA,CACE,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;IACKC,KAAS,QAAgCC,KAAW,SACrD,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,QAAD,EAAA,UAAOD,EAAW,CAAA,GAClB,kBAAC,QAAD;KAAM,WAAU;KAA8B,UAAAC;IAAa,CAAA,CACxD;;GAEP,kBAAC,MAAD;IAAI,WAAU;IAA6B,UAAAC;GAAU,CAAA;GACrD,kBAAC,OAAD;IAAK,WAAU;IACZ,UAAAH,IAAU,kBAAC,QAAD;KAAM,WAAU;KAA+B,eAAY;IAAQ,CAAA,IAAII;GAC/E,CAAA;GACJC,KAAgB,QAAqC,kBAAC,OAAD;IAAK,WAAU;IAAmC,UAAAA;GAAiB,CAAA;EACtH;CACJ,CAAA,GAAAC,EAAM,SAAS,KACd,kBAAC,MAAD;EAAI,WAAU;EACX,UAAAA,EAAM,KAAK,GAAM,MAChB,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,kBAAC,MAAD,EAAA,UAAKC,EAAK,MAAU,CAAA,GACpB,kBAAC,MAAD,EAAA,UAAKP,IAAU,kBAAC,QAAD;IAAM,WAAU;IAA+B,eAAY;GAAQ,CAAA,IAAIO,EAAK,MAAU,CAAA,CAClG;EAH0C,GAAAA,EAAK,OAAOC,CAGtD,CACN;CACC,CAAA,CAEC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Ticket2.js","names":[],"sources":["../../../src/components/Card/Ticket.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { cn } from '../../utils/cn';\nimport './Ticket.css';\n\nexport type CardTicketTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\nexport type CardTicketPriorityLevel = 'none' | 'lowest' | 'low' | 'medium' | 'high' | 'highest';\n\nexport type CardTicketStatus = {\n label: React.ReactNode;\n tone?: CardTicketTone;\n};\n\nexport type CardTicketIssueType = {\n label: React.ReactNode;\n icon?: React.ReactNode;\n tone?: CardTicketTone;\n};\n\nexport type CardTicketAssignee = {\n id?: React.Key;\n name: string;\n avatarUrl?: string;\n avatarAlt?: string;\n};\n\nexport type CardTicketPriority = {\n level: CardTicketPriorityLevel;\n label?: React.ReactNode;\n};\n\nexport type CardTicketLabel = {\n id?: React.Key;\n label: React.ReactNode;\n};\n\nexport type CardTicketSubtaskProgress = {\n completed: number;\n total: number;\n label?: React.ReactNode;\n};\n\nexport type CardTicketProps = Omit<React.HTMLAttributes<HTMLElement>, 'title' | 'id' | 'onClick'> & {\n /** DOM id for linking the ticket to other UI. Use React's reserved `key` separately in lists. */\n id?: string;\n /** Human-facing issue key, for example `WEB-142`. */\n issueKey?: React.ReactNode;\n title: React.ReactNode;\n description?: React.ReactNode;\n status?: CardTicketStatus | React.ReactNode;\n issueType?: CardTicketIssueType | React.ReactNode;\n assignees?: CardTicketAssignee[];\n priority?: CardTicketPriority | CardTicketPriorityLevel;\n labels?: Array<CardTicketLabel | React.ReactNode>;\n dueDate?: React.ReactNode;\n estimate?: React.ReactNode;\n subtaskProgress?: CardTicketSubtaskProgress;\n selected?: boolean;\n disabled?: boolean;\n onClick?: React.MouseEventHandler<HTMLElement>;\n className?: string;\n};\n\nconst EMPTY_ASSIGNEES: CardTicketAssignee[] = [];\nconst EMPTY_LABELS: Array<CardTicketLabel | React.ReactNode> = [];\n\nconst PRIORITY_LABELS: Record<CardTicketPriorityLevel, string> = {\n none: 'No priority',\n lowest: 'Lowest priority',\n low: 'Low priority',\n medium: 'Medium priority',\n high: 'High priority',\n highest: 'Highest priority',\n};\n\nconst getInitials = (name: string) => {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '?';\n return parts.slice(0, 2).map(part => Array.from(part)[0]).join('').toUpperCase();\n};\n\nconst DefaultIssueIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <rect x=\"2.5\" y=\"2.5\" width=\"11\" height=\"11\" rx=\"2\" stroke=\"currentColor\" />\n <path d=\"M5 6h6M5 8.5h4.5\" stroke=\"currentColor\" strokeLinecap=\"round\" />\n </svg>\n);\n\nconst MetaIcon = ({ type }: { type: 'calendar' | 'estimate' | 'subtask' }) => {\n if (type === 'calendar') return <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><rect x=\"2.5\" y=\"3.5\" width=\"11\" height=\"10\" rx=\"2\" stroke=\"currentColor\" /><path d=\"M5 2v3M11 2v3M3 6.5h10\" stroke=\"currentColor\" /></svg>;\n if (type === 'estimate') return <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><circle cx=\"8\" cy=\"8\" r=\"5.5\" stroke=\"currentColor\" /><path d=\"M8 5v3.5l2 1\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>;\n return <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><rect x=\"2.5\" y=\"2.5\" width=\"11\" height=\"11\" rx=\"2\" stroke=\"currentColor\" /><path d=\"m5 8 2 2 4-4\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>;\n};\n\nconst TicketAvatar = ({ assignee }: { assignee: CardTicketAssignee }) => {\n const [failed, setFailed] = useState(false);\n const showImage = !!assignee.avatarUrl && !failed;\n\n return (\n <span className=\"dishui-card-ticket__avatar\" title={assignee.name} aria-label={assignee.name}>\n {showImage ? (\n <img\n src={assignee.avatarUrl}\n alt={assignee.avatarAlt ?? ''}\n onError={() => setFailed(true)}\n />\n ) : (\n <span aria-hidden=\"true\">{getInitials(assignee.name)}</span>\n )}\n </span>\n );\n};\n\nconst normalizeStatus = (status: CardTicketProps['status']): CardTicketStatus | undefined => {\n if (status === null || status === undefined) return undefined;\n if (typeof status === 'object' && !React.isValidElement(status) && 'label' in status) return status as CardTicketStatus;\n return { label: status, tone: 'neutral' };\n};\n\nconst normalizeIssueType = (issueType: CardTicketProps['issueType']): CardTicketIssueType | undefined => {\n if (issueType === null || issueType === undefined) return undefined;\n if (typeof issueType === 'object' && !React.isValidElement(issueType) && 'label' in issueType) return issueType as CardTicketIssueType;\n return { label: issueType, tone: 'neutral' };\n};\n\nexport const CardTicket = ({\n id,\n issueKey,\n title,\n description,\n status,\n issueType,\n assignees = EMPTY_ASSIGNEES,\n priority = 'none',\n labels = EMPTY_LABELS,\n dueDate,\n estimate,\n subtaskProgress,\n selected = false,\n disabled = false,\n onClick,\n className,\n ...rest\n}: CardTicketProps) => {\n const interactive = !!onClick;\n const statusValue = normalizeStatus(status);\n const issueTypeValue = normalizeIssueType(issueType);\n const priorityValue = typeof priority === 'string' ? { level: priority } : priority;\n const priorityLabel = priorityValue.label ?? PRIORITY_LABELS[priorityValue.level];\n const completed = Math.max(0, subtaskProgress?.completed ?? 0);\n const total = Math.max(0, subtaskProgress?.total ?? 0);\n const progress = total > 0 ? Math.min(100, (completed / total) * 100) : 0;\n\n return (\n <article\n {...rest}\n id={id}\n className={cn(\n 'dishui-card-ticket',\n interactive && !disabled && 'dishui-card-ticket--interactive',\n selected && 'dishui-card-ticket--selected',\n disabled && 'dishui-card-ticket--disabled',\n className,\n )}\n role={interactive ? 'button' : undefined}\n tabIndex={interactive && !disabled ? 0 : undefined}\n aria-pressed={interactive ? selected : undefined}\n aria-disabled={disabled || undefined}\n onClick={interactive && !disabled ? onClick : undefined}\n onKeyDown={interactive && !disabled ? event => {\n if (event.target !== event.currentTarget) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n if (!event.repeat) event.currentTarget.click();\n }\n } : undefined}\n >\n <div className=\"dishui-card-ticket__header\">\n {issueTypeValue && (\n <span\n className={cn('dishui-card-ticket__type', `dishui-card-ticket__type--${issueTypeValue.tone ?? 'neutral'}`)}\n title={typeof issueTypeValue.label === 'string' ? issueTypeValue.label : undefined}\n >\n <span className=\"dishui-card-ticket__type-icon\" aria-hidden=\"true\">{issueTypeValue.icon ?? <DefaultIssueIcon />}</span>\n <span className=\"dishui-card-ticket__type-label\">{issueTypeValue.label}</span>\n </span>\n )}\n {issueKey !== null && issueKey !== undefined && <span className=\"dishui-card-ticket__key\">{issueKey}</span>}\n {statusValue && (\n <span className={cn('dishui-card-ticket__status', `dishui-card-ticket__status--${statusValue.tone ?? 'neutral'}`)}>\n {statusValue.label}\n </span>\n )}\n </div>\n\n <h3 className=\"dishui-card-ticket__title\">{title}</h3>\n {description !== null && description !== undefined && <div className=\"dishui-card-ticket__description\">{description}</div>}\n\n {labels.length > 0 && (\n <div className=\"dishui-card-ticket__labels\" aria-label=\"Labels\">\n {labels.map((item, index) => {\n const value = typeof item === 'object' && item !== null && !React.isValidElement(item) && 'label' in item\n ? item as CardTicketLabel\n : { label: item };\n return <span className=\"dishui-card-ticket__label\" key={value.id ?? index}>{value.label}</span>;\n })}\n </div>\n )}\n\n <div className=\"dishui-card-ticket__footer\">\n <span\n className={cn('dishui-card-ticket__priority', `dishui-card-ticket__priority--${priorityValue.level}`)}\n title={typeof priorityLabel === 'string' ? priorityLabel : undefined}\n >\n <span className=\"dishui-card-ticket__priority-bars\" aria-hidden=\"true\"><i /><i /><i /></span>\n <span>{priorityLabel}</span>\n </span>\n\n <div className=\"dishui-card-ticket__metadata\">\n {dueDate !== null && dueDate !== undefined && <span className=\"dishui-card-ticket__meta\"><MetaIcon type=\"calendar\" /><span>{dueDate}</span></span>}\n {estimate !== null && estimate !== undefined && <span className=\"dishui-card-ticket__meta\"><MetaIcon type=\"estimate\" /><span>{estimate}</span></span>}\n {subtaskProgress && (\n <span className=\"dishui-card-ticket__meta dishui-card-ticket__subtasks\" aria-label={typeof subtaskProgress.label === 'string' ? subtaskProgress.label : `${completed} of ${total} subtasks complete`}>\n <MetaIcon type=\"subtask\" />\n <span>{subtaskProgress.label ?? `${completed}/${total}`}</span>\n <span className=\"dishui-card-ticket__progress\" aria-hidden=\"true\"><span style={{ width: `${progress}%` }} /></span>\n </span>\n )}\n </div>\n\n {assignees.length > 0 && (\n <div className=\"dishui-card-ticket__assignees\" aria-label=\"Assignees\">\n {assignees.map((assignee, index) => <TicketAvatar key={assignee.id ?? `${assignee.name}-${index}`} assignee={assignee} />)}\n </div>\n )}\n </div>\n </article>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Ticket2.js","names":["React","EMPTY_ASSIGNEES","EMPTY_LABELS","PRIORITY_LABELS","getInitials","parts","name","part","DefaultIssueIcon","MetaIcon","type","TicketAvatar","failed","setFailed","useState","showImage","assignee","normalizeStatus","status","normalizeIssueType","issueType","CardTicket","rest","interactive","onClick","statusValue","issueTypeValue","priorityValue","priority","priorityLabel","completed","subtaskProgress","total","progress","cn","disabled","selected","className","event","issueKey","title","description","labels","value","item","index","dueDate","estimate","assignees"],"sources":["../../../src/components/Card/Ticket.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { cn } from '../../utils/cn';\nimport './Ticket.css';\n\nexport type CardTicketTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\nexport type CardTicketPriorityLevel = 'none' | 'lowest' | 'low' | 'medium' | 'high' | 'highest';\n\nexport type CardTicketStatus = {\n label: React.ReactNode;\n tone?: CardTicketTone;\n};\n\nexport type CardTicketIssueType = {\n label: React.ReactNode;\n icon?: React.ReactNode;\n tone?: CardTicketTone;\n};\n\nexport type CardTicketAssignee = {\n id?: React.Key;\n name: string;\n avatarUrl?: string;\n avatarAlt?: string;\n};\n\nexport type CardTicketPriority = {\n level: CardTicketPriorityLevel;\n label?: React.ReactNode;\n};\n\nexport type CardTicketLabel = {\n id?: React.Key;\n label: React.ReactNode;\n};\n\nexport type CardTicketSubtaskProgress = {\n completed: number;\n total: number;\n label?: React.ReactNode;\n};\n\nexport type CardTicketProps = Omit<React.HTMLAttributes<HTMLElement>, 'title' | 'id' | 'onClick'> & {\n /** DOM id for linking the ticket to other UI. Use React's reserved `key` separately in lists. */\n id?: string;\n /** Human-facing issue key, for example `WEB-142`. */\n issueKey?: React.ReactNode;\n title: React.ReactNode;\n description?: React.ReactNode;\n status?: CardTicketStatus | React.ReactNode;\n issueType?: CardTicketIssueType | React.ReactNode;\n assignees?: CardTicketAssignee[];\n priority?: CardTicketPriority | CardTicketPriorityLevel;\n labels?: Array<CardTicketLabel | React.ReactNode>;\n dueDate?: React.ReactNode;\n estimate?: React.ReactNode;\n subtaskProgress?: CardTicketSubtaskProgress;\n selected?: boolean;\n disabled?: boolean;\n onClick?: React.MouseEventHandler<HTMLElement>;\n className?: string;\n};\n\nconst EMPTY_ASSIGNEES: CardTicketAssignee[] = [];\nconst EMPTY_LABELS: Array<CardTicketLabel | React.ReactNode> = [];\n\nconst PRIORITY_LABELS: Record<CardTicketPriorityLevel, string> = {\n none: 'No priority',\n lowest: 'Lowest priority',\n low: 'Low priority',\n medium: 'Medium priority',\n high: 'High priority',\n highest: 'Highest priority',\n};\n\nconst getInitials = (name: string) => {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '?';\n return parts.slice(0, 2).map(part => Array.from(part)[0]).join('').toUpperCase();\n};\n\nconst DefaultIssueIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <rect x=\"2.5\" y=\"2.5\" width=\"11\" height=\"11\" rx=\"2\" stroke=\"currentColor\" />\n <path d=\"M5 6h6M5 8.5h4.5\" stroke=\"currentColor\" strokeLinecap=\"round\" />\n </svg>\n);\n\nconst MetaIcon = ({ type }: { type: 'calendar' | 'estimate' | 'subtask' }) => {\n if (type === 'calendar') return <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><rect x=\"2.5\" y=\"3.5\" width=\"11\" height=\"10\" rx=\"2\" stroke=\"currentColor\" /><path d=\"M5 2v3M11 2v3M3 6.5h10\" stroke=\"currentColor\" /></svg>;\n if (type === 'estimate') return <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><circle cx=\"8\" cy=\"8\" r=\"5.5\" stroke=\"currentColor\" /><path d=\"M8 5v3.5l2 1\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>;\n return <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><rect x=\"2.5\" y=\"2.5\" width=\"11\" height=\"11\" rx=\"2\" stroke=\"currentColor\" /><path d=\"m5 8 2 2 4-4\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>;\n};\n\nconst TicketAvatar = ({ assignee }: { assignee: CardTicketAssignee }) => {\n const [failed, setFailed] = useState(false);\n const showImage = !!assignee.avatarUrl && !failed;\n\n return (\n <span className=\"dishui-card-ticket__avatar\" title={assignee.name} aria-label={assignee.name}>\n {showImage ? (\n <img\n src={assignee.avatarUrl}\n alt={assignee.avatarAlt ?? ''}\n onError={() => setFailed(true)}\n />\n ) : (\n <span aria-hidden=\"true\">{getInitials(assignee.name)}</span>\n )}\n </span>\n );\n};\n\nconst normalizeStatus = (status: CardTicketProps['status']): CardTicketStatus | undefined => {\n if (status === null || status === undefined) return undefined;\n if (typeof status === 'object' && !React.isValidElement(status) && 'label' in status) return status as CardTicketStatus;\n return { label: status, tone: 'neutral' };\n};\n\nconst normalizeIssueType = (issueType: CardTicketProps['issueType']): CardTicketIssueType | undefined => {\n if (issueType === null || issueType === undefined) return undefined;\n if (typeof issueType === 'object' && !React.isValidElement(issueType) && 'label' in issueType) return issueType as CardTicketIssueType;\n return { label: issueType, tone: 'neutral' };\n};\n\nexport const CardTicket = ({\n id,\n issueKey,\n title,\n description,\n status,\n issueType,\n assignees = EMPTY_ASSIGNEES,\n priority = 'none',\n labels = EMPTY_LABELS,\n dueDate,\n estimate,\n subtaskProgress,\n selected = false,\n disabled = false,\n onClick,\n className,\n ...rest\n}: CardTicketProps) => {\n const interactive = !!onClick;\n const statusValue = normalizeStatus(status);\n const issueTypeValue = normalizeIssueType(issueType);\n const priorityValue = typeof priority === 'string' ? { level: priority } : priority;\n const priorityLabel = priorityValue.label ?? PRIORITY_LABELS[priorityValue.level];\n const completed = Math.max(0, subtaskProgress?.completed ?? 0);\n const total = Math.max(0, subtaskProgress?.total ?? 0);\n const progress = total > 0 ? Math.min(100, (completed / total) * 100) : 0;\n\n return (\n <article\n {...rest}\n id={id}\n className={cn(\n 'dishui-card-ticket',\n interactive && !disabled && 'dishui-card-ticket--interactive',\n selected && 'dishui-card-ticket--selected',\n disabled && 'dishui-card-ticket--disabled',\n className,\n )}\n role={interactive ? 'button' : undefined}\n tabIndex={interactive && !disabled ? 0 : undefined}\n aria-pressed={interactive ? selected : undefined}\n aria-disabled={disabled || undefined}\n onClick={interactive && !disabled ? onClick : undefined}\n onKeyDown={interactive && !disabled ? event => {\n if (event.target !== event.currentTarget) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n if (!event.repeat) event.currentTarget.click();\n }\n } : undefined}\n >\n <div className=\"dishui-card-ticket__header\">\n {issueTypeValue && (\n <span\n className={cn('dishui-card-ticket__type', `dishui-card-ticket__type--${issueTypeValue.tone ?? 'neutral'}`)}\n title={typeof issueTypeValue.label === 'string' ? issueTypeValue.label : undefined}\n >\n <span className=\"dishui-card-ticket__type-icon\" aria-hidden=\"true\">{issueTypeValue.icon ?? <DefaultIssueIcon />}</span>\n <span className=\"dishui-card-ticket__type-label\">{issueTypeValue.label}</span>\n </span>\n )}\n {issueKey !== null && issueKey !== undefined && <span className=\"dishui-card-ticket__key\">{issueKey}</span>}\n {statusValue && (\n <span className={cn('dishui-card-ticket__status', `dishui-card-ticket__status--${statusValue.tone ?? 'neutral'}`)}>\n {statusValue.label}\n </span>\n )}\n </div>\n\n <h3 className=\"dishui-card-ticket__title\">{title}</h3>\n {description !== null && description !== undefined && <div className=\"dishui-card-ticket__description\">{description}</div>}\n\n {labels.length > 0 && (\n <div className=\"dishui-card-ticket__labels\" aria-label=\"Labels\">\n {labels.map((item, index) => {\n const value = typeof item === 'object' && item !== null && !React.isValidElement(item) && 'label' in item\n ? item as CardTicketLabel\n : { label: item };\n return <span className=\"dishui-card-ticket__label\" key={value.id ?? index}>{value.label}</span>;\n })}\n </div>\n )}\n\n <div className=\"dishui-card-ticket__footer\">\n <span\n className={cn('dishui-card-ticket__priority', `dishui-card-ticket__priority--${priorityValue.level}`)}\n title={typeof priorityLabel === 'string' ? priorityLabel : undefined}\n >\n <span className=\"dishui-card-ticket__priority-bars\" aria-hidden=\"true\"><i /><i /><i /></span>\n <span>{priorityLabel}</span>\n </span>\n\n <div className=\"dishui-card-ticket__metadata\">\n {dueDate !== null && dueDate !== undefined && <span className=\"dishui-card-ticket__meta\"><MetaIcon type=\"calendar\" /><span>{dueDate}</span></span>}\n {estimate !== null && estimate !== undefined && <span className=\"dishui-card-ticket__meta\"><MetaIcon type=\"estimate\" /><span>{estimate}</span></span>}\n {subtaskProgress && (\n <span className=\"dishui-card-ticket__meta dishui-card-ticket__subtasks\" aria-label={typeof subtaskProgress.label === 'string' ? subtaskProgress.label : `${completed} of ${total} subtasks complete`}>\n <MetaIcon type=\"subtask\" />\n <span>{subtaskProgress.label ?? `${completed}/${total}`}</span>\n <span className=\"dishui-card-ticket__progress\" aria-hidden=\"true\"><span style={{ width: `${progress}%` }} /></span>\n </span>\n )}\n </div>\n\n {assignees.length > 0 && (\n <div className=\"dishui-card-ticket__assignees\" aria-label=\"Assignees\">\n {assignees.map((assignee, index) => <TicketAvatar key={assignee.id ?? `${assignee.name}-${index}`} assignee={assignee} />)}\n </div>\n )}\n </div>\n </article>\n );\n};\n"],"mappings":"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"}
|