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/Select/index.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useId, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport interface Option {\n value: string | number;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectProps {\n /** Accessible name for the combobox. */\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n /** Optional ID for the combobox; generated per instance when omitted. */\n id?: string;\n disabled?: boolean;\n options: Option[];\n value?: string | number | (string | number)[];\n onChange: (value: string | number | (string | number)[]) => void;\n placeholder?: string;\n multiple?: boolean;\n fixedHeight?: boolean;\n style?: React.CSSProperties; // Allow passing inline styles\n className?: string; // Allow passing CSS classes for the wrapper\n}\n\n// SVG component for the dropdown arrow\nconst DropdownArrow: React.FC<{ isOpen: boolean }> = ({ isOpen }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n style={{\n display: 'block',\n width: 16,\n height: 16,\n transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',\n transition: 'transform 200ms ease-in-out',\n }}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n);\n\n// SVG component for the remove button 'x'\nconst RemoveIcon: React.FC = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n);\n\n// Select Component Implementation using daisyUI/Tailwind\nconst Select: React.FC<SelectProps> = ({\n options,\n value,\n onChange,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n 'aria-describedby': ariaDescribedby,\n id,\n disabled = false,\n placeholder = 'Select...',\n multiple = false,\n fixedHeight = false,\n style,\n className // This className applies to the wrapper\n}) => {\n const generatedId = useId();\n const comboboxId = id ?? `select-${generatedId}`;\n const listboxId = `${comboboxId}-listbox`;\n const optionId = (option: Option) => `${listboxId}-${typeof option.value}-${encodeURIComponent(String(option.value))}`;\n const [open, setIsOpen] = useState(false);\n const isOpen = open && !disabled;\n if (disabled && open) setIsOpen(false);\n const [highlightedValue, setHighlightedValue] = useState<Option['value'] | null>(null);\n const [tooltipText, setTooltipText] = useState('');\n const [showArrow, setShowArrow] = useState(true);\n const [dropdownStyle, setDropdownStyle] = useState<React.CSSProperties>({});\n const wrapperRef = useRef<HTMLDivElement>(null);\n const comboboxRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null); // Ref for the header div\n const optionsListRef = useRef<HTMLUListElement>(null);\n // Tracks a touch/pen press on an option so a tap selects while a drag scrolls.\n // (pointerdown on touch must NOT preventDefault — that blocks native scrolling.)\n const touchPressRef = useRef<{ pointerId: number; x: number; y: number } | null>(null);\n const touchTapRef = useRef(false);\n\n useEffect(() => {\n if (!isOpen) return;\n const handlePointerDown = (event: MouseEvent) => {\n const target = event.target as Node;\n if (wrapperRef.current?.contains(target) || optionsListRef.current?.contains(target)) return;\n setIsOpen(false);\n };\n document.addEventListener('pointerdown', handlePointerDown);\n\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown);\n };\n }, [isOpen]);\n\n const selectedValuesArray = useMemo(() => Array.isArray(value) ? value : (value !== undefined && value !== null ? [value] : []), [value]);\n\n const enabledIndices = options.flatMap((option, index) => option.disabled ? [] : [index]);\n const selectedIndex = options.findIndex(option => !option.disabled && selectedValuesArray.includes(option.value));\n const storedIndex = options.findIndex(option => !option.disabled && option.value === highlightedValue);\n // Derive a valid active option even when options are removed, reordered or disabled.\n const highlightedIndex = storedIndex >= 0 ? storedIndex : selectedIndex >= 0 ? selectedIndex : enabledIndices[0] ?? -1;\n\n\n const handleBlur = (event: React.FocusEvent) => {\n const next = event.relatedTarget as Node | null;\n if (!next || (!wrapperRef.current?.contains(next) && !optionsListRef.current?.contains(next))) {\n setIsOpen(false);\n }\n };\n\n const updateDropdownPosition = useCallback(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return;\n const rect = wrapper.getBoundingClientRect();\n const estimatedHeight = Math.min(options.length, 8) * 36 + 8;\n const fitsBelow = rect.bottom + 4 + estimatedHeight <= window.innerHeight;\n setDropdownStyle({\n position: 'fixed',\n left: rect.left,\n top: fitsBelow ? rect.bottom + 4 : Math.max(8, rect.top - estimatedHeight - 4),\n width: rect.width,\n zIndex: 10000,\n });\n }, [options.length]);\n\n useEffect(() => {\n if (!isOpen) return;\n updateDropdownPosition();\n window.addEventListener('resize', updateDropdownPosition);\n window.addEventListener('scroll', updateDropdownPosition, true);\n return () => {\n window.removeEventListener('resize', updateDropdownPosition);\n window.removeEventListener('scroll', updateDropdownPosition, true);\n };\n }, [isOpen, updateDropdownPosition]);\n\n // Hide the decorative arrow when the control becomes too narrow to reserve\n // space for both it and a useful amount of label text.\n useEffect(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return;\n const update = () => setShowArrow(wrapper.clientWidth >= 88);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(wrapper);\n return () => observer.disconnect();\n }, []);\n\n // Scroll after React commits the new active option, not using the previous index.\n useEffect(() => {\n if (isOpen && optionsListRef.current && highlightedIndex >= 0) {\n const list = optionsListRef.current;\n const optionElement = list.children[highlightedIndex] as HTMLLIElement;\n if (optionElement) {\n const listRect = list.getBoundingClientRect();\n const optionRect = optionElement.getBoundingClientRect();\n\n if (optionRect.bottom > listRect.bottom) {\n list.scrollTop += optionRect.bottom - listRect.bottom;\n } else if (optionRect.top < listRect.top) {\n list.scrollTop -= listRect.top - optionRect.top;\n }\n }\n }\n }, [isOpen, highlightedIndex]);\n\n const openDropdown = (edge: 'first' | 'last' = 'first') => {\n if (disabled) return;\n const index = selectedIndex >= 0 ? selectedIndex : edge === 'last' ? enabledIndices.at(-1) : enabledIndices[0];\n setHighlightedValue(index !== undefined && index >= 0 ? options[index].value : null);\n setIsOpen(true);\n updateDropdownPosition();\n };\n\n const toggleDropdown = () => {\n if (disabled) return;\n comboboxRef.current?.focus({ preventScroll: true });\n if (isOpen) setIsOpen(false);\n else openDropdown();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Tab') {\n setIsOpen(false); // Preserve native Tab / Shift+Tab focus traversal, including tag buttons.\n return;\n }\n if (event.target !== comboboxRef.current || disabled || event.defaultPrevented || event.nativeEvent.isComposing || event.altKey || event.ctrlKey || event.metaKey) return;\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n if (!isOpen) openDropdown(event.key === 'ArrowUp' ? 'last' : 'first');\n else if (enabledIndices.length) {\n const current = enabledIndices.indexOf(highlightedIndex);\n const step = event.key === 'ArrowDown' ? 1 : -1;\n const next = enabledIndices[(current + step + enabledIndices.length) % enabledIndices.length];\n setHighlightedValue(options[next].value);\n }\n break;\n }\n case 'Home':\n case 'End': {\n if (!isOpen) openDropdown();\n const next = event.key === 'Home' ? enabledIndices[0] : enabledIndices.at(-1);\n setHighlightedValue(next === undefined ? null : options[next].value);\n break;\n }\n case 'Enter':\n case ' ':\n if (!isOpen) openDropdown();\n else if (highlightedIndex >= 0) handleOptionClick(options[highlightedIndex]);\n break;\n case 'Escape':\n if (!isOpen) return;\n setIsOpen(false);\n break;\n default:\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n };\n\n const handleOptionClick = (option: Option) => {\n if (disabled || option.disabled) return;\n setHighlightedValue(option.value);\n comboboxRef.current?.focus({ preventScroll: true });\n if (multiple) {\n const currentValues = Array.isArray(value) ? value : [];\n let newValue;\n if (currentValues.includes(option.value)) {\n newValue = currentValues.filter(v => v !== option.value);\n } else {\n newValue = [...currentValues, option.value];\n }\n onChange(newValue);\n } else {\n onChange(option.value);\n setIsOpen(false); // Close dropdown on single select\n }\n };\n\n // Mouse: select immediately on press (existing desktop behavior).\n // Touch/pen: confirm a tap on pointerup, then select on click. Unmounting the\n // option on pointerup would send compatibility mouse events to the page behind\n // the portal, stealing focus. preventDefault() on a\n // touch pointerdown suppresses the browser's native pan gesture, which made\n // long dropdowns impossible to scroll on mobile (and every scroll attempt\n // selected an option instead).\n const handleOptionPointerDown = (event: React.PointerEvent<HTMLLIElement>, option: Option) => {\n touchTapRef.current = false;\n if (event.pointerType === 'mouse') {\n event.preventDefault();\n event.stopPropagation();\n handleOptionClick(option);\n return;\n }\n event.stopPropagation();\n touchPressRef.current = { pointerId: event.pointerId, x: event.clientX, y: event.clientY };\n };\n\n const handleOptionPointerUp = (event: React.PointerEvent<HTMLLIElement>) => {\n const press = touchPressRef.current;\n touchPressRef.current = null;\n if (!press || event.pointerId !== press.pointerId) return;\n // Select only if the finger did not move much — otherwise it was a scroll.\n const moved = Math.hypot(event.clientX - press.x, event.clientY - press.y);\n touchTapRef.current = moved < 10;\n event.stopPropagation();\n };\n\n const handleOptionPointerCancel = () => {\n touchPressRef.current = null;\n touchTapRef.current = false;\n };\n\n const handleRemoveItem = (e: React.MouseEvent, itemValue: string | number) => {\n e.stopPropagation(); // Prevent dropdown from opening/closing\n if (disabled || options.find(option => option.value === itemValue)?.disabled) return;\n comboboxRef.current?.focus({ preventScroll: true });\n const currentValues = Array.isArray(value) ? value : [];\n onChange(currentValues.filter(v => v !== itemValue));\n };\n\n // Update tooltip text and check for overflow\n useEffect(() => {\n if (multiple && headerRef.current) {\n const header = headerRef.current;\n const selectedLabels = options\n .filter(opt => selectedValuesArray.includes(opt.value))\n .map(opt => opt.label)\n .join(', ');\n\n // Check if the content (scrollWidth) exceeds the visible area (clientWidth)\n const isOverflowing = header.scrollWidth > header.clientWidth;\n setTooltipText(isOverflowing ? selectedLabels : ''); // Only set text if overflowing\n } else {\n setTooltipText(''); // Clear tooltip for single select or empty multi-select\n }\n }, [multiple, options, selectedValuesArray]);\n\n\n const renderSelectedValue = () => {\n if (selectedValuesArray.length === 0) {\n return <span className=\"text-base-content/60 italic\">{placeholder}</span>;\n }\n\n const selectedOptions = options.filter(opt => selectedValuesArray.includes(opt.value));\n\n if (multiple) {\n const isFixed = fixedHeight;\n // Apply overflow-x-auto for horizontal scrolling in fixedHeight mode\n const containerClasses = `\n flex gap-1 \n ${isFixed ? 'flex-nowrap overflow-x-auto overflow-y-hidden' : 'flex-wrap overflow-hidden'} // Enable horizontal scroll, hide vertical scrollbar if any\n ${tooltipText ? 'tooltip tooltip-bottom' : ''} // Keep tooltip for overflow\n `;\n // Removed showEllipsisPrefix\n\n return (\n <div\n ref={headerRef}\n className={containerClasses}\n data-tip={tooltipText ? tooltipText : undefined} // Keep tooltip logic\n // Add scrollbar styling if desired (e.g., using ::-webkit-scrollbar pseudo-element via CSS or a utility)\n style={{\n scrollbarWidth: 'thin',\n // 为固定高度模式添加右侧内边距,避免与下拉图标重叠\n ...(isFixed ? { paddingRight: '1.75rem' } : {})\n }}\n >\n {/* Removed wrapper for ellipsis and its popup */}\n\n {/* Render the badges */}\n {selectedOptions.map(option => (\n <span key={optionId(option)} className=\"badge badge-ghost gap-1 text-xs items-center whitespace-nowrap flex-shrink-0\">\n {option.label}\n <button\n type=\"button\"\n disabled={disabled || option.disabled}\n onClick={(e) => handleRemoveItem(e, option.value)}\n className=\"btn btn-xs btn-ghost btn-circle p-0 m-0 hover:bg-error hover:text-error-content\"\n aria-label={`Remove ${option.label}`}\n >\n <RemoveIcon />\n </button>\n </span>\n ))}\n </div>\n );\n } else {\n const selectedOption = options.find(opt => opt.value === selectedValuesArray[0]);\n return selectedOption ? <span className=\"truncate\">{selectedOption.label}</span> : <span className=\"text-base-content/60 italic\">{placeholder}</span>;\n }\n };\n\n // Match the default control height to a normal line of form text. Multi-select\n // may still grow when wrapping tags unless fixedHeight is requested.\n const selectClasses = `\n relative border border-base-300 rounded-lg bg-base-100 w-full\n flex justify-between items-center cursor-pointer px-3 text-sm\n focus:outline-none focus:ring-2 focus:ring-primary focus:ring-opacity-50\n hover:border-base-content/30\n ${multiple\n ? (fixedHeight ? 'h-8' : 'min-h-8 h-auto py-1')\n : 'h-8'}\n `;\n\n return (\n <div\n ref={wrapperRef}\n style={style}\n className={`relative w-full font-sans select-none ${className || ''}`}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n >\n {/* Header */}\n <div\n ref={comboboxRef}\n id={comboboxId}\n tabIndex={disabled ? -1 : 0}\n className={`${selectClasses} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`}\n onClick={toggleDropdown}\n\n role=\"combobox\"\n aria-label={ariaLabel ?? (ariaLabelledby ? undefined : placeholder)}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n aria-disabled={disabled || undefined}\n aria-controls={isOpen ? listboxId : undefined}\n aria-activedescendant={isOpen && highlightedIndex >= 0 ? optionId(options[highlightedIndex]) : undefined}\n >\n <div\n className=\"flex-1 min-w-0 overflow-hidden\"\n style={{ paddingRight: showArrow ? 28 : 0 }}\n >\n {renderSelectedValue()}\n </div>\n {/* Inline positioning avoids utility CSS/theme overrides moving the icon. */}\n {showArrow && (\n <div\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n right: 10,\n top: '50%',\n transform: 'translateY(-50%)',\n pointerEvents: 'none',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 16,\n height: 16,\n }}\n >\n <DropdownArrow isOpen={isOpen} />\n </div>\n )}\n </div>\n\n {/* Dropdown Options */}\n {isOpen && typeof document !== 'undefined' && createPortal(\n <ul\n ref={optionsListRef}\n id={listboxId}\n className=\"bg-base-100 border border-base-300 rounded-md shadow-lg list-none p-0 m-0 max-h-60 overflow-y-auto focus:outline-none\"\n style={{ ...dropdownStyle, touchAction: 'pan-y' }}\n onPointerDown={(event) => event.stopPropagation()}\n role=\"listbox\"\n aria-labelledby={ariaLabelledby ?? comboboxId}\n aria-multiselectable={multiple || undefined}\n // Keep DOM focus on the combobox even when touch focuses the portal.\n onFocus={() => comboboxRef.current?.focus({ preventScroll: true })}\n tabIndex={-1}\n >\n {options.length > 0 ? (\n options.map((option, index) => (\n <li\n key={optionId(option)}\n id={optionId(option)}\n className={`p-2 ${option.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:bg-base-200'} whitespace-nowrap overflow-hidden text-ellipsis ${index === highlightedIndex ? 'bg-base-300' : '' // Highlight style\n } ${selectedValuesArray.includes(option.value) && !multiple ? 'font-semibold bg-base-200' : '' // Style for selected single item\n } ${selectedValuesArray.includes(option.value) && multiple ? 'font-semibold' : '' // Style for selected multi items (less prominent background)\n }`}\n onPointerDown={(event) => handleOptionPointerDown(event, option)}\n onPointerUp={handleOptionPointerUp}\n onPointerCancel={handleOptionPointerCancel}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (touchTapRef.current || event.detail === 0) handleOptionClick(option);\n touchTapRef.current = false;\n }}\n onPointerMove={event => {\n // Scrolling under a stationary pointer must not undo keyboard navigation.\n if (event.pointerType === 'mouse' && (event.movementX || event.movementY) && !option.disabled) {\n setHighlightedValue(option.value);\n }\n }}\n role=\"option\"\n aria-disabled={option.disabled || undefined}\n aria-selected={selectedValuesArray.includes(option.value)}\n >\n {/* Optional: Add a checkmark or similar for selected items, especially in multi-select */}\n {option.label}\n </li>\n ))\n ) : (\n <li className=\"p-2 text-base-content/60 italic\">\n No options available\n </li>\n )}\n </ul>,\n document.body,\n )}\n </div>\n );\n};\n\nexport default Select; "],"mappings":";;;;AA4BA,IAAM,KAAgD,EAAE,gBACtD,kBAAC,OAAD;CACE,OAAM;CACN,MAAK;CACL,SAAQ;CACR,QAAO;CACP,aAAa;CACb,OAAO;EACL,SAAS;EACT,OAAO;EACP,QAAQ;EACR,WAAW,IAAS,mBAAmB;EACvC,YAAY;CACd;CAEA,UAAA,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,GAAE;CAAkB,CAAA;AACpE,CAAA,GAID,UACJ,kBAAC,OAAD;CAAK,OAAM;CAA6B,WAAU;CAAU,MAAK;CAAO,SAAQ;CAAY,QAAO;CAAe,aAAa;CAC7H,UAAA,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,GAAE;CAAwB,CAAA;AAC1E,CAAA,GAID,KAAiC,EACrC,YACA,UACA,aACA,cAAc,GACd,mBAAmB,GACnB,oBAAoB,GACpB,OACA,cAAW,IACX,iBAAc,aACd,cAAW,IACX,iBAAc,IACd,UACA,mBACI;CACJ,IAAM,IAAc,EAAM,GACpB,IAAa,KAAM,UAAU,KAC7B,IAAY,GAAG,EAAW,WAC1B,KAAY,MAAmB,GAAG,EAAU,GAAG,OAAO,EAAO,MAAM,GAAG,mBAAmB,OAAO,EAAO,KAAK,CAAC,KAC7G,CAAC,GAAM,KAAa,EAAS,EAAK,GAClC,IAAS,KAAQ,CAAC;CACxB,AAAI,KAAY,KAAM,EAAU,EAAK;CACrC,IAAM,CAAC,GAAkB,KAAuB,EAAiC,IAAI,GAC/E,CAAC,GAAa,KAAkB,EAAS,EAAE,GAC3C,CAAC,GAAW,KAAgB,EAAS,EAAI,GACzC,CAAC,GAAe,KAAoB,EAA8B,CAAC,CAAC,GACpE,IAAa,EAAuB,IAAI,GACxC,IAAc,EAAuB,IAAI,GACzC,IAAY,EAAuB,IAAI,GACvC,IAAiB,EAAyB,IAAI,GAG9C,IAAgB,EAA2D,IAAI,GAC/E,IAAc,EAAO,EAAK;CAEhC,QAAgB;EACd,IAAI,CAAC,GAAQ;EACb,IAAM,KAAqB,MAAsB;GAC/C,IAAM,IAAS,EAAM;GACjB,EAAW,SAAS,SAAS,CAAM,KAAK,EAAe,SAAS,SAAS,CAAM,KACnF,EAAU,EAAK;EACjB;EAGA,OAFA,SAAS,iBAAiB,eAAe,CAAiB,SAE7C;GACX,SAAS,oBAAoB,eAAe,CAAiB;EAC/D;CACF,GAAG,CAAC,CAAM,CAAC;CAEX,IAAM,IAAsB,QAAc,MAAM,QAAQ,CAAK,IAAI,IAAS,KAAiC,OAAiB,CAAC,IAAX,CAAC,CAAK,GAAS,CAAC,CAAK,CAAC,GAElI,IAAiB,EAAQ,SAAS,GAAQ,MAAU,EAAO,WAAW,CAAC,IAAI,CAAC,CAAK,CAAC,GAClF,IAAgB,EAAQ,WAAU,MAAU,CAAC,EAAO,YAAY,EAAoB,SAAS,EAAO,KAAK,CAAC,GAC1G,IAAc,EAAQ,WAAU,MAAU,CAAC,EAAO,YAAY,EAAO,UAAU,CAAgB,GAE/F,IAAmB,KAAe,IAAI,IAAc,KAAiB,IAAI,IAAgB,EAAe,MAAM,IAG9G,KAAc,MAA4B;EAC9C,IAAM,IAAO,EAAM;EACnB,CAAI,CAAC,KAAS,CAAC,EAAW,SAAS,SAAS,CAAI,KAAK,CAAC,EAAe,SAAS,SAAS,CAAI,MACzF,EAAU,EAAK;CAEnB,GAEM,IAAyB,QAAkB;EAC/C,IAAM,IAAU,EAAW;EAC3B,IAAI,CAAC,GAAS;EACd,IAAM,IAAO,EAAQ,sBAAsB,GACrC,IAAkB,KAAK,IAAI,EAAQ,QAAQ,CAAC,IAAI,KAAK,GACrD,IAAY,EAAK,SAAS,IAAI,KAAmB,OAAO;EAC9D,EAAiB;GACf,UAAU;GACV,MAAM,EAAK;GACX,KAAK,IAAY,EAAK,SAAS,IAAI,KAAK,IAAI,GAAG,EAAK,MAAM,IAAkB,CAAC;GAC7E,OAAO,EAAK;GACZ,QAAQ;EACV,CAAC;CACH,GAAG,CAAC,EAAQ,MAAM,CAAC;CA0BnB,AAxBA,QAAgB;EACT,OAIL,OAHA,EAAuB,GACvB,OAAO,iBAAiB,UAAU,CAAsB,GACxD,OAAO,iBAAiB,UAAU,GAAwB,EAAI,SACjD;GAEX,AADA,OAAO,oBAAoB,UAAU,CAAsB,GAC3D,OAAO,oBAAoB,UAAU,GAAwB,EAAI;EACnE;CACF,GAAG,CAAC,GAAQ,CAAsB,CAAC,GAInC,QAAgB;EACd,IAAM,IAAU,EAAW;EAC3B,IAAI,CAAC,GAAS;EACd,IAAM,UAAe,EAAa,EAAQ,eAAe,EAAE;EAC3D,EAAO;EACP,IAAM,IAAW,IAAI,eAAe,CAAM;EAE1C,OADA,EAAS,QAAQ,CAAO,SACX,EAAS,WAAW;CACnC,GAAG,CAAC,CAAC,GAGL,QAAgB;EACd,IAAI,KAAU,EAAe,WAAW,KAAoB,GAAG;GAC7D,IAAM,IAAO,EAAe,SACtB,IAAgB,EAAK,SAAS;GACpC,IAAI,GAAe;IACjB,IAAM,IAAW,EAAK,sBAAsB,GACtC,IAAa,EAAc,sBAAsB;IAEvD,AAAI,EAAW,SAAS,EAAS,SAC/B,EAAK,aAAa,EAAW,SAAS,EAAS,SACtC,EAAW,MAAM,EAAS,QACnC,EAAK,aAAa,EAAS,MAAM,EAAW;GAEhD;EACF;CACF,GAAG,CAAC,GAAQ,CAAgB,CAAC;CAE7B,IAAM,KAAgB,IAAyB,YAAY;EACzD,IAAI,GAAU;EACd,IAAM,IAAQ,KAAiB,IAAI,IAAgB,MAAS,SAAS,EAAe,GAAG,EAAE,IAAI,EAAe;EAG5G,AAFA,EAAoB,MAAU,KAAA,KAAa,KAAS,IAAI,EAAQ,EAAM,CAAC,QAAQ,IAAI,GACnF,EAAU,EAAI,GACd,EAAuB;CACzB,GAEM,WAAuB;EACvB,MACJ,EAAY,SAAS,MAAM,EAAE,eAAe,GAAK,CAAC,GAC9C,IAAQ,EAAU,EAAK,IACtB,EAAa;CACpB,GAEM,MAAiB,MAA+C;EACpE,IAAI,EAAM,QAAQ,OAAO;GACvB,EAAU,EAAK;GACf;EACF;EACI,QAAM,WAAW,EAAY,WAAW,KAAY,EAAM,oBAAoB,EAAM,YAAY,eAAe,EAAM,UAAU,EAAM,WAAW,EAAM,UAC1J;WAAQ,EAAM,KAAd;IACE,KAAK;IACL,KAAK;KACH,IAAI,CAAC,GAAQ,EAAa,EAAM,QAAQ,YAAY,SAAS,OAAO;UAC/D,IAAI,EAAe,QAAQ;MAC9B,IAAM,IAAU,EAAe,QAAQ,CAAgB,GACjD,IAAO,EAAM,QAAQ,cAAc,IAAI,IACvC,IAAO,GAAgB,IAAU,IAAO,EAAe,UAAU,EAAe;MACtF,EAAoB,EAAQ,EAAK,CAAC,KAAK;KACzC;KACA;IAEF,KAAK;IACL,KAAK,OAAO;KACV,AAAK,KAAQ,EAAa;KAC1B,IAAM,IAAO,EAAM,QAAQ,SAAS,EAAe,KAAK,EAAe,GAAG,EAAE;KAC5E,EAAoB,MAAS,KAAA,IAAY,OAAO,EAAQ,EAAK,CAAC,KAAK;KACnE;IACF;IACA,KAAK;IACL,KAAK;KACH,AAAK,IACI,KAAoB,KAAG,EAAkB,EAAQ,EAAiB,IAD9D,EAAa;KAE1B;IACF,KAAK;KACH,IAAI,CAAC,GAAQ;KACb,EAAU,EAAK;KACf;IACF,SACE;GACJ;GAEA,AADA,EAAM,eAAe,GACrB,EAAM,gBAAgB;EAFtB;CAGF,GAEM,KAAqB,MAAmB;EACxC,WAAY,EAAO,WAGvB;OAFA,EAAoB,EAAO,KAAK,GAChC,EAAY,SAAS,MAAM,EAAE,eAAe,GAAK,CAAC,GAC9C,GAAU;IACZ,IAAM,IAAgB,MAAM,QAAQ,CAAK,IAAI,IAAQ,CAAC,GAClD;IAMJ,AALA,AAGE,IAHE,EAAc,SAAS,EAAO,KAAK,IAC1B,EAAc,QAAO,MAAK,MAAM,EAAO,KAAK,IAE5C,CAAC,GAAG,GAAe,EAAO,KAAK,GAE5C,EAAS,CAAQ;GACnB,OAEE,AADA,EAAS,EAAO,KAAK,GACrB,EAAU,EAAK;EACjB;CACF,GASM,MAA2B,GAA0C,MAAmB;EAE5F,IADA,EAAY,UAAU,IAClB,EAAM,gBAAgB,SAAS;GAGjC,AAFA,EAAM,eAAe,GACrB,EAAM,gBAAgB,GACtB,EAAkB,CAAM;GACxB;EACF;EAEA,AADA,EAAM,gBAAgB,GACtB,EAAc,UAAU;GAAE,WAAW,EAAM;GAAW,GAAG,EAAM;GAAS,GAAG,EAAM;EAAQ;CAC3F,GAEM,MAAyB,MAA6C;EAC1E,IAAM,IAAQ,EAAc;EAE5B,IADA,EAAc,UAAU,MACpB,CAAC,KAAS,EAAM,cAAc,EAAM,WAAW;EAEnD,IAAM,IAAQ,KAAK,MAAM,EAAM,UAAU,EAAM,GAAG,EAAM,UAAU,EAAM,CAAC;EAEzE,AADA,EAAY,UAAU,IAAQ,IAC9B,EAAM,gBAAgB;CACxB,GAEM,WAAkC;EAEtC,AADA,EAAc,UAAU,MACxB,EAAY,UAAU;CACxB,GAEM,MAAoB,GAAqB,MAA+B;EAC5E,EAAE,gBAAgB,GACd,OAAY,EAAQ,MAAK,MAAU,EAAO,UAAU,CAAS,CAAC,EAAE,cACpE,EAAY,SAAS,MAAM,EAAE,eAAe,GAAK,CAAC,GAElD,GADsB,MAAM,QAAQ,CAAK,IAAI,IAAQ,CAAC,EAAA,CAC/B,QAAO,MAAK,MAAM,CAAS,CAAC;CACrD;CAGA,QAAgB;EACd,IAAI,KAAY,EAAU,SAAS;GACjC,IAAM,IAAS,EAAU,SACnB,IAAiB,EACpB,QAAO,MAAO,EAAoB,SAAS,EAAI,KAAK,CAAC,CAAC,CACtD,KAAI,MAAO,EAAI,KAAK,CAAC,CACrB,KAAK,IAAI,GAGN,IAAgB,EAAO,cAAc,EAAO;GAClD,EAAe,IAAgB,IAAiB,EAAE;EACpD,OACE,EAAe,EAAE;CAErB,GAAG;EAAC;EAAU;EAAS;CAAmB,CAAC;CAG3C,IAAM,WAA4B;EAChC,IAAI,EAAoB,WAAW,GACjC,OAAO,kBAAC,QAAD;GAAM,WAAU;GAA+B,UAAA;EAAkB,CAAA;EAG1E,IAAM,IAAkB,EAAQ,QAAO,MAAO,EAAoB,SAAS,EAAI,KAAK,CAAC;EAErF,IAAI,GAAU;GACZ,IAAM,IAAU;GAShB,OACE,kBAAC,OAAD;IACE,KAAK;IACL,WAAW;;UARX,IAAU,kDAAkD,4BAA4B;UACxF,IAAc,2BAA2B,GAAG;;IAQ5C,YAAU,KAA4B,KAAA;IAEtC,OAAO;KACL,gBAAgB;KAEhB,GAAI,IAAU,EAAE,cAAc,UAAU,IAAI,CAAC;IAC/C;IAKC,UAAA,EAAgB,KAAI,MACnB,kBAAC,QAAD;KAA6B,WAAU;KAAvC,UAAA,CACG,EAAO,OACR,kBAAC,UAAD;MACE,MAAK;MACL,UAAU,KAAY,EAAO;MAC7B,UAAU,MAAM,GAAiB,GAAG,EAAO,KAAK;MAChD,WAAU;MACV,cAAY,UAAU,EAAO;MAE7B,UAAA,kBAAC,GAAD,CAAa,CAAA;KACP,CAAA,CACJ;IAXK,GAAA,EAAS,CAAM,CAWpB,CACP;GACE,CAAA;EAET;EAAO;GACL,IAAM,IAAiB,EAAQ,MAAK,MAAO,EAAI,UAAU,EAAoB,EAAE;GAC/E,OAAO,IAAiB,kBAAC,QAAD;IAAM,WAAU;IAAY,UAAA,EAAe;GAAY,CAAA,IAAI,kBAAC,QAAD;IAAM,WAAU;IAA+B,UAAA;GAAkB,CAAA;EACtJ;CACF,GAIM,KAAgB;;;;;MAKlB,IACG,IAAc,QAAQ,wBACvB,MAAM;;CAGZ,OACE,kBAAC,OAAD;EACE,KAAK;EACE;EACP,WAAW,yCAAyC,KAAa;EACjE,QAAQ;EACR,WAAW;EALb,UAAA,CAQE,kBAAC,OAAD;GACE,KAAK;GACL,IAAI;GACJ,UAAU,IAAW,KAAK;GAC1B,WAAW,GAAG,GAAc,GAAG,IAAW,kCAAkC;GAC5E,SAAS;GAET,MAAK;GACL,cAAY,MAAc,IAAiB,KAAA,IAAY;GACvD,mBAAiB;GACjB,oBAAkB;GAClB,iBAAc;GACd,iBAAe;GACf,iBAAe,KAAY,KAAA;GAC3B,iBAAe,IAAS,IAAY,KAAA;GACpC,yBAAuB,KAAU,KAAoB,IAAI,EAAS,EAAQ,EAAiB,IAAI,KAAA;GAfjG,UAAA,CAiBE,kBAAC,OAAD;IACE,WAAU;IACV,OAAO,EAAE,cAAc,IAAY,KAAK,EAAE;IAEzC,UAAA,GAAoB;GAClB,CAAA,GAEJ,KACC,kBAAC,OAAD;IACE,eAAY;IACZ,OAAO;KACL,UAAU;KACV,OAAO;KACP,KAAK;KACL,WAAW;KACX,eAAe;KACf,SAAS;KACT,YAAY;KACZ,gBAAgB;KAChB,OAAO;KACP,QAAQ;IACV;IAEA,UAAA,kBAAC,GAAD,EAAuB,UAAS,CAAA;GAC7B,CAAA,CAEJ;EAGJ,CAAA,GAAA,KAAU,OAAO,WAAa,OAAe,EAC5C,kBAAC,MAAD;GACE,KAAK;GACL,IAAI;GACJ,WAAU;GACV,OAAO;IAAE,GAAG;IAAe,aAAa;GAAQ;GAChD,gBAAgB,MAAU,EAAM,gBAAgB;GAChD,MAAK;GACL,mBAAiB,KAAkB;GACnC,wBAAsB,KAAY,KAAA;GAElC,eAAe,EAAY,SAAS,MAAM,EAAE,eAAe,GAAK,CAAC;GACjE,UAAU;GAET,UAAA,EAAQ,SAAS,IAChB,EAAQ,KAAK,GAAQ,MACnB,kBAAC,MAAD;IAEE,IAAI,EAAS,CAAM;IACnB,WAAW,OAAO,EAAO,WAAW,kCAAkC,mCAAmC,mDAAmD,MAAU,IAAmB,gBAAgB,GACtM,GAAG,EAAoB,SAAS,EAAO,KAAK,KAAK,CAAC,IAAW,8BAA8B,GAC3F,GAAG,EAAoB,SAAS,EAAO,KAAK,KAAK,IAAW,kBAAkB;IAEjF,gBAAgB,MAAU,GAAwB,GAAO,CAAM;IAC/D,aAAa;IACb,iBAAiB;IACjB,UAAU,MAAU;KAIlB,AAHA,EAAM,eAAe,GACrB,EAAM,gBAAgB,IAClB,EAAY,WAAW,EAAM,WAAW,MAAG,EAAkB,CAAM,GACvE,EAAY,UAAU;IACxB;IACA,gBAAe,MAAS;KAEtB,AAAI,EAAM,gBAAgB,YAAY,EAAM,aAAa,EAAM,cAAc,CAAC,EAAO,YACnF,EAAoB,EAAO,KAAK;IAEpC;IACA,MAAK;IACL,iBAAe,EAAO,YAAY,KAAA;IAClC,iBAAe,EAAoB,SAAS,EAAO,KAAK;IAGvD,UAAA,EAAO;GACN,GA3BG,EAAS,CAAM,CA2BlB,CACL,IAED,kBAAC,MAAD;IAAI,WAAU;IAAkC,UAAA;GAE5C,CAAA;EAEJ,CAAA,GACJ,SAAS,IACX,CACG;;AAET"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["DropdownArrow","isOpen","RemoveIcon","Select","ariaLabel","ariaLabelledby","ariaDescribedby","generatedId","useId","comboboxId","id","listboxId","optionId","option","open","setIsOpen","useState","disabled","highlightedValue","setHighlightedValue","tooltipText","setTooltipText","showArrow","setShowArrow","dropdownStyle","setDropdownStyle","wrapperRef","useRef","comboboxRef","headerRef","optionsListRef","touchPressRef","touchTapRef","handlePointerDown","target","event","selectedValuesArray","useMemo","value","enabledIndices","options","index","selectedIndex","storedIndex","highlightedIndex","handleBlur","next","updateDropdownPosition","useCallback","wrapper","rect","estimatedHeight","fitsBelow","useEffect","update","observer","list","optionElement","listRect","optionRect","openDropdown","edge","toggleDropdown","handleKeyDown","current","step","handleOptionClick","multiple","currentValues","newValue","v","onChange","handleOptionPointerDown","handleOptionPointerUp","press","moved","handleOptionPointerCancel","handleRemoveItem","itemValue","header","selectedLabels","opt","isOverflowing","renderSelectedValue","placeholder","selectedOptions","isFixed","fixedHeight","e","selectedOption","selectClasses","className","createPortal"],"sources":["../../../src/components/Select/index.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useId, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport interface Option {\n value: string | number;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectProps {\n /** Accessible name for the combobox. */\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n /** Optional ID for the combobox; generated per instance when omitted. */\n id?: string;\n disabled?: boolean;\n options: Option[];\n value?: string | number | (string | number)[];\n onChange: (value: string | number | (string | number)[]) => void;\n placeholder?: string;\n multiple?: boolean;\n fixedHeight?: boolean;\n style?: React.CSSProperties; // Allow passing inline styles\n className?: string; // Allow passing CSS classes for the wrapper\n}\n\n// SVG component for the dropdown arrow\nconst DropdownArrow: React.FC<{ isOpen: boolean }> = ({ isOpen }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n style={{\n display: 'block',\n width: 16,\n height: 16,\n transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',\n transition: 'transform 200ms ease-in-out',\n }}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n);\n\n// SVG component for the remove button 'x'\nconst RemoveIcon: React.FC = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n);\n\n// Select Component Implementation using daisyUI/Tailwind\nconst Select: React.FC<SelectProps> = ({\n options,\n value,\n onChange,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n 'aria-describedby': ariaDescribedby,\n id,\n disabled = false,\n placeholder = 'Select...',\n multiple = false,\n fixedHeight = false,\n style,\n className // This className applies to the wrapper\n}) => {\n const generatedId = useId();\n const comboboxId = id ?? `select-${generatedId}`;\n const listboxId = `${comboboxId}-listbox`;\n const optionId = (option: Option) => `${listboxId}-${typeof option.value}-${encodeURIComponent(String(option.value))}`;\n const [open, setIsOpen] = useState(false);\n const isOpen = open && !disabled;\n if (disabled && open) setIsOpen(false);\n const [highlightedValue, setHighlightedValue] = useState<Option['value'] | null>(null);\n const [tooltipText, setTooltipText] = useState('');\n const [showArrow, setShowArrow] = useState(true);\n const [dropdownStyle, setDropdownStyle] = useState<React.CSSProperties>({});\n const wrapperRef = useRef<HTMLDivElement>(null);\n const comboboxRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null); // Ref for the header div\n const optionsListRef = useRef<HTMLUListElement>(null);\n // Tracks a touch/pen press on an option so a tap selects while a drag scrolls.\n // (pointerdown on touch must NOT preventDefault — that blocks native scrolling.)\n const touchPressRef = useRef<{ pointerId: number; x: number; y: number } | null>(null);\n const touchTapRef = useRef(false);\n\n useEffect(() => {\n if (!isOpen) return;\n const handlePointerDown = (event: MouseEvent) => {\n const target = event.target as Node;\n if (wrapperRef.current?.contains(target) || optionsListRef.current?.contains(target)) return;\n setIsOpen(false);\n };\n document.addEventListener('pointerdown', handlePointerDown);\n\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown);\n };\n }, [isOpen]);\n\n const selectedValuesArray = useMemo(() => Array.isArray(value) ? value : (value !== undefined && value !== null ? [value] : []), [value]);\n\n const enabledIndices = options.flatMap((option, index) => option.disabled ? [] : [index]);\n const selectedIndex = options.findIndex(option => !option.disabled && selectedValuesArray.includes(option.value));\n const storedIndex = options.findIndex(option => !option.disabled && option.value === highlightedValue);\n // Derive a valid active option even when options are removed, reordered or disabled.\n const highlightedIndex = storedIndex >= 0 ? storedIndex : selectedIndex >= 0 ? selectedIndex : enabledIndices[0] ?? -1;\n\n\n const handleBlur = (event: React.FocusEvent) => {\n const next = event.relatedTarget as Node | null;\n if (!next || (!wrapperRef.current?.contains(next) && !optionsListRef.current?.contains(next))) {\n setIsOpen(false);\n }\n };\n\n const updateDropdownPosition = useCallback(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return;\n const rect = wrapper.getBoundingClientRect();\n const estimatedHeight = Math.min(options.length, 8) * 36 + 8;\n const fitsBelow = rect.bottom + 4 + estimatedHeight <= window.innerHeight;\n setDropdownStyle({\n position: 'fixed',\n left: rect.left,\n top: fitsBelow ? rect.bottom + 4 : Math.max(8, rect.top - estimatedHeight - 4),\n width: rect.width,\n zIndex: 10000,\n });\n }, [options.length]);\n\n useEffect(() => {\n if (!isOpen) return;\n updateDropdownPosition();\n window.addEventListener('resize', updateDropdownPosition);\n window.addEventListener('scroll', updateDropdownPosition, true);\n return () => {\n window.removeEventListener('resize', updateDropdownPosition);\n window.removeEventListener('scroll', updateDropdownPosition, true);\n };\n }, [isOpen, updateDropdownPosition]);\n\n // Hide the decorative arrow when the control becomes too narrow to reserve\n // space for both it and a useful amount of label text.\n useEffect(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return;\n const update = () => setShowArrow(wrapper.clientWidth >= 88);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(wrapper);\n return () => observer.disconnect();\n }, []);\n\n // Scroll after React commits the new active option, not using the previous index.\n useEffect(() => {\n if (isOpen && optionsListRef.current && highlightedIndex >= 0) {\n const list = optionsListRef.current;\n const optionElement = list.children[highlightedIndex] as HTMLLIElement;\n if (optionElement) {\n const listRect = list.getBoundingClientRect();\n const optionRect = optionElement.getBoundingClientRect();\n\n if (optionRect.bottom > listRect.bottom) {\n list.scrollTop += optionRect.bottom - listRect.bottom;\n } else if (optionRect.top < listRect.top) {\n list.scrollTop -= listRect.top - optionRect.top;\n }\n }\n }\n }, [isOpen, highlightedIndex]);\n\n const openDropdown = (edge: 'first' | 'last' = 'first') => {\n if (disabled) return;\n const index = selectedIndex >= 0 ? selectedIndex : edge === 'last' ? enabledIndices.at(-1) : enabledIndices[0];\n setHighlightedValue(index !== undefined && index >= 0 ? options[index].value : null);\n setIsOpen(true);\n updateDropdownPosition();\n };\n\n const toggleDropdown = () => {\n if (disabled) return;\n comboboxRef.current?.focus({ preventScroll: true });\n if (isOpen) setIsOpen(false);\n else openDropdown();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Tab') {\n setIsOpen(false); // Preserve native Tab / Shift+Tab focus traversal, including tag buttons.\n return;\n }\n if (event.target !== comboboxRef.current || disabled || event.defaultPrevented || event.nativeEvent.isComposing || event.altKey || event.ctrlKey || event.metaKey) return;\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n if (!isOpen) openDropdown(event.key === 'ArrowUp' ? 'last' : 'first');\n else if (enabledIndices.length) {\n const current = enabledIndices.indexOf(highlightedIndex);\n const step = event.key === 'ArrowDown' ? 1 : -1;\n const next = enabledIndices[(current + step + enabledIndices.length) % enabledIndices.length];\n setHighlightedValue(options[next].value);\n }\n break;\n }\n case 'Home':\n case 'End': {\n if (!isOpen) openDropdown();\n const next = event.key === 'Home' ? enabledIndices[0] : enabledIndices.at(-1);\n setHighlightedValue(next === undefined ? null : options[next].value);\n break;\n }\n case 'Enter':\n case ' ':\n if (!isOpen) openDropdown();\n else if (highlightedIndex >= 0) handleOptionClick(options[highlightedIndex]);\n break;\n case 'Escape':\n if (!isOpen) return;\n setIsOpen(false);\n break;\n default:\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n };\n\n const handleOptionClick = (option: Option) => {\n if (disabled || option.disabled) return;\n setHighlightedValue(option.value);\n comboboxRef.current?.focus({ preventScroll: true });\n if (multiple) {\n const currentValues = Array.isArray(value) ? value : [];\n let newValue;\n if (currentValues.includes(option.value)) {\n newValue = currentValues.filter(v => v !== option.value);\n } else {\n newValue = [...currentValues, option.value];\n }\n onChange(newValue);\n } else {\n onChange(option.value);\n setIsOpen(false); // Close dropdown on single select\n }\n };\n\n // Mouse: select immediately on press (existing desktop behavior).\n // Touch/pen: confirm a tap on pointerup, then select on click. Unmounting the\n // option on pointerup would send compatibility mouse events to the page behind\n // the portal, stealing focus. preventDefault() on a\n // touch pointerdown suppresses the browser's native pan gesture, which made\n // long dropdowns impossible to scroll on mobile (and every scroll attempt\n // selected an option instead).\n const handleOptionPointerDown = (event: React.PointerEvent<HTMLLIElement>, option: Option) => {\n touchTapRef.current = false;\n if (event.pointerType === 'mouse') {\n event.preventDefault();\n event.stopPropagation();\n handleOptionClick(option);\n return;\n }\n event.stopPropagation();\n touchPressRef.current = { pointerId: event.pointerId, x: event.clientX, y: event.clientY };\n };\n\n const handleOptionPointerUp = (event: React.PointerEvent<HTMLLIElement>) => {\n const press = touchPressRef.current;\n touchPressRef.current = null;\n if (!press || event.pointerId !== press.pointerId) return;\n // Select only if the finger did not move much — otherwise it was a scroll.\n const moved = Math.hypot(event.clientX - press.x, event.clientY - press.y);\n touchTapRef.current = moved < 10;\n event.stopPropagation();\n };\n\n const handleOptionPointerCancel = () => {\n touchPressRef.current = null;\n touchTapRef.current = false;\n };\n\n const handleRemoveItem = (e: React.MouseEvent, itemValue: string | number) => {\n e.stopPropagation(); // Prevent dropdown from opening/closing\n if (disabled || options.find(option => option.value === itemValue)?.disabled) return;\n comboboxRef.current?.focus({ preventScroll: true });\n const currentValues = Array.isArray(value) ? value : [];\n onChange(currentValues.filter(v => v !== itemValue));\n };\n\n // Update tooltip text and check for overflow\n useEffect(() => {\n if (multiple && headerRef.current) {\n const header = headerRef.current;\n const selectedLabels = options\n .filter(opt => selectedValuesArray.includes(opt.value))\n .map(opt => opt.label)\n .join(', ');\n\n // Check if the content (scrollWidth) exceeds the visible area (clientWidth)\n const isOverflowing = header.scrollWidth > header.clientWidth;\n setTooltipText(isOverflowing ? selectedLabels : ''); // Only set text if overflowing\n } else {\n setTooltipText(''); // Clear tooltip for single select or empty multi-select\n }\n }, [multiple, options, selectedValuesArray]);\n\n\n const renderSelectedValue = () => {\n if (selectedValuesArray.length === 0) {\n return <span className=\"text-base-content/60 italic\">{placeholder}</span>;\n }\n\n const selectedOptions = options.filter(opt => selectedValuesArray.includes(opt.value));\n\n if (multiple) {\n const isFixed = fixedHeight;\n // Apply overflow-x-auto for horizontal scrolling in fixedHeight mode\n const containerClasses = `\n flex gap-1 \n ${isFixed ? 'flex-nowrap overflow-x-auto overflow-y-hidden' : 'flex-wrap overflow-hidden'} // Enable horizontal scroll, hide vertical scrollbar if any\n ${tooltipText ? 'tooltip tooltip-bottom' : ''} // Keep tooltip for overflow\n `;\n // Removed showEllipsisPrefix\n\n return (\n <div\n ref={headerRef}\n className={containerClasses}\n data-tip={tooltipText ? tooltipText : undefined} // Keep tooltip logic\n // Add scrollbar styling if desired (e.g., using ::-webkit-scrollbar pseudo-element via CSS or a utility)\n style={{\n scrollbarWidth: 'thin',\n // 为固定高度模式添加右侧内边距,避免与下拉图标重叠\n ...(isFixed ? { paddingRight: '1.75rem' } : {})\n }}\n >\n {/* Removed wrapper for ellipsis and its popup */}\n\n {/* Render the badges */}\n {selectedOptions.map(option => (\n <span key={optionId(option)} className=\"badge badge-ghost gap-1 text-xs items-center whitespace-nowrap flex-shrink-0\">\n {option.label}\n <button\n type=\"button\"\n disabled={disabled || option.disabled}\n onClick={(e) => handleRemoveItem(e, option.value)}\n className=\"btn btn-xs btn-ghost btn-circle p-0 m-0 hover:bg-error hover:text-error-content\"\n aria-label={`Remove ${option.label}`}\n >\n <RemoveIcon />\n </button>\n </span>\n ))}\n </div>\n );\n } else {\n const selectedOption = options.find(opt => opt.value === selectedValuesArray[0]);\n return selectedOption ? <span className=\"truncate\">{selectedOption.label}</span> : <span className=\"text-base-content/60 italic\">{placeholder}</span>;\n }\n };\n\n // Match the default control height to a normal line of form text. Multi-select\n // may still grow when wrapping tags unless fixedHeight is requested.\n const selectClasses = `\n relative border border-base-300 rounded-lg bg-base-100 w-full\n flex justify-between items-center cursor-pointer px-3 text-sm\n focus:outline-none focus:ring-2 focus:ring-primary focus:ring-opacity-50\n hover:border-base-content/30\n ${multiple\n ? (fixedHeight ? 'h-8' : 'min-h-8 h-auto py-1')\n : 'h-8'}\n `;\n\n return (\n <div\n ref={wrapperRef}\n style={style}\n className={`relative w-full font-sans select-none ${className || ''}`}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n >\n {/* Header */}\n <div\n ref={comboboxRef}\n id={comboboxId}\n tabIndex={disabled ? -1 : 0}\n className={`${selectClasses} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`}\n onClick={toggleDropdown}\n\n role=\"combobox\"\n aria-label={ariaLabel ?? (ariaLabelledby ? undefined : placeholder)}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n aria-disabled={disabled || undefined}\n aria-controls={isOpen ? listboxId : undefined}\n aria-activedescendant={isOpen && highlightedIndex >= 0 ? optionId(options[highlightedIndex]) : undefined}\n >\n <div\n className=\"flex-1 min-w-0 overflow-hidden\"\n style={{ paddingRight: showArrow ? 28 : 0 }}\n >\n {renderSelectedValue()}\n </div>\n {/* Inline positioning avoids utility CSS/theme overrides moving the icon. */}\n {showArrow && (\n <div\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n right: 10,\n top: '50%',\n transform: 'translateY(-50%)',\n pointerEvents: 'none',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 16,\n height: 16,\n }}\n >\n <DropdownArrow isOpen={isOpen} />\n </div>\n )}\n </div>\n\n {/* Dropdown Options */}\n {isOpen && typeof document !== 'undefined' && createPortal(\n <ul\n ref={optionsListRef}\n id={listboxId}\n className=\"bg-base-100 border border-base-300 rounded-md shadow-lg list-none p-0 m-0 max-h-60 overflow-y-auto focus:outline-none\"\n style={{ ...dropdownStyle, touchAction: 'pan-y' }}\n onPointerDown={(event) => event.stopPropagation()}\n role=\"listbox\"\n aria-labelledby={ariaLabelledby ?? comboboxId}\n aria-multiselectable={multiple || undefined}\n // Keep DOM focus on the combobox even when touch focuses the portal.\n onFocus={() => comboboxRef.current?.focus({ preventScroll: true })}\n tabIndex={-1}\n >\n {options.length > 0 ? (\n options.map((option, index) => (\n <li\n key={optionId(option)}\n id={optionId(option)}\n className={`p-2 ${option.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:bg-base-200'} whitespace-nowrap overflow-hidden text-ellipsis ${index === highlightedIndex ? 'bg-base-300' : '' // Highlight style\n } ${selectedValuesArray.includes(option.value) && !multiple ? 'font-semibold bg-base-200' : '' // Style for selected single item\n } ${selectedValuesArray.includes(option.value) && multiple ? 'font-semibold' : '' // Style for selected multi items (less prominent background)\n }`}\n onPointerDown={(event) => handleOptionPointerDown(event, option)}\n onPointerUp={handleOptionPointerUp}\n onPointerCancel={handleOptionPointerCancel}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (touchTapRef.current || event.detail === 0) handleOptionClick(option);\n touchTapRef.current = false;\n }}\n onPointerMove={event => {\n // Scrolling under a stationary pointer must not undo keyboard navigation.\n if (event.pointerType === 'mouse' && (event.movementX || event.movementY) && !option.disabled) {\n setHighlightedValue(option.value);\n }\n }}\n role=\"option\"\n aria-disabled={option.disabled || undefined}\n aria-selected={selectedValuesArray.includes(option.value)}\n >\n {/* Optional: Add a checkmark or similar for selected items, especially in multi-select */}\n {option.label}\n </li>\n ))\n ) : (\n <li className=\"p-2 text-base-content/60 italic\">\n No options available\n </li>\n )}\n </ul>,\n document.body,\n )}\n </div>\n );\n};\n\nexport default Select; "],"mappings":";;;;AA4BA,IAAMA,KAAgD,EAAE,gBACtD,kBAAC,OAAD;CACE,OAAM;CACN,MAAK;CACL,SAAQ;CACR,QAAO;CACP,aAAa;CACb,OAAO;EACL,SAAS;EACT,OAAO;EACP,QAAQ;EACR,WAAWC,IAAS,mBAAmB;EACvC,YAAY;CACd;CAEA,UAAA,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,GAAE;CAAkB,CAAA;AACpE,CAAA,GAIDC,UACJ,kBAAC,OAAD;CAAK,OAAM;CAA6B,WAAU;CAAU,MAAK;CAAO,SAAQ;CAAY,QAAO;CAAe,aAAa;CAC7H,UAAA,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,GAAE;CAAwB,CAAA;AAC1E,CAAA,GAIDC,KAAiC,EACrC,YACA,UACA,aACA,cAAcC,GACd,mBAAmBC,GACnB,oBAAoBC,GACpB,OACA,cAAW,IACX,iBAAc,aACd,cAAW,IACX,iBAAc,IACd,UACA,mBACI;CACJ,IAAMC,IAAcC,EAAM,GACpBC,IAAaC,KAAM,UAAUH,KAC7BI,IAAY,GAAGF,EAAW,WAC1BG,KAAY,MAAmB,GAAGD,EAAU,GAAG,OAAOE,EAAO,MAAM,GAAG,mBAAmB,OAAOA,EAAO,KAAK,CAAC,KAC7G,CAACC,GAAMC,KAAaC,EAAS,EAAK,GAClCf,IAASa,KAAQ,CAACG;CACxB,AAAIA,KAAYH,KAAMC,EAAU,EAAK;CACrC,IAAM,CAACG,GAAkBC,KAAuBH,EAAiC,IAAI,GAC/E,CAACI,GAAaC,KAAkBL,EAAS,EAAE,GAC3C,CAACM,GAAWC,KAAgBP,EAAS,EAAI,GACzC,CAACQ,GAAeC,KAAoBT,EAA8B,CAAC,CAAC,GACpEU,IAAaC,EAAuB,IAAI,GACxCC,IAAcD,EAAuB,IAAI,GACzCE,IAAYF,EAAuB,IAAI,GACvCG,IAAiBH,EAAyB,IAAI,GAG9CI,IAAgBJ,EAA2D,IAAI,GAC/EK,IAAcL,EAAO,EAAK;CAEhC,QAAgB;EACd,IAAI,CAAC1B,GAAQ;EACb,IAAMgC,KAAqB,MAAsB;GAC/C,IAAMC,IAASC,EAAM;GACrB,AAAIT,EAAW,SAAS,SAASQ,CAAM,KAAKJ,EAAe,SAAS,SAASI,CAAM,KACnFnB,EAAU,EAAK;EACjB;EAGA,OAFA,SAAS,iBAAiB,eAAekB,CAAiB,SAE7C;GACX,SAAS,oBAAoB,eAAeA,CAAiB;EAC/D;CACF,GAAG,CAAChC,CAAM,CAAC;CAEX,IAAMmC,IAAsBC,QAAc,MAAM,QAAQC,CAAK,IAAIA,IAASA,KAAiC,OAAiB,CAAC,IAAX,CAACA,CAAK,GAAS,CAACA,CAAK,CAAC,GAElIC,IAAiBC,EAAQ,SAAS,GAAQ,MAAU3B,EAAO,WAAW,CAAC,IAAI,CAAC4B,CAAK,CAAC,GAClFC,IAAgBF,EAAQ,WAAU,MAAU,CAAC3B,EAAO,YAAYuB,EAAoB,SAASvB,EAAO,KAAK,CAAC,GAC1G8B,IAAcH,EAAQ,WAAU,MAAU,CAAC3B,EAAO,YAAYA,EAAO,UAAUK,CAAgB,GAE/F0B,IAAmBD,KAAe,IAAIA,IAAcD,KAAiB,IAAIA,IAAgBH,EAAe,MAAM,IAG9GM,KAAc,MAA4B;EAC9C,IAAMC,IAAOX,EAAM;EACnB,CAAI,CAACW,KAAS,CAACpB,EAAW,SAAS,SAASoB,CAAI,KAAK,CAAChB,EAAe,SAAS,SAASgB,CAAI,MACzF/B,EAAU,EAAK;CAEnB,GAEMgC,IAAyBC,QAAkB;EAC/C,IAAMC,IAAUvB,EAAW;EAC3B,IAAI,CAACuB,GAAS;EACd,IAAMC,IAAOD,EAAQ,sBAAsB,GACrCE,IAAkB,KAAK,IAAIX,EAAQ,QAAQ,CAAC,IAAI,KAAK,GACrDY,IAAYF,EAAK,SAAS,IAAIC,KAAmB,OAAO;EAC9D,EAAiB;GACf,UAAU;GACV,MAAMD,EAAK;GACX,KAAKE,IAAYF,EAAK,SAAS,IAAI,KAAK,IAAI,GAAGA,EAAK,MAAMC,IAAkB,CAAC;GAC7E,OAAOD,EAAK;GACZ,QAAQ;EACV,CAAC;CACH,GAAG,CAACV,EAAQ,MAAM,CAAC;CA0BnB,AAxBAa,QAAgB;EACd,IAAKpD,GAIL,OAHA8C,EAAuB,GACvB,OAAO,iBAAiB,UAAUA,CAAsB,GACxD,OAAO,iBAAiB,UAAUA,GAAwB,EAAI,SACjD;GAEX,AADA,OAAO,oBAAoB,UAAUA,CAAsB,GAC3D,OAAO,oBAAoB,UAAUA,GAAwB,EAAI;EACnE;CACF,GAAG,CAAC9C,GAAQ8C,CAAsB,CAAC,GAInCM,QAAgB;EACd,IAAMJ,IAAUvB,EAAW;EAC3B,IAAI,CAACuB,GAAS;EACd,IAAMK,UAAe/B,EAAa0B,EAAQ,eAAe,EAAE;EAC3D,EAAO;EACP,IAAMM,IAAW,IAAI,eAAeD,CAAM;EAE1C,OADAC,EAAS,QAAQN,CAAO,SACXM,EAAS,WAAW;CACnC,GAAG,CAAC,CAAC,GAGLF,QAAgB;EACd,IAAIpD,KAAU6B,EAAe,WAAWc,KAAoB,GAAG;GAC7D,IAAMY,IAAO1B,EAAe,SACtB2B,IAAgBD,EAAK,SAASZ;GACpC,IAAIa,GAAe;IACjB,IAAMC,IAAWF,EAAK,sBAAsB,GACtCG,IAAaF,EAAc,sBAAsB;IAEvD,AAAIE,EAAW,SAASD,EAAS,SAC/B,EAAK,aAAaC,EAAW,SAASD,EAAS,SACtCC,EAAW,MAAMD,EAAS,QACnC,EAAK,aAAaA,EAAS,MAAMC,EAAW;GAEhD;EACF;CACF,GAAG,CAAC1D,GAAQ2C,CAAgB,CAAC;CAE7B,IAAMgB,KAAgB,IAAyB,YAAY;EACzD,IAAI3C,GAAU;EACd,IAAMwB,IAAQC,KAAiB,IAAIA,IAAgBmB,MAAS,SAAStB,EAAe,GAAG,EAAE,IAAIA,EAAe;EAG5G,AAFApB,EAAoBsB,MAAU,KAAA,KAAaA,KAAS,IAAID,EAAQC,EAAM,CAAC,QAAQ,IAAI,GACnF1B,EAAU,EAAI,GACdgC,EAAuB;CACzB,GAEMe,WAAuB;EAC3B,AAAI7C,MACJW,EAAY,SAAS,MAAM,EAAE,eAAe,GAAK,CAAC,GAC9C3B,IAAQc,EAAU,EAAK,IACtB6C,EAAa;CACpB,GAEMG,MAAiB,MAA+C;EACpE,IAAI5B,EAAM,QAAQ,OAAO;GACvB,EAAU,EAAK;GACf;EACF;EACA,IAAI,IAAM,WAAWP,EAAY,WAAWX,KAAYkB,EAAM,oBAAoBA,EAAM,YAAY,eAAeA,EAAM,UAAUA,EAAM,WAAWA,EAAM,UAC1J;WAAQA,EAAM,KAAd;IACE,KAAK;IACL,KAAK;KACH,IAAI,CAAClC,GAAQ,EAAakC,EAAM,QAAQ,YAAY,SAAS,OAAO;UAC/D,IAAII,EAAe,QAAQ;MAC9B,IAAMyB,IAAUzB,EAAe,QAAQK,CAAgB,GACjDqB,IAAO9B,EAAM,QAAQ,cAAc,IAAI,IACvCW,IAAOP,GAAgByB,IAAUC,IAAO1B,EAAe,UAAUA,EAAe;MACtF,EAAoBC,EAAQM,EAAK,CAAC,KAAK;KACzC;KACA;IAEF,KAAK;IACL,KAAK,OAAO;KACV,AAAK7C,KAAQ2D,EAAa;KAC1B,IAAMd,IAAOX,EAAM,QAAQ,SAASI,EAAe,KAAKA,EAAe,GAAG,EAAE;KAC5E,EAAoBO,MAAS,KAAA,IAAY,OAAON,EAAQM,EAAK,CAAC,KAAK;KACnE;IACF;IACA,KAAK;IACL,KAAK;KACH,AAAK7C,IACI2C,KAAoB,KAAGsB,EAAkB1B,EAAQI,EAAiB,IAD9DgB,EAAa;KAE1B;IACF,KAAK;KACH,IAAI,CAAC3D,GAAQ;KACb,EAAU,EAAK;KACf;IACF,SACE;GACJ;GAEA,AADAkC,EAAM,eAAe,GACrBA,EAAM,gBAAgB;EAFtB;CAGF,GAEM+B,KAAqB,MAAmB;EAC5C,IAAI,OAAYrD,EAAO,WAGvB;OAFAM,EAAoBN,EAAO,KAAK,GAChCe,EAAY,SAAS,MAAM,EAAE,eAAe,GAAK,CAAC,GAC9CuC,GAAU;IACZ,IAAMC,IAAgB,MAAM,QAAQ9B,CAAK,IAAIA,IAAQ,CAAC,GAClD+B;IAMJ,AALA,AAGEA,IAHED,EAAc,SAASvD,EAAO,KAAK,IAC1BuD,EAAc,QAAO,MAAKE,MAAMzD,EAAO,KAAK,IAE5C,CAAC,GAAGuD,GAAevD,EAAO,KAAK,GAE5C0D,EAASF,CAAQ;GACnB,OAEE,AADAE,EAAS1D,EAAO,KAAK,GACrBE,EAAU,EAAK;EACjB;CACF,GASMyD,MAA2B,GAA0C,MAAmB;EAE5F,IADA,EAAY,UAAU,IAClBrC,EAAM,gBAAgB,SAAS;GAGjC,AAFAA,EAAM,eAAe,GACrBA,EAAM,gBAAgB,GACtB+B,EAAkBrD,CAAM;GACxB;EACF;EAEA,AADAsB,EAAM,gBAAgB,GACtB,EAAc,UAAU;GAAE,WAAWA,EAAM;GAAW,GAAGA,EAAM;GAAS,GAAGA,EAAM;EAAQ;CAC3F,GAEMsC,MAAyB,MAA6C;EAC1E,IAAMC,IAAQ3C,EAAc;EAE5B,IADA,EAAc,UAAU,MACpB,CAAC2C,KAASvC,EAAM,cAAcuC,EAAM,WAAW;EAEnD,IAAMC,IAAQ,KAAK,MAAMxC,EAAM,UAAUuC,EAAM,GAAGvC,EAAM,UAAUuC,EAAM,CAAC;EAEzE,AADA,EAAY,UAAUC,IAAQ,IAC9BxC,EAAM,gBAAgB;CACxB,GAEMyC,WAAkC;EAEtC,AADA,EAAc,UAAU,MACxB,EAAY,UAAU;CACxB,GAEMC,MAAoB,GAAqB,MAA+B;EAE5E,AADA,EAAE,gBAAgB,GACd,OAAYrC,EAAQ,MAAK,MAAU3B,EAAO,UAAUiE,CAAS,CAAC,EAAE,cACpElD,EAAY,SAAS,MAAM,EAAE,eAAe,GAAK,CAAC,GAElD2C,GADsB,MAAM,QAAQjC,CAAK,IAAIA,IAAQ,CAAC,EAAA,CAC/B,QAAO,MAAKgC,MAAMQ,CAAS,CAAC;CACrD;CAGA,QAAgB;EACd,IAAIX,KAAYtC,EAAU,SAAS;GACjC,IAAMkD,IAASlD,EAAU,SACnBmD,IAAiBxC,EACpB,QAAO,MAAOJ,EAAoB,SAAS6C,EAAI,KAAK,CAAC,CAAC,CACtD,KAAI,MAAOA,EAAI,KAAK,CAAC,CACrB,KAAK,IAAI,GAGNC,IAAgBH,EAAO,cAAcA,EAAO;GAClD,EAAeG,IAAgBF,IAAiB,EAAE;EACpD,OACE,EAAe,EAAE;CAErB,GAAG;EAACb;EAAU3B;EAASJ;CAAmB,CAAC;CAG3C,IAAM+C,WAA4B;EAChC,IAAI/C,EAAoB,WAAW,GACjC,OAAO,kBAAC,QAAD;GAAM,WAAU;GAA+B,UAAAgD;EAAkB,CAAA;EAG1E,IAAMC,IAAkB7C,EAAQ,QAAO,MAAOJ,EAAoB,SAAS6C,EAAI,KAAK,CAAC;EAErF,IAAId,GAAU;GACZ,IAAMmB,IAAUC;GAShB,OACE,kBAAC,OAAD;IACE,KAAK1D;IACL,WAAW;;UARXyD,IAAU,kDAAkD,4BAA4B;UACxFlE,IAAc,2BAA2B,GAAG;;IAQ5C,YAAUA,KAA4B,KAAA;IAEtC,OAAO;KACL,gBAAgB;KAEhB,GAAIkE,IAAU,EAAE,cAAc,UAAU,IAAI,CAAC;IAC/C;IAKC,UAAAD,EAAgB,KAAI,MACnB,kBAAC,QAAD;KAA6B,WAAU;KAAvC,UAAA,CACGxE,EAAO,OACR,kBAAC,UAAD;MACE,MAAK;MACL,UAAUI,KAAYJ,EAAO;MAC7B,UAAU,MAAMgE,GAAiBW,GAAG3E,EAAO,KAAK;MAChD,WAAU;MACV,cAAY,UAAUA,EAAO;MAE7B,UAAA,kBAACX,GAAD,CAAa,CAAA;KACP,CAAA,CACJ;IAXK,GAAAU,EAASC,CAAM,CAWpB,CACP;GACE,CAAA;EAET;EAAO;GACL,IAAM4E,IAAiBjD,EAAQ,MAAK,MAAOyC,EAAI,UAAU7C,EAAoB,EAAE;GAC/E,OAAOqD,IAAiB,kBAAC,QAAD;IAAM,WAAU;IAAY,UAAAA,EAAe;GAAY,CAAA,IAAI,kBAAC,QAAD;IAAM,WAAU;IAA+B,UAAAL;GAAkB,CAAA;EACtJ;CACF,GAIMM,KAAgB;;;;;MAKlBvB,IACGoB,IAAc,QAAQ,wBACvB,MAAM;;CAGZ,OACE,kBAAC,OAAD;EACE,KAAK7D;EACE;EACP,WAAW,yCAAyCiE,KAAa;EACjE,QAAQ9C;EACR,WAAWkB;EALb,UAAA,CAQE,kBAAC,OAAD;GACE,KAAKnC;GACL,IAAInB;GACJ,UAAUQ,IAAW,KAAK;GAC1B,WAAW,GAAGyE,GAAc,GAAGzE,IAAW,kCAAkC;GAC5E,SAAS6C;GAET,MAAK;GACL,cAAY1D,MAAcC,IAAiB,KAAA,IAAY+E;GACvD,mBAAiB/E;GACjB,oBAAkBC;GAClB,iBAAc;GACd,iBAAeL;GACf,iBAAegB,KAAY,KAAA;GAC3B,iBAAehB,IAASU,IAAY,KAAA;GACpC,yBAAuBV,KAAU2C,KAAoB,IAAIhC,EAAS4B,EAAQI,EAAiB,IAAI,KAAA;GAfjG,UAAA,CAiBE,kBAAC,OAAD;IACE,WAAU;IACV,OAAO,EAAE,cAActB,IAAY,KAAK,EAAE;IAEzC,UAAA6D,GAAoB;GAClB,CAAA,GAEJ7D,KACC,kBAAC,OAAD;IACE,eAAY;IACZ,OAAO;KACL,UAAU;KACV,OAAO;KACP,KAAK;KACL,WAAW;KACX,eAAe;KACf,SAAS;KACT,YAAY;KACZ,gBAAgB;KAChB,OAAO;KACP,QAAQ;IACV;IAEA,UAAA,kBAACtB,GAAD,EAAuB,UAAS,CAAA;GAC7B,CAAA,CAEJ;EAGJ,CAAA,GAAAC,KAAU,OAAO,WAAa,OAAe2F,EAC5C,kBAAC,MAAD;GACE,KAAK9D;GACL,IAAInB;GACJ,WAAU;GACV,OAAO;IAAE,GAAGa;IAAe,aAAa;GAAQ;GAChD,gBAAgB,MAAUW,EAAM,gBAAgB;GAChD,MAAK;GACL,mBAAiB9B,KAAkBI;GACnC,wBAAsB0D,KAAY,KAAA;GAElC,eAAevC,EAAY,SAAS,MAAM,EAAE,eAAe,GAAK,CAAC;GACjE,UAAU;GAET,UAAAY,EAAQ,SAAS,IAChBA,EAAQ,KAAK,GAAQ,MACnB,kBAAC,MAAD;IAEE,IAAI5B,EAASC,CAAM;IACnB,WAAW,OAAOA,EAAO,WAAW,kCAAkC,mCAAmC,mDAAmD4B,MAAUG,IAAmB,gBAAgB,GACtM,GAAGR,EAAoB,SAASvB,EAAO,KAAK,KAAK,CAACsD,IAAW,8BAA8B,GAC3F,GAAG/B,EAAoB,SAASvB,EAAO,KAAK,KAAKsD,IAAW,kBAAkB;IAEjF,gBAAgB,MAAUK,GAAwBrC,GAAOtB,CAAM;IAC/D,aAAa4D;IACb,iBAAiBG;IACjB,UAAU,MAAU;KAIlB,AAHAzC,EAAM,eAAe,GACrBA,EAAM,gBAAgB,IAClBH,EAAY,WAAWG,EAAM,WAAW,MAAG+B,EAAkBrD,CAAM,GACvE,EAAY,UAAU;IACxB;IACA,gBAAe,MAAS;KAEtB,AAAIsB,EAAM,gBAAgB,YAAYA,EAAM,aAAaA,EAAM,cAAc,CAACtB,EAAO,YACnFM,EAAoBN,EAAO,KAAK;IAEpC;IACA,MAAK;IACL,iBAAeA,EAAO,YAAY,KAAA;IAClC,iBAAeuB,EAAoB,SAASvB,EAAO,KAAK;IAGvD,UAAAA,EAAO;GACN,GA3BGD,EAASC,CAAM,CA2BlB,CACL,IAED,kBAAC,MAAD;IAAI,WAAU;IAAkC,UAAA;GAE5C,CAAA;EAEJ,CAAA,GACJ,SAAS,IACX,CACG;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/SidebarToggleButton/index.tsx"],"sourcesContent":["import React from 'react';\nimport { useResize } from '../Resizable/useResize';\nimport '../Resizable/Resizable.css';\n\ninterface SidebarToggleButtonProps {\n /** 侧边栏是否折叠 */\n isCollapsed: boolean;\n /** 侧栏位置;手柄始终放在靠近主内容的内侧边缘。 */\n side?: 'left' | 'right';\n /** 切换侧边栏的回调 */\n onToggle: () => void;\n /** 当前侧边栏宽度 */\n sidebarWidth: number;\n /** 折叠时的宽度 */\n collapsedWidth?: number;\n /** 拖拽调节宽度的回调(传入时支持拖拽缩放) */\n onWidthChange?: (width: number) => void;\n /** 拖拽时的最小宽度(px) */\n minWidth?: number;\n /** 拖拽时的最大宽度(px) */\n maxWidth?: number;\n /**\n * 侧边栏容器引用,用实际渲染宽度作为调宽起点(包括 rem / 百分比宽度)。\n */\n anchorRef?: React.RefObject<HTMLElement | null>;\n}\n\n\n\n/**\n * 桌面端侧边栏切换控件(与靠近主内容的纵向边界线一体)\n * - 点击:折叠 / 展开侧边栏\n * - 拖拽:任意调节侧边栏宽度(需传入 onWidthChange)\n *\n * 采用 `absolute` 定位内嵌在侧边栏(relative 容器)内侧边缘,随侧边栏布局自然移动——\n * 无需测量/追赶,无延迟,也不受其它可变宽度组件影响。\n */\nexport const DesktopSidebarToggleButton: React.FC<SidebarToggleButtonProps> = ({\n isCollapsed,\n side = 'left',\n onToggle,\n sidebarWidth,\n onWidthChange,\n minWidth = 160,\n maxWidth = 400,\n anchorRef,\n}) => {\n const draggable = typeof onWidthChange === 'function';\n\n const resize = useResize({\n value: sidebarWidth, min: minWidth, max: maxWidth, step: 10,\n disabled: !draggable || isCollapsed, threshold: 4,\n getValue: () => anchorRef?.current?.getBoundingClientRect().width ?? sidebarWidth,\n getScale: () => side === 'right' ? -1 : 1,\n keyboardDirection: side === 'right' ? -1 : 1,\n onChange: width => onWidthChange?.(width),\n });\n\n return (\n // 热区透明覆盖相邻区域;只有分隔线和 pill 绘制背景,不占据布局宽度。\n <div\n className={`dishui-sidebar-resize absolute inset-y-0 z-40 hidden w-3 md:block ${side === 'right' ? 'left-0 -translate-x-1/2' : 'right-0 translate-x-1/2'}`}\n style={{ cursor: draggable && !isCollapsed ? 'ew-resize' : 'pointer', touchAction: 'none', userSelect: 'none' }}\n onPointerDown={event => { if (event.target === event.currentTarget || !(event.target as HTMLElement).closest('button')) resize.onPointerDown(event); }}\n onClickCapture={resize.onClickCapture}\n onClick={onToggle}\n >\n {/* 纵向边界线与 pill 共用区域交界处的中心轴。 */}\n <div className=\"pointer-events-none absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-hairline\" aria-hidden=\"true\" />\n {/* pill 手柄(坐落在线上,与之一体) */}\n <button\n type=\"button\"\n tabIndex={0}\n onPointerDown={resize.onPointerDown}\n onKeyDown={resize.onKeyDown}\n className=\"group absolute top-1/2 left-1/2 flex h-10 w-4 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-hairline bg-page text-tertiary shadow-none transition-[width,color] duration-200 ease-in-out hover:w-5 hover:text-primary focus-visible:outline-2 focus-visible:outline-ring\"\n style={{ cursor: draggable && !isCollapsed ? 'ew-resize' : 'pointer' }}\n aria-label={isCollapsed ? '展开侧边栏' : (draggable ? '拖拽调整侧边栏宽度,点击收起' : '收起侧边栏')}\n aria-expanded={!isCollapsed}\n aria-description={draggable && !isCollapsed ? `宽度 ${Math.round(sidebarWidth)}px;左右方向键调整,Home/End 到达最小/最大宽度,Enter/空格折叠` : undefined}\n title={draggable && !isCollapsed ? '拖拽调节宽度 · 点击折叠' : undefined}\n >\n {isCollapsed ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" className=\"pointer-events-none\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2.5\" d={side === 'right' ? 'M15 5l-7 7 7 7' : 'M9 5l7 7-7 7'} />\n </svg>\n ) : (\n <svg width=\"6\" height=\"18\" viewBox=\"0 0 6 18\" fill=\"currentColor\" aria-hidden=\"true\" className=\"pointer-events-none\">\n <circle cx=\"1.5\" cy=\"3\" r=\"1\" /><circle cx=\"4.5\" cy=\"3\" r=\"1\" />\n <circle cx=\"1.5\" cy=\"9\" r=\"1\" /><circle cx=\"4.5\" cy=\"9\" r=\"1\" />\n <circle cx=\"1.5\" cy=\"15\" r=\"1\" /><circle cx=\"4.5\" cy=\"15\" r=\"1\" />\n </svg>\n )}\n </button>\n </div>\n );\n};\n\n/**\n * 移动端悬浮侧边栏切换按钮\n */\nexport const MobileSidebarToggleButton: React.FC<Pick<SidebarToggleButtonProps, 'isCollapsed' | 'onToggle'>> = ({\n isCollapsed,\n onToggle,\n}) => {\n return (\n <button\n onClick={onToggle}\n className=\"fixed bottom-6 right-6 z-50 bg-primary bg-opacity-30 hover:bg-opacity-50 text-primary-content rounded-full p-3 shadow-lg transition-all duration-300 ease-in-out backdrop-blur-sm hover:scale-105 md:hidden\"\n style={{\n boxShadow: '0 4px 20px rgba(0, 0, 0, 0.15)',\n }}\n aria-label={isCollapsed ? '展开侧边栏' : '收起侧边栏'}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n className=\"w-5 h-5\"\n >\n {isCollapsed ? (\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\n ) : (\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n )}\n </svg>\n </button>\n );\n};\n\n/**\n * 组合的侧边栏切换按钮(包含桌面端和移动端)\n */\nexport const SidebarToggleButtons: React.FC<SidebarToggleButtonProps> = (props) => {\n return (\n <>\n <DesktopSidebarToggleButton {...props} />\n <MobileSidebarToggleButton isCollapsed={props.isCollapsed} onToggle={props.onToggle} />\n </>\n );\n};\n\nexport default SidebarToggleButtons;\n"],"mappings":";;;;;AAqCA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["_Fragment","DesktopSidebarToggleButton","draggable","onWidthChange","resize","useResize","sidebarWidth","minWidth","maxWidth","isCollapsed","anchorRef","side","width","event","onToggle","MobileSidebarToggleButton","SidebarToggleButtons","Fragment","props"],"sources":["../../../src/components/SidebarToggleButton/index.tsx"],"sourcesContent":["import React from 'react';\nimport { useResize } from '../Resizable/useResize';\nimport '../Resizable/Resizable.css';\n\ninterface SidebarToggleButtonProps {\n /** 侧边栏是否折叠 */\n isCollapsed: boolean;\n /** 侧栏位置;手柄始终放在靠近主内容的内侧边缘。 */\n side?: 'left' | 'right';\n /** 切换侧边栏的回调 */\n onToggle: () => void;\n /** 当前侧边栏宽度 */\n sidebarWidth: number;\n /** 折叠时的宽度 */\n collapsedWidth?: number;\n /** 拖拽调节宽度的回调(传入时支持拖拽缩放) */\n onWidthChange?: (width: number) => void;\n /** 拖拽时的最小宽度(px) */\n minWidth?: number;\n /** 拖拽时的最大宽度(px) */\n maxWidth?: number;\n /**\n * 侧边栏容器引用,用实际渲染宽度作为调宽起点(包括 rem / 百分比宽度)。\n */\n anchorRef?: React.RefObject<HTMLElement | null>;\n}\n\n\n\n/**\n * 桌面端侧边栏切换控件(与靠近主内容的纵向边界线一体)\n * - 点击:折叠 / 展开侧边栏\n * - 拖拽:任意调节侧边栏宽度(需传入 onWidthChange)\n *\n * 采用 `absolute` 定位内嵌在侧边栏(relative 容器)内侧边缘,随侧边栏布局自然移动——\n * 无需测量/追赶,无延迟,也不受其它可变宽度组件影响。\n */\nexport const DesktopSidebarToggleButton: React.FC<SidebarToggleButtonProps> = ({\n isCollapsed,\n side = 'left',\n onToggle,\n sidebarWidth,\n onWidthChange,\n minWidth = 160,\n maxWidth = 400,\n anchorRef,\n}) => {\n const draggable = typeof onWidthChange === 'function';\n\n const resize = useResize({\n value: sidebarWidth, min: minWidth, max: maxWidth, step: 10,\n disabled: !draggable || isCollapsed, threshold: 4,\n getValue: () => anchorRef?.current?.getBoundingClientRect().width ?? sidebarWidth,\n getScale: () => side === 'right' ? -1 : 1,\n keyboardDirection: side === 'right' ? -1 : 1,\n onChange: width => onWidthChange?.(width),\n });\n\n return (\n // 热区透明覆盖相邻区域;只有分隔线和 pill 绘制背景,不占据布局宽度。\n <div\n className={`dishui-sidebar-resize absolute inset-y-0 z-40 hidden w-3 md:block ${side === 'right' ? 'left-0 -translate-x-1/2' : 'right-0 translate-x-1/2'}`}\n style={{ cursor: draggable && !isCollapsed ? 'ew-resize' : 'pointer', touchAction: 'none', userSelect: 'none' }}\n onPointerDown={event => { if (event.target === event.currentTarget || !(event.target as HTMLElement).closest('button')) resize.onPointerDown(event); }}\n onClickCapture={resize.onClickCapture}\n onClick={onToggle}\n >\n {/* 纵向边界线与 pill 共用区域交界处的中心轴。 */}\n <div className=\"pointer-events-none absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-hairline\" aria-hidden=\"true\" />\n {/* pill 手柄(坐落在线上,与之一体) */}\n <button\n type=\"button\"\n tabIndex={0}\n onPointerDown={resize.onPointerDown}\n onKeyDown={resize.onKeyDown}\n className=\"group absolute top-1/2 left-1/2 flex h-10 w-4 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-hairline bg-page text-tertiary shadow-none transition-[width,color] duration-200 ease-in-out hover:w-5 hover:text-primary focus-visible:outline-2 focus-visible:outline-ring\"\n style={{ cursor: draggable && !isCollapsed ? 'ew-resize' : 'pointer' }}\n aria-label={isCollapsed ? '展开侧边栏' : (draggable ? '拖拽调整侧边栏宽度,点击收起' : '收起侧边栏')}\n aria-expanded={!isCollapsed}\n aria-description={draggable && !isCollapsed ? `宽度 ${Math.round(sidebarWidth)}px;左右方向键调整,Home/End 到达最小/最大宽度,Enter/空格折叠` : undefined}\n title={draggable && !isCollapsed ? '拖拽调节宽度 · 点击折叠' : undefined}\n >\n {isCollapsed ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" className=\"pointer-events-none\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2.5\" d={side === 'right' ? 'M15 5l-7 7 7 7' : 'M9 5l7 7-7 7'} />\n </svg>\n ) : (\n <svg width=\"6\" height=\"18\" viewBox=\"0 0 6 18\" fill=\"currentColor\" aria-hidden=\"true\" className=\"pointer-events-none\">\n <circle cx=\"1.5\" cy=\"3\" r=\"1\" /><circle cx=\"4.5\" cy=\"3\" r=\"1\" />\n <circle cx=\"1.5\" cy=\"9\" r=\"1\" /><circle cx=\"4.5\" cy=\"9\" r=\"1\" />\n <circle cx=\"1.5\" cy=\"15\" r=\"1\" /><circle cx=\"4.5\" cy=\"15\" r=\"1\" />\n </svg>\n )}\n </button>\n </div>\n );\n};\n\n/**\n * 移动端悬浮侧边栏切换按钮\n */\nexport const MobileSidebarToggleButton: React.FC<Pick<SidebarToggleButtonProps, 'isCollapsed' | 'onToggle'>> = ({\n isCollapsed,\n onToggle,\n}) => {\n return (\n <button\n onClick={onToggle}\n className=\"fixed bottom-6 right-6 z-50 bg-primary bg-opacity-30 hover:bg-opacity-50 text-primary-content rounded-full p-3 shadow-lg transition-all duration-300 ease-in-out backdrop-blur-sm hover:scale-105 md:hidden\"\n style={{\n boxShadow: '0 4px 20px rgba(0, 0, 0, 0.15)',\n }}\n aria-label={isCollapsed ? '展开侧边栏' : '收起侧边栏'}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n className=\"w-5 h-5\"\n >\n {isCollapsed ? (\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\n ) : (\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n )}\n </svg>\n </button>\n );\n};\n\n/**\n * 组合的侧边栏切换按钮(包含桌面端和移动端)\n */\nexport const SidebarToggleButtons: React.FC<SidebarToggleButtonProps> = (props) => {\n return (\n <>\n <DesktopSidebarToggleButton {...props} />\n <MobileSidebarToggleButton isCollapsed={props.isCollapsed} onToggle={props.onToggle} />\n </>\n );\n};\n\nexport default SidebarToggleButtons;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Skeleton/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\nimport './Skeleton.css';\n\nexport type SkeletonProps = React.HTMLAttributes<HTMLSpanElement> & {\n width?: React.CSSProperties['width'];\n height?: React.CSSProperties['height'];\n};\n\n/** Static placeholder; the containing data region supplies the loading announcement. */\nexport default function Skeleton({ width = '100%', height = '1em', className, style, ...rest }: SkeletonProps) {\n return <span {...rest} aria-hidden=\"true\" className={cn('dishui-skeleton', className)} style={{ width, height, ...style }} />;\n}\n"],"mappings":";;;;;AAUA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["Skeleton","rest","cn","className","style"],"sources":["../../../src/components/Skeleton/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\nimport './Skeleton.css';\n\nexport type SkeletonProps = React.HTMLAttributes<HTMLSpanElement> & {\n width?: React.CSSProperties['width'];\n height?: React.CSSProperties['height'];\n};\n\n/** Static placeholder; the containing data region supplies the loading announcement. */\nexport default function Skeleton({ width = '100%', height = '1em', className, style, ...rest }: SkeletonProps) {\n return <span {...rest} aria-hidden=\"true\" className={cn('dishui-skeleton', className)} style={{ width, height, ...style }} />;\n}\n"],"mappings":";;;;;AAUA,SAAwBA,EAAS,EAAE,WAAQ,QAAQ,YAAS,OAAO,cAAW,UAAO,GAAGC,KAAuB;CAC3G,OAAO,kBAAC,QAAD;EAAM,GAAIA;EAAM,eAAY;EAAO,WAAWC,EAAG,mBAAmBC,CAAS;EAAG,OAAO;GAAE;GAAO;GAAQ,GAAGC;EAAM;CAAI,CAAA;AAChI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Slider/index.tsx"],"sourcesContent":["import React, { useId, useRef, useState } from 'react';\nimport './Slider.css';\nimport { cn } from '../../utils/cn';\n\nexport type SliderVariant =\n | 'default'\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\nexport type SliderSize = 'xs' | 'sm' | 'md' | 'lg';\n\nexport type SliderProps = {\n /** Linear remains the default. Circular starts at 12 o'clock, clockwise. */\n mode?: 'linear' | 'circular' | 'discrete';\n /** Applies to linear and discrete sliders. */\n orientation?: 'horizontal' | 'vertical';\n /** Discrete item shape and quantity (positive integer, defaults to 5). */\n shape?: 'square' | 'star' | 'heart';\n count?: number;\n /** Discrete increments: half an item instead of a whole item. */\n allowHalf?: boolean;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-valuetext'?: string;\n /** Controlled value. */\n value?: number;\n /** Uncontrolled initial value. */\n defaultValue?: number;\n /** Minimum value. */\n min?: number;\n /** Maximum value. */\n max?: number;\n /** Step increment for linear/circular modes; discrete derives it from count and allowHalf. */\n step?: number;\n /** Change handler with the numeric value. */\n onChange?: (value: number, e: React.ChangeEvent<HTMLInputElement>) => void;\n /** Optional label rendered above the track. */\n label?: React.ReactNode;\n /** Show the current value next to the label. */\n showValue?: boolean;\n /** Color variant (daisyUI). */\n variant?: SliderVariant;\n /** Size (daisyUI). */\n size?: SliderSize;\n /** Disabled state. */\n disabled?: boolean;\n /** Native name attribute. */\n name?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Inline styles on the wrapper. */\n style?: React.CSSProperties;\n};\n\nconst VARIANT_CLASS: Record<SliderVariant, string> = {\n default: '',\n primary: 'range-primary',\n secondary: 'range-secondary',\n accent: 'range-accent',\n info: 'range-info',\n success: 'range-success',\n warning: 'range-warning',\n error: 'range-error',\n};\n\nconst SIZE_CLASS: Record<SliderSize, string> = {\n xs: 'range-xs',\n sm: 'range-sm',\n md: 'range-md',\n lg: 'range-lg',\n};\n\n/**\n * Slider —— Native range semantics with linear, circular and discrete presentations.\n * Supports controlled/uncontrolled values, keyboard input and semantic colors.\n */\nconst Slider: React.FC<SliderProps> = ({\n value,\n defaultValue,\n min = 0,\n max: maxProp,\n step: stepProp,\n onChange,\n label,\n showValue = false,\n variant = 'default',\n size = 'sm',\n disabled = false,\n name,\n className = '',\n style,\n mode = 'linear',\n orientation = 'horizontal',\n shape = 'star',\n count = 5,\n allowHalf = false,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n 'aria-describedby': ariaDescribedby,\n 'aria-valuetext': ariaValueText,\n}) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const inputRef = useRef<HTMLInputElement>(null);\n const itemCount = Number.isFinite(count) ? Math.max(1, Math.floor(count)) : 5;\n const max = Math.max(min, maxProp ?? (mode === 'discrete' ? min + itemCount : 100));\n // Discrete steps are fractions of an item, even for a custom numeric range.\n const step = mode === 'discrete'\n ? (max - min) / itemCount / (allowHalf ? 2 : 1) || 1\n : stepProp !== undefined && Number.isFinite(stepProp) && stepProp > 0 ? stepProp : 1;\n const normalize = (n: number) => {\n const bounded = Math.min(max, Math.max(min, Number.isFinite(n) ? n : min));\n const ticks = Math.min(Math.round((bounded - min) / step), Math.floor((max - min) / step + 1e-10));\n return Number((min + ticks * step).toPrecision(15));\n };\n const [internal, setInternal] = useState<number>(defaultValue ?? min);\n const isControlled = value !== undefined;\n const current = normalize(isControlled ? value : internal);\n const ratio = max > min ? (current - min) / (max - min) : 0;\n const vertical = orientation === 'vertical' && mode !== 'circular';\n const custom = mode !== 'linear';\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n const next = normalize(Number(e.target.value));\n if (!isControlled) setInternal(next);\n onChange?.(next, e);\n };\n const updatePointer = (e: React.PointerEvent<HTMLDivElement>) => {\n const input = inputRef.current;\n if (disabled || !input || max === min) return;\n const rect = e.currentTarget.getBoundingClientRect();\n let fraction = vertical ? (rect.bottom - e.clientY) / rect.height : (e.clientX - rect.left) / rect.width;\n if (mode === 'circular') {\n const dx = e.clientX - rect.left - rect.width / 2;\n const dy = e.clientY - rect.top - rect.height / 2;\n if (Math.hypot(dx, dy) < rect.width * 0.15) return;\n fraction = (Math.atan2(dx, -dy) + Math.PI * 2) % (Math.PI * 2) / (Math.PI * 2);\n // Keep dragging across the seam at the nearest endpoint, not a full-range jump.\n if (Math.abs(fraction - ratio) > 0.5 && e.type === 'pointermove') fraction = ratio > 0.5 ? 1 : 0;\n }\n const next = normalize(min + Math.min(1, Math.max(0, fraction)) * (max - min));\n if (next === current) return;\n // Dispatch through the native input so consumers receive a real React change event.\n Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set?.call(input, String(next));\n input.dispatchEvent(new Event('input', { bubbles: true }));\n };\n\n return (\n <div className={cn('w-full dishui-slider', className)} style={style} data-mode={mode} data-orientation={orientation} data-size={size} data-variant={variant} data-disabled={disabled}>\n {(label !== undefined || showValue) && (\n <div className=\"mb-1 flex items-center justify-between\">\n {label !== undefined && (\n <label htmlFor={inputId} className=\"label-text text-sm text-base-content/80\">{label}</label>\n )}\n {showValue && (\n <span className=\"text-xs font-mono text-base-content/60\">{current}</span>\n )}\n </div>\n )}\n <div className=\"dishui-slider-control\"\n onPointerDown={custom ? e => {\n if (disabled || e.button !== 0) return;\n e.preventDefault();\n inputRef.current?.focus();\n e.currentTarget.setPointerCapture(e.pointerId);\n updatePointer(e);\n } : undefined}\n onPointerMove={custom ? e => { if (e.currentTarget.hasPointerCapture(e.pointerId)) updatePointer(e); } : undefined}\n onPointerUp={custom ? e => { if (e.currentTarget.hasPointerCapture(e.pointerId)) e.currentTarget.releasePointerCapture(e.pointerId); } : undefined}\n >\n <input\n ref={inputRef}\n id={inputId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-valuetext={ariaValueText}\n aria-orientation={vertical ? 'vertical' : 'horizontal'}\n type=\"range\"\n className={cn('range', VARIANT_CLASS[variant], SIZE_CLASS[size])}\n value={current}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n name={name}\n onChange={handleChange}\n />\n {mode === 'circular' && <svg className=\"dishui-slider-dial\" viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <circle className=\"dishui-slider-ring\" cx=\"50\" cy=\"50\" r=\"40\" />\n <circle className=\"dishui-slider-progress\" cx=\"50\" cy=\"50\" r=\"40\" pathLength=\"100\" strokeDasharray={`${ratio * 100} 100`} transform=\"rotate(-90 50 50)\" />\n <circle className=\"dishui-slider-thumb\" cx={50 + 40 * Math.sin(ratio * Math.PI * 2)} cy={50 - 40 * Math.cos(ratio * Math.PI * 2)} r=\"5\" />\n <text x=\"50\" y=\"50\" dominantBaseline=\"central\" textAnchor=\"middle\">{current}</text>\n </svg>}\n {mode === 'discrete' && <div className=\"dishui-slider-items\" aria-hidden=\"true\">\n {Array.from({ length: itemCount }, (_, index) => {\n const fill = Math.max(0, Math.min(1, ratio * itemCount - index));\n return <span className=\"dishui-slider-item\" key={index}>\n <svg viewBox=\"0 0 24 24\"><path d={SHAPES[shape]} /></svg>\n <span className=\"dishui-slider-item-fill\" style={{ clipPath: vertical ? `inset(${(1 - fill) * 100}% 0 0 0)` : `inset(0 ${(1 - fill) * 100}% 0 0)` }}>\n <svg viewBox=\"0 0 24 24\"><path d={SHAPES[shape]} /></svg>\n </span>\n </span>;\n })}\n </div>}\n </div>\n </div>\n );\n};\n\nconst SHAPES = {\n square: 'M3 3h18v18H3z',\n star: 'm12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z',\n heart: 'M12 21 3.5 12.5C-3 6 6-2 12 5c6-7 15 1 8.5 7.5Z',\n};\n\nexport default Slider;\n"],"mappings":";;;;;AA6DA,IAAM,IAA+C;CACnD,SAAS;CACT,SAAS;CACT,WAAW;CACX,QAAQ;CACR,MAAM;CACN,SAAS;CACT,SAAS;CACT,OAAO;AACT,GAEM,IAAyC;CAC7C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAMM,KAAiC,EACrC,UACA,iBACA,SAAM,GACN,KAAK,GACL,MAAM,GACN,aACA,UACA,eAAY,IACZ,aAAU,WACV,UAAO,MACP,cAAW,IACX,SACA,eAAY,IACZ,UACA,UAAO,UACP,iBAAc,cACd,WAAQ,QACR,WAAQ,GACR,eAAY,IACZ,OACA,cAAc,GACd,mBAAmB,GACnB,oBAAoB,GACpB,kBAAkB,QACd;CACJ,IAAM,IAAc,EAAM,GACpB,IAAU,KAAM,GAChB,IAAW,EAAyB,IAAI,GACxC,IAAY,OAAO,SAAS,CAAK,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,CAAK,CAAC,IAAI,GACtE,IAAM,KAAK,IAAI,GAAK,MAAY,MAAS,aAAa,IAAM,IAAY,IAAI,GAE5E,IAAO,MAAS,cACjB,IAAM,KAAO,KAAa,IAAY,IAAI,MAAM,IACjD,MAAa,KAAA,KAAa,OAAO,SAAS,CAAQ,KAAK,IAAW,IAAI,IAAW,GAC/E,KAAa,MAAc;EAE/B,IAAM,IAAQ,KAAK,IAAI,KAAK,OADZ,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,OAAO,SAAS,CAAC,IAAI,IAAI,CAAG,CACrC,IAAU,KAAO,CAAI,GAAG,KAAK,OAAO,IAAM,KAAO,IAAO,KAAK,CAAC;EACjG,OAAO,QAAQ,IAAM,IAAQ,EAAA,CAAM,YAAY,EAAE,CAAC;CACpD,GACM,CAAC,GAAU,KAAe,EAAiB,KAAgB,CAAG,GAC9D,IAAe,MAAU,KAAA,GACzB,IAAU,EAAU,IAAe,IAAQ,CAAQ,GACnD,IAAQ,IAAM,KAAO,IAAU,MAAQ,IAAM,KAAO,GACpD,IAAW,MAAgB,cAAc,MAAS,YAClD,IAAS,MAAS,UAClB,KAAgB,MAA2C;EAC/D,IAAI,GAAU;EACd,IAAM,IAAO,EAAU,OAAO,EAAE,OAAO,KAAK,CAAC;EAE7C,AADK,KAAc,EAAY,CAAI,GACnC,IAAW,GAAM,CAAC;CACpB,GACM,KAAiB,MAA0C;EAC/D,IAAM,IAAQ,EAAS;EACvB,IAAI,KAAY,CAAC,KAAS,MAAQ,GAAK;EACvC,IAAM,IAAO,EAAE,cAAc,sBAAsB,GAC/C,IAAW,KAAY,EAAK,SAAS,EAAE,WAAW,EAAK,UAAU,EAAE,UAAU,EAAK,QAAQ,EAAK;EACnG,IAAI,MAAS,YAAY;GACvB,IAAM,IAAK,EAAE,UAAU,EAAK,OAAO,EAAK,QAAQ,GAC1C,IAAK,EAAE,UAAU,EAAK,MAAM,EAAK,SAAS;GAChD,IAAI,KAAK,MAAM,GAAI,CAAE,IAAI,EAAK,QAAQ,KAAM;GAG5C,AAFA,KAAY,KAAK,MAAM,GAAI,CAAC,CAAE,IAAI,KAAK,KAAK,MAAM,KAAK,KAAK,MAAM,KAAK,KAAK,IAExE,KAAK,IAAI,IAAW,CAAK,IAAI,MAAO,EAAE,SAAS,kBAAe,IAAW,MAAQ;EACvF;EACA,IAAM,IAAO,EAAU,IAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAQ,CAAC,KAAK,IAAM,EAAI;EACzE,MAAS,MAEb,OAAO,yBAAyB,iBAAiB,WAAW,OAAO,CAAC,EAAE,KAAK,KAAK,GAAO,OAAO,CAAI,CAAC,GACnG,EAAM,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,GAAK,CAAC,CAAC;CAC3D;CAEA,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,wBAAwB,CAAS;EAAU;EAAO,aAAW;EAAM,oBAAkB;EAAa,aAAW;EAAM,gBAAc;EAAS,iBAAe;EAA5K,UAAA,EACI,MAAU,KAAA,KAAa,MACvB,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,MAAU,KAAA,KACT,kBAAC,SAAD;IAAO,SAAS;IAAS,WAAU;IAA2C,UAAA;GAAa,CAAA,GAE5F,KACC,kBAAC,QAAD;IAAM,WAAU;IAA0C,UAAA;GAAc,CAAA,CAEvE;EAEP,CAAA,GAAA,kBAAC,OAAD;GAAK,WAAU;GACb,eAAe,KAAS,MAAK;IACvB,KAAY,EAAE,WAAW,MAC7B,EAAE,eAAe,GACjB,EAAS,SAAS,MAAM,GACxB,EAAE,cAAc,kBAAkB,EAAE,SAAS,GAC7C,EAAc,CAAC;GACjB,IAAI,KAAA;GACJ,eAAe,KAAS,MAAK;IAAE,AAAI,EAAE,cAAc,kBAAkB,EAAE,SAAS,KAAG,EAAc,CAAC;GAAG,IAAI,KAAA;GACzG,aAAa,KAAS,MAAK;IAAE,AAAI,EAAE,cAAc,kBAAkB,EAAE,SAAS,KAAG,EAAE,cAAc,sBAAsB,EAAE,SAAS;GAAG,IAAI,KAAA;GAT3I,UAAA;IAWA,kBAAC,SAAD;KACE,KAAK;KACL,IAAI;KACJ,cAAY;KACZ,mBAAiB;KACjB,oBAAkB;KAClB,kBAAgB;KAChB,oBAAkB,IAAW,aAAa;KAC1C,MAAK;KACL,WAAW,EAAG,SAAS,EAAc,IAAU,EAAW,EAAK;KAC/D,OAAO;KACF;KACA;KACC;KACI;KACJ;KACN,UAAU;IACX,CAAA;IACA,MAAS,cAAc,kBAAC,OAAD;KAAK,WAAU;KAAqB,SAAQ;KAAc,eAAY;KAAtE,UAAA;MACtB,kBAAC,UAAD;OAAQ,WAAU;OAAqB,IAAG;OAAK,IAAG;OAAK,GAAE;MAAM,CAAA;MAC/D,kBAAC,UAAD;OAAQ,WAAU;OAAyB,IAAG;OAAK,IAAG;OAAK,GAAE;OAAK,YAAW;OAAM,iBAAiB,GAAG,IAAQ,IAAI;OAAO,WAAU;MAAqB,CAAA;MACzJ,kBAAC,UAAD;OAAQ,WAAU;OAAsB,IAAI,KAAK,KAAK,KAAK,IAAI,IAAQ,KAAK,KAAK,CAAC;OAAG,IAAI,KAAK,KAAK,KAAK,IAAI,IAAQ,KAAK,KAAK,CAAC;OAAG,GAAE;MAAK,CAAA;MACzI,kBAAC,QAAD;OAAM,GAAE;OAAK,GAAE;OAAK,kBAAiB;OAAU,YAAW;OAAU,UAAA;MAAc,CAAA;KAC/E;;IACJ,MAAS,cAAc,kBAAC,OAAD;KAAK,WAAU;KAAsB,eAAY;KACtE,UAAA,MAAM,KAAK,EAAE,QAAQ,EAAU,IAAI,GAAG,MAAU;MAC/C,IAAM,IAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,IAAQ,IAAY,CAAK,CAAC;MAC/D,OAAO,kBAAC,QAAD;OAAM,WAAU;OAAhB,UAAA,CACL,kBAAC,OAAD;QAAK,SAAQ;QAAY,UAAA,kBAAC,QAAD,EAAM,GAAG,EAAO,GAAS,CAAA;OAAM,CAAA,GACxD,kBAAC,QAAD;QAAM,WAAU;QAA0B,OAAO,EAAE,UAAU,IAAW,UAAU,IAAI,KAAQ,IAAI,YAAY,YAAY,IAAI,KAAQ,IAAI,QAAQ;QAChJ,UAAA,kBAAC,OAAD;SAAK,SAAQ;SAAY,UAAA,kBAAC,QAAD,EAAM,GAAG,EAAO,GAAS,CAAA;QAAM,CAAA;OACpD,CAAA,CACF;MAL2C,GAAA,CAK3C;KACR,CAAC;IACE,CAAA;GACA;EACF,CAAA,CAAA;;AAET,GAEM,IAAS;CACb,QAAQ;CACR,MAAM;CACN,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["VARIANT_CLASS","SIZE_CLASS","Slider","maxProp","stepProp","ariaLabel","ariaLabelledby","ariaDescribedby","ariaValueText","generatedId","useId","inputId","id","inputRef","useRef","itemCount","count","max","min","mode","step","allowHalf","normalize","ticks","n","internal","setInternal","useState","defaultValue","isControlled","value","current","ratio","vertical","orientation","custom","handleChange","disabled","next","onChange","updatePointer","input","rect","fraction","dx","dy","cn","className","size","variant","label","showValue","fill","index","SHAPES","shape"],"sources":["../../../src/components/Slider/index.tsx"],"sourcesContent":["import React, { useId, useRef, useState } from 'react';\nimport './Slider.css';\nimport { cn } from '../../utils/cn';\n\nexport type SliderVariant =\n | 'default'\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\nexport type SliderSize = 'xs' | 'sm' | 'md' | 'lg';\n\nexport type SliderProps = {\n /** Linear remains the default. Circular starts at 12 o'clock, clockwise. */\n mode?: 'linear' | 'circular' | 'discrete';\n /** Applies to linear and discrete sliders. */\n orientation?: 'horizontal' | 'vertical';\n /** Discrete item shape and quantity (positive integer, defaults to 5). */\n shape?: 'square' | 'star' | 'heart';\n count?: number;\n /** Discrete increments: half an item instead of a whole item. */\n allowHalf?: boolean;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-valuetext'?: string;\n /** Controlled value. */\n value?: number;\n /** Uncontrolled initial value. */\n defaultValue?: number;\n /** Minimum value. */\n min?: number;\n /** Maximum value. */\n max?: number;\n /** Step increment for linear/circular modes; discrete derives it from count and allowHalf. */\n step?: number;\n /** Change handler with the numeric value. */\n onChange?: (value: number, e: React.ChangeEvent<HTMLInputElement>) => void;\n /** Optional label rendered above the track. */\n label?: React.ReactNode;\n /** Show the current value next to the label. */\n showValue?: boolean;\n /** Color variant (daisyUI). */\n variant?: SliderVariant;\n /** Size (daisyUI). */\n size?: SliderSize;\n /** Disabled state. */\n disabled?: boolean;\n /** Native name attribute. */\n name?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Inline styles on the wrapper. */\n style?: React.CSSProperties;\n};\n\nconst VARIANT_CLASS: Record<SliderVariant, string> = {\n default: '',\n primary: 'range-primary',\n secondary: 'range-secondary',\n accent: 'range-accent',\n info: 'range-info',\n success: 'range-success',\n warning: 'range-warning',\n error: 'range-error',\n};\n\nconst SIZE_CLASS: Record<SliderSize, string> = {\n xs: 'range-xs',\n sm: 'range-sm',\n md: 'range-md',\n lg: 'range-lg',\n};\n\n/**\n * Slider —— Native range semantics with linear, circular and discrete presentations.\n * Supports controlled/uncontrolled values, keyboard input and semantic colors.\n */\nconst Slider: React.FC<SliderProps> = ({\n value,\n defaultValue,\n min = 0,\n max: maxProp,\n step: stepProp,\n onChange,\n label,\n showValue = false,\n variant = 'default',\n size = 'sm',\n disabled = false,\n name,\n className = '',\n style,\n mode = 'linear',\n orientation = 'horizontal',\n shape = 'star',\n count = 5,\n allowHalf = false,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n 'aria-describedby': ariaDescribedby,\n 'aria-valuetext': ariaValueText,\n}) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const inputRef = useRef<HTMLInputElement>(null);\n const itemCount = Number.isFinite(count) ? Math.max(1, Math.floor(count)) : 5;\n const max = Math.max(min, maxProp ?? (mode === 'discrete' ? min + itemCount : 100));\n // Discrete steps are fractions of an item, even for a custom numeric range.\n const step = mode === 'discrete'\n ? (max - min) / itemCount / (allowHalf ? 2 : 1) || 1\n : stepProp !== undefined && Number.isFinite(stepProp) && stepProp > 0 ? stepProp : 1;\n const normalize = (n: number) => {\n const bounded = Math.min(max, Math.max(min, Number.isFinite(n) ? n : min));\n const ticks = Math.min(Math.round((bounded - min) / step), Math.floor((max - min) / step + 1e-10));\n return Number((min + ticks * step).toPrecision(15));\n };\n const [internal, setInternal] = useState<number>(defaultValue ?? min);\n const isControlled = value !== undefined;\n const current = normalize(isControlled ? value : internal);\n const ratio = max > min ? (current - min) / (max - min) : 0;\n const vertical = orientation === 'vertical' && mode !== 'circular';\n const custom = mode !== 'linear';\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n const next = normalize(Number(e.target.value));\n if (!isControlled) setInternal(next);\n onChange?.(next, e);\n };\n const updatePointer = (e: React.PointerEvent<HTMLDivElement>) => {\n const input = inputRef.current;\n if (disabled || !input || max === min) return;\n const rect = e.currentTarget.getBoundingClientRect();\n let fraction = vertical ? (rect.bottom - e.clientY) / rect.height : (e.clientX - rect.left) / rect.width;\n if (mode === 'circular') {\n const dx = e.clientX - rect.left - rect.width / 2;\n const dy = e.clientY - rect.top - rect.height / 2;\n if (Math.hypot(dx, dy) < rect.width * 0.15) return;\n fraction = (Math.atan2(dx, -dy) + Math.PI * 2) % (Math.PI * 2) / (Math.PI * 2);\n // Keep dragging across the seam at the nearest endpoint, not a full-range jump.\n if (Math.abs(fraction - ratio) > 0.5 && e.type === 'pointermove') fraction = ratio > 0.5 ? 1 : 0;\n }\n const next = normalize(min + Math.min(1, Math.max(0, fraction)) * (max - min));\n if (next === current) return;\n // Dispatch through the native input so consumers receive a real React change event.\n Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set?.call(input, String(next));\n input.dispatchEvent(new Event('input', { bubbles: true }));\n };\n\n return (\n <div className={cn('w-full dishui-slider', className)} style={style} data-mode={mode} data-orientation={orientation} data-size={size} data-variant={variant} data-disabled={disabled}>\n {(label !== undefined || showValue) && (\n <div className=\"mb-1 flex items-center justify-between\">\n {label !== undefined && (\n <label htmlFor={inputId} className=\"label-text text-sm text-base-content/80\">{label}</label>\n )}\n {showValue && (\n <span className=\"text-xs font-mono text-base-content/60\">{current}</span>\n )}\n </div>\n )}\n <div className=\"dishui-slider-control\"\n onPointerDown={custom ? e => {\n if (disabled || e.button !== 0) return;\n e.preventDefault();\n inputRef.current?.focus();\n e.currentTarget.setPointerCapture(e.pointerId);\n updatePointer(e);\n } : undefined}\n onPointerMove={custom ? e => { if (e.currentTarget.hasPointerCapture(e.pointerId)) updatePointer(e); } : undefined}\n onPointerUp={custom ? e => { if (e.currentTarget.hasPointerCapture(e.pointerId)) e.currentTarget.releasePointerCapture(e.pointerId); } : undefined}\n >\n <input\n ref={inputRef}\n id={inputId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-valuetext={ariaValueText}\n aria-orientation={vertical ? 'vertical' : 'horizontal'}\n type=\"range\"\n className={cn('range', VARIANT_CLASS[variant], SIZE_CLASS[size])}\n value={current}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n name={name}\n onChange={handleChange}\n />\n {mode === 'circular' && <svg className=\"dishui-slider-dial\" viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <circle className=\"dishui-slider-ring\" cx=\"50\" cy=\"50\" r=\"40\" />\n <circle className=\"dishui-slider-progress\" cx=\"50\" cy=\"50\" r=\"40\" pathLength=\"100\" strokeDasharray={`${ratio * 100} 100`} transform=\"rotate(-90 50 50)\" />\n <circle className=\"dishui-slider-thumb\" cx={50 + 40 * Math.sin(ratio * Math.PI * 2)} cy={50 - 40 * Math.cos(ratio * Math.PI * 2)} r=\"5\" />\n <text x=\"50\" y=\"50\" dominantBaseline=\"central\" textAnchor=\"middle\">{current}</text>\n </svg>}\n {mode === 'discrete' && <div className=\"dishui-slider-items\" aria-hidden=\"true\">\n {Array.from({ length: itemCount }, (_, index) => {\n const fill = Math.max(0, Math.min(1, ratio * itemCount - index));\n return <span className=\"dishui-slider-item\" key={index}>\n <svg viewBox=\"0 0 24 24\"><path d={SHAPES[shape]} /></svg>\n <span className=\"dishui-slider-item-fill\" style={{ clipPath: vertical ? `inset(${(1 - fill) * 100}% 0 0 0)` : `inset(0 ${(1 - fill) * 100}% 0 0)` }}>\n <svg viewBox=\"0 0 24 24\"><path d={SHAPES[shape]} /></svg>\n </span>\n </span>;\n })}\n </div>}\n </div>\n </div>\n );\n};\n\nconst SHAPES = {\n square: 'M3 3h18v18H3z',\n star: 'm12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z',\n heart: 'M12 21 3.5 12.5C-3 6 6-2 12 5c6-7 15 1 8.5 7.5Z',\n};\n\nexport default Slider;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Switch/index.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type SwitchProps = {\n /** Controlled checked state. */\n checked?: boolean;\n /** Uncontrolled initial checked state. */\n defaultChecked?: boolean;\n /** Change handler; receives the new checked value. */\n onChange?: (checked: boolean, event: React.ChangeEvent<HTMLInputElement>) => void;\n /** Optional label rendered next to the switch. */\n label?: React.ReactNode;\n /** Label position relative to the switch. */\n labelPosition?: 'right' | 'left';\n /** Color variant (daisyUI). */\n variant?: 'default' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error';\n /** Size. */\n size?: 'xs' | 'sm' | 'md' | 'lg';\n /** Disabled state. */\n disabled?: boolean;\n /** Native name attribute (useful in forms). */\n name?: string;\n /** Native value attribute. */\n value?: string;\n /** Extra class names applied to the wrapping label element. */\n className?: string;\n /** Inline styles applied to the wrapping label element. */\n style?: React.CSSProperties;\n /** id forwarded to the input. */\n id?: string;\n};\n\nconst VARIANT_CLASS: Record<NonNullable<SwitchProps['variant']>, string> = {\n default: '',\n primary: 'toggle-primary',\n secondary: 'toggle-secondary',\n accent: 'toggle-accent',\n info: 'toggle-info',\n success: 'toggle-success',\n warning: 'toggle-warning',\n error: 'toggle-error',\n};\n\nconst SIZE_CLASS: Record<NonNullable<SwitchProps['size']>, string> = {\n xs: 'toggle-xs',\n sm: 'toggle-sm',\n md: 'toggle-md',\n lg: 'toggle-lg',\n};\n\n/**\n * Switch —— 开关控件。基于 daisyUI `toggle`,支持受控/非受控、色调变体与尺寸。\n */\nconst Switch: React.FC<SwitchProps> = ({\n checked,\n defaultChecked,\n onChange,\n label,\n labelPosition = 'right',\n variant = 'default',\n size = 'sm',\n disabled = false,\n name,\n value,\n className = '',\n style,\n id,\n}) => {\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange?.(e.target.checked, e);\n },\n [onChange],\n );\n\n const inputClasses = cn(\n 'toggle',\n VARIANT_CLASS[variant],\n SIZE_CLASS[size],\n className && !label ? className : '',\n );\n\n const input = (\n <input\n id={id}\n type=\"checkbox\"\n role=\"switch\"\n className={inputClasses}\n checked={checked}\n defaultChecked={defaultChecked}\n onChange={handleChange}\n disabled={disabled}\n name={name}\n value={value}\n />\n );\n\n if (label === undefined || label === null || label === '') {\n return input;\n }\n\n const labelClasses = cn(\n 'label cursor-pointer inline-flex items-center gap-2 w-fit',\n disabled && 'opacity-50 cursor-not-allowed',\n className,\n );\n\n return (\n <label className={labelClasses} style={style}>\n {labelPosition === 'left' && <span className=\"label-text\">{label}</span>}\n {input}\n {labelPosition === 'right' && <span className=\"label-text\">{label}</span>}\n </label>\n );\n};\n\nexport default Switch;\n"],"mappings":";;;;AAgCA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["VARIANT_CLASS","SIZE_CLASS","Switch","handleChange","useCallback","onChange","inputClasses","cn","variant","size","className","label","input","labelClasses","disabled","labelPosition"],"sources":["../../../src/components/Switch/index.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type SwitchProps = {\n /** Controlled checked state. */\n checked?: boolean;\n /** Uncontrolled initial checked state. */\n defaultChecked?: boolean;\n /** Change handler; receives the new checked value. */\n onChange?: (checked: boolean, event: React.ChangeEvent<HTMLInputElement>) => void;\n /** Optional label rendered next to the switch. */\n label?: React.ReactNode;\n /** Label position relative to the switch. */\n labelPosition?: 'right' | 'left';\n /** Color variant (daisyUI). */\n variant?: 'default' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error';\n /** Size. */\n size?: 'xs' | 'sm' | 'md' | 'lg';\n /** Disabled state. */\n disabled?: boolean;\n /** Native name attribute (useful in forms). */\n name?: string;\n /** Native value attribute. */\n value?: string;\n /** Extra class names applied to the wrapping label element. */\n className?: string;\n /** Inline styles applied to the wrapping label element. */\n style?: React.CSSProperties;\n /** id forwarded to the input. */\n id?: string;\n};\n\nconst VARIANT_CLASS: Record<NonNullable<SwitchProps['variant']>, string> = {\n default: '',\n primary: 'toggle-primary',\n secondary: 'toggle-secondary',\n accent: 'toggle-accent',\n info: 'toggle-info',\n success: 'toggle-success',\n warning: 'toggle-warning',\n error: 'toggle-error',\n};\n\nconst SIZE_CLASS: Record<NonNullable<SwitchProps['size']>, string> = {\n xs: 'toggle-xs',\n sm: 'toggle-sm',\n md: 'toggle-md',\n lg: 'toggle-lg',\n};\n\n/**\n * Switch —— 开关控件。基于 daisyUI `toggle`,支持受控/非受控、色调变体与尺寸。\n */\nconst Switch: React.FC<SwitchProps> = ({\n checked,\n defaultChecked,\n onChange,\n label,\n labelPosition = 'right',\n variant = 'default',\n size = 'sm',\n disabled = false,\n name,\n value,\n className = '',\n style,\n id,\n}) => {\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange?.(e.target.checked, e);\n },\n [onChange],\n );\n\n const inputClasses = cn(\n 'toggle',\n VARIANT_CLASS[variant],\n SIZE_CLASS[size],\n className && !label ? className : '',\n );\n\n const input = (\n <input\n id={id}\n type=\"checkbox\"\n role=\"switch\"\n className={inputClasses}\n checked={checked}\n defaultChecked={defaultChecked}\n onChange={handleChange}\n disabled={disabled}\n name={name}\n value={value}\n />\n );\n\n if (label === undefined || label === null || label === '') {\n return input;\n }\n\n const labelClasses = cn(\n 'label cursor-pointer inline-flex items-center gap-2 w-fit',\n disabled && 'opacity-50 cursor-not-allowed',\n className,\n );\n\n return (\n <label className={labelClasses} style={style}>\n {labelPosition === 'left' && <span className=\"label-text\">{label}</span>}\n {input}\n {labelPosition === 'right' && <span className=\"label-text\">{label}</span>}\n </label>\n );\n};\n\nexport default Switch;\n"],"mappings":";;;;AAgCA,IAAMA,IAAqE;CACzE,SAAS;CACT,SAAS;CACT,WAAW;CACX,QAAQ;CACR,MAAM;CACN,SAAS;CACT,SAAS;CACT,OAAO;AACT,GAEMC,IAA+D;CACnE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAKMC,KAAiC,EACrC,YACA,mBACA,aACA,UACA,mBAAgB,SAChB,aAAU,WACV,UAAO,MACP,cAAW,IACX,SACA,UACA,eAAY,IACZ,UACA,YACI;CACJ,IAAMC,IAAeC,GAClB,MAA2C;EAC1C,IAAW,EAAE,OAAO,SAAS,CAAC;CAChC,GACA,CAACC,CAAQ,CACX,GAEMC,IAAeC,EACnB,UACAP,EAAcQ,IACdP,EAAWQ,IACXC,KAAa,CAACC,IAAQD,IAAY,EACpC,GAEME,IACJ,kBAAC,SAAD;EACM;EACJ,MAAK;EACL,MAAK;EACL,WAAWN;EACF;EACO;EAChB,UAAUH;EACA;EACJ;EACC;CACR,CAAA;CAGH,IAAIQ,KAAiC,QAAQA,MAAU,IACrD,OAAOC;CAGT,IAAMC,IAAeN,EACnB,6DACAO,KAAY,iCACZJ,CACF;CAEA,OACE,kBAAC,SAAD;EAAO,WAAWG;EAAqB;EAAvC,UAAA;GACGE,MAAkB,UAAU,kBAAC,QAAD;IAAM,WAAU;IAAc,UAAAJ;GAAY,CAAA;GACtEC;GACAG,MAAkB,WAAW,kBAAC,QAAD;IAAM,WAAU;IAAc,UAAAJ;GAAY,CAAA;EACnE;;AAEX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Tab/index.tsx"],"sourcesContent":["import React, { Children, isValidElement, useCallback, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../utils/cn';\nimport { isTabNavigationKey, nextTab } from '../Tabs/tabNavigation';\n\nexport type TabPaneProps = {\n /** Stable id for the pane (used with controlled / default value) */\n id: string;\n label: React.ReactNode;\n children: React.ReactNode;\n disabled?: boolean;\n /** className on the tab button */\n tabClassName?: string;\n /** className on the active panel */\n className?: string;\n};\n\nconst TabPane: React.FC<TabPaneProps> = () => null;\n\nfunction isTabPane(\n child: React.ReactNode,\n Pane: typeof TabPane\n): child is React.ReactElement<TabPaneProps> {\n return isValidElement(child) && child.type === Pane;\n}\n\nexport type TabShape = 'square' | 'rounded' | 'pill' | 'trapezoid' | 'angled';\n\nexport type TabProps = {\n children: React.ReactNode;\n defaultValue?: string;\n value?: string;\n onValueChange?: (id: string) => void;\n variant?: 'line' | 'boxed' | 'lifted' | 'bordered';\n /** Shape of the selected-tab background.\n * - square: 0 radius (default for boxed/bordered)\n * - rounded: small radius\n * - pill: full radius capsule\n * - trapezoid: bottom-wider CSS clip-path trapezoid\n * - angled: slanted right edge\n */\n shape?: TabShape;\n size?: 'sm' | 'md' | 'lg';\n className?: string;\n tabListClassName?: string;\n panelClassName?: string;\n fullWidth?: boolean;\n};\n\nconst shapeStyle: Record<TabShape, React.CSSProperties> = {\n square: {},\n rounded: { borderRadius: '0.5rem 0.5rem 0 0' },\n pill: { borderRadius: '9999px' },\n trapezoid: {\n clipPath: 'polygon(8% 0%, 92% 0%, 100% 100%, 0% 100%)',\n borderRadius: 0,\n },\n angled: {\n clipPath: 'polygon(0 0, calc(100% - 10px) 0, 100% 100%, 0 100%)',\n borderRadius: 0,\n },\n};\n\nconst TabRoot: React.FC<TabProps> = ({\n children,\n defaultValue,\n value: valueProp,\n onValueChange,\n variant = 'line',\n shape,\n size = 'md',\n className = '',\n tabListClassName = '',\n panelClassName = '',\n fullWidth = false,\n}) => {\n const panes = useMemo(() => {\n const out: React.ReactElement<TabPaneProps>[] = [];\n Children.forEach(children, (child) => {\n if (isTabPane(child, TabPane)) {\n out.push(child);\n }\n });\n return out;\n }, [children]);\n\n const firstId = panes.find(p => !p.props.disabled)?.props.id ?? '';\n const isControlled = valueProp !== undefined;\n const [uncontrolled, setUncontrolled] = useState<string | undefined>(defaultValue);\n const requested = isControlled ? valueProp : uncontrolled;\n const active = panes.find(p => p.props.id === requested && !p.props.disabled)?.props.id ?? firstId;\n const baseId = useId();\n const tabRefs = useRef(new Map<string, HTMLButtonElement>());\n const [focusedId, setFocusedId] = useState<string | null>(null);\n const focusable = panes.find(p => p.props.id === focusedId && !p.props.disabled)?.props.id ?? active;\n const enabledPanes = panes.filter(p => !p.props.disabled);\n const onTabKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, id: string) => {\n if (event.altKey || event.ctrlKey || event.metaKey || event.nativeEvent.isComposing) return;\n const index = enabledPanes.findIndex(p => p.props.id === id);\n if (!isTabNavigationKey(event.key)) return;\n const target = nextTab(enabledPanes, index, event.key);\n event.preventDefault();\n tabRefs.current.get(target?.props.id ?? '')?.focus();\n };\n\n const setActive = useCallback(\n (id: string) => {\n if (!isControlled) setUncontrolled(id);\n onValueChange?.(id);\n },\n [isControlled, onValueChange]\n );\n\n const listVariantClass =\n variant === 'boxed'\n ? 'tabs-boxed'\n : variant === 'lifted'\n ? 'tabs-lifted'\n : variant === 'bordered'\n ? 'border border-base-300 rounded-t-lg p-0 overflow-hidden'\n : '';\n\n const listBase =\n variant === 'line' ? 'tabs gap-0 border-b border-base-300 w-full' : `tabs ${listVariantClass} w-full flex-wrap`;\n const sizeClass = size === 'sm' ? 'tab-sm' : size === 'lg' ? 'tab-lg' : '';\n\n const getTriggerStateClass = (selected: boolean) => {\n if (selected) {\n if (variant === 'line') {\n return 'tab-active z-[1] -mb-px font-semibold text-primary border-b-2 border-primary bg-base-100/80';\n }\n if (variant === 'boxed' || variant === 'lifted') {\n return 'tab-active font-semibold text-primary ring-1 ring-inset ring-primary/30 bg-primary/10';\n }\n if (variant === 'bordered') {\n return 'tab-active -mb-px z-[1] font-semibold text-primary border-b-2 border-primary bg-base-200/90';\n }\n return 'tab-active font-semibold text-primary';\n }\n if (variant === 'line') {\n return 'border-b-2 border-transparent font-normal text-base-content/50 hover:text-base-content/75';\n }\n return 'font-normal text-base-content/50 hover:text-base-content/80 hover:bg-base-200/50';\n };\n\n const activePane = panes.find((p) => p.props.id === active);\n const panel = activePane?.props.children;\n\n const resolvedShape = shape ?? (variant === 'lifted' ? 'rounded' : undefined);\n\n return (\n <div className={cn('w-full', className)}>\n <div\n role=\"tablist\"\n onBlur={event => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) setFocusedId(null);\n }}\n className={cn(listBase, fullWidth && 'grid', tabListClassName)}\n style={fullWidth ? { gridTemplateColumns: `repeat(${panes.length}, minmax(0, 1fr))` } : undefined}\n >\n {panes.map((p) => {\n const { id, label, disabled, tabClassName = '' } = p.props;\n const selected = id === active;\n const needShape = selected && resolvedShape && resolvedShape !== 'square';\n return (\n <button\n key={id}\n ref={element => {\n if (element) tabRefs.current.set(id, element);\n else tabRefs.current.delete(id);\n }}\n type=\"button\"\n id={`${baseId}-tab-${encodeURIComponent(id)}`}\n role=\"tab\"\n aria-controls={`${baseId}-panel`}\n aria-selected={selected}\n tabIndex={!disabled && id === focusable ? 0 : -1}\n disabled={disabled}\n className={cn(\n 'tab',\n 'transition-all duration-150',\n sizeClass,\n fullWidth && 'w-full justify-center',\n getTriggerStateClass(selected),\n disabled ? 'tab-disabled pointer-events-none opacity-50' : 'cursor-pointer',\n tabClassName,\n )}\n style={needShape ? shapeStyle[resolvedShape!] : undefined}\n onFocus={() => setFocusedId(id)}\n onKeyDown={event => onTabKeyDown(event, id)}\n onClick={() => setActive(id)}\n >\n {label}\n </button>\n );\n })}\n </div>\n <div\n role=\"tabpanel\"\n id={`${baseId}-panel`}\n aria-labelledby={activePane ? `${baseId}-tab-${encodeURIComponent(activePane.props.id)}` : undefined}\n className={cn('mt-3 w-full', panelClassName, activePane?.props.className)}\n >\n {panel}\n </div>\n </div>\n );\n};\n\nexport type TabComponent = React.FC<TabProps> & { Pane: typeof TabPane };\nconst Tab = TabRoot as TabComponent;\nTab.Pane = TabPane;\n\nexport { Tab };\n\nexport default Tab;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["TabPane","isTabPane","isValidElement","child","Pane","shapeStyle","Tab","valueProp","panes","useMemo","out","Children","children","firstId","p","isControlled","uncontrolled","setUncontrolled","useState","defaultValue","requested","active","baseId","useId","tabRefs","useRef","focusedId","setFocusedId","focusable","enabledPanes","onTabKeyDown","event","index","id","isTabNavigationKey","target","nextTab","setActive","useCallback","onValueChange","listBase","variant","sizeClass","size","getTriggerStateClass","selected","activePane","panel","resolvedShape","shape","cn","className","fullWidth","tabListClassName","needShape","element","disabled","tabClassName","label","panelClassName"],"sources":["../../../src/components/Tab/index.tsx"],"sourcesContent":["import React, { Children, isValidElement, useCallback, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../utils/cn';\nimport { isTabNavigationKey, nextTab } from '../Tabs/tabNavigation';\n\nexport type TabPaneProps = {\n /** Stable id for the pane (used with controlled / default value) */\n id: string;\n label: React.ReactNode;\n children: React.ReactNode;\n disabled?: boolean;\n /** className on the tab button */\n tabClassName?: string;\n /** className on the active panel */\n className?: string;\n};\n\nconst TabPane: React.FC<TabPaneProps> = () => null;\n\nfunction isTabPane(\n child: React.ReactNode,\n Pane: typeof TabPane\n): child is React.ReactElement<TabPaneProps> {\n return isValidElement(child) && child.type === Pane;\n}\n\nexport type TabShape = 'square' | 'rounded' | 'pill' | 'trapezoid' | 'angled';\n\nexport type TabProps = {\n children: React.ReactNode;\n defaultValue?: string;\n value?: string;\n onValueChange?: (id: string) => void;\n variant?: 'line' | 'boxed' | 'lifted' | 'bordered';\n /** Shape of the selected-tab background.\n * - square: 0 radius (default for boxed/bordered)\n * - rounded: small radius\n * - pill: full radius capsule\n * - trapezoid: bottom-wider CSS clip-path trapezoid\n * - angled: slanted right edge\n */\n shape?: TabShape;\n size?: 'sm' | 'md' | 'lg';\n className?: string;\n tabListClassName?: string;\n panelClassName?: string;\n fullWidth?: boolean;\n};\n\nconst shapeStyle: Record<TabShape, React.CSSProperties> = {\n square: {},\n rounded: { borderRadius: '0.5rem 0.5rem 0 0' },\n pill: { borderRadius: '9999px' },\n trapezoid: {\n clipPath: 'polygon(8% 0%, 92% 0%, 100% 100%, 0% 100%)',\n borderRadius: 0,\n },\n angled: {\n clipPath: 'polygon(0 0, calc(100% - 10px) 0, 100% 100%, 0 100%)',\n borderRadius: 0,\n },\n};\n\nconst TabRoot: React.FC<TabProps> = ({\n children,\n defaultValue,\n value: valueProp,\n onValueChange,\n variant = 'line',\n shape,\n size = 'md',\n className = '',\n tabListClassName = '',\n panelClassName = '',\n fullWidth = false,\n}) => {\n const panes = useMemo(() => {\n const out: React.ReactElement<TabPaneProps>[] = [];\n Children.forEach(children, (child) => {\n if (isTabPane(child, TabPane)) {\n out.push(child);\n }\n });\n return out;\n }, [children]);\n\n const firstId = panes.find(p => !p.props.disabled)?.props.id ?? '';\n const isControlled = valueProp !== undefined;\n const [uncontrolled, setUncontrolled] = useState<string | undefined>(defaultValue);\n const requested = isControlled ? valueProp : uncontrolled;\n const active = panes.find(p => p.props.id === requested && !p.props.disabled)?.props.id ?? firstId;\n const baseId = useId();\n const tabRefs = useRef(new Map<string, HTMLButtonElement>());\n const [focusedId, setFocusedId] = useState<string | null>(null);\n const focusable = panes.find(p => p.props.id === focusedId && !p.props.disabled)?.props.id ?? active;\n const enabledPanes = panes.filter(p => !p.props.disabled);\n const onTabKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, id: string) => {\n if (event.altKey || event.ctrlKey || event.metaKey || event.nativeEvent.isComposing) return;\n const index = enabledPanes.findIndex(p => p.props.id === id);\n if (!isTabNavigationKey(event.key)) return;\n const target = nextTab(enabledPanes, index, event.key);\n event.preventDefault();\n tabRefs.current.get(target?.props.id ?? '')?.focus();\n };\n\n const setActive = useCallback(\n (id: string) => {\n if (!isControlled) setUncontrolled(id);\n onValueChange?.(id);\n },\n [isControlled, onValueChange]\n );\n\n const listVariantClass =\n variant === 'boxed'\n ? 'tabs-boxed'\n : variant === 'lifted'\n ? 'tabs-lifted'\n : variant === 'bordered'\n ? 'border border-base-300 rounded-t-lg p-0 overflow-hidden'\n : '';\n\n const listBase =\n variant === 'line' ? 'tabs gap-0 border-b border-base-300 w-full' : `tabs ${listVariantClass} w-full flex-wrap`;\n const sizeClass = size === 'sm' ? 'tab-sm' : size === 'lg' ? 'tab-lg' : '';\n\n const getTriggerStateClass = (selected: boolean) => {\n if (selected) {\n if (variant === 'line') {\n return 'tab-active z-[1] -mb-px font-semibold text-primary border-b-2 border-primary bg-base-100/80';\n }\n if (variant === 'boxed' || variant === 'lifted') {\n return 'tab-active font-semibold text-primary ring-1 ring-inset ring-primary/30 bg-primary/10';\n }\n if (variant === 'bordered') {\n return 'tab-active -mb-px z-[1] font-semibold text-primary border-b-2 border-primary bg-base-200/90';\n }\n return 'tab-active font-semibold text-primary';\n }\n if (variant === 'line') {\n return 'border-b-2 border-transparent font-normal text-base-content/50 hover:text-base-content/75';\n }\n return 'font-normal text-base-content/50 hover:text-base-content/80 hover:bg-base-200/50';\n };\n\n const activePane = panes.find((p) => p.props.id === active);\n const panel = activePane?.props.children;\n\n const resolvedShape = shape ?? (variant === 'lifted' ? 'rounded' : undefined);\n\n return (\n <div className={cn('w-full', className)}>\n <div\n role=\"tablist\"\n onBlur={event => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) setFocusedId(null);\n }}\n className={cn(listBase, fullWidth && 'grid', tabListClassName)}\n style={fullWidth ? { gridTemplateColumns: `repeat(${panes.length}, minmax(0, 1fr))` } : undefined}\n >\n {panes.map((p) => {\n const { id, label, disabled, tabClassName = '' } = p.props;\n const selected = id === active;\n const needShape = selected && resolvedShape && resolvedShape !== 'square';\n return (\n <button\n key={id}\n ref={element => {\n if (element) tabRefs.current.set(id, element);\n else tabRefs.current.delete(id);\n }}\n type=\"button\"\n id={`${baseId}-tab-${encodeURIComponent(id)}`}\n role=\"tab\"\n aria-controls={`${baseId}-panel`}\n aria-selected={selected}\n tabIndex={!disabled && id === focusable ? 0 : -1}\n disabled={disabled}\n className={cn(\n 'tab',\n 'transition-all duration-150',\n sizeClass,\n fullWidth && 'w-full justify-center',\n getTriggerStateClass(selected),\n disabled ? 'tab-disabled pointer-events-none opacity-50' : 'cursor-pointer',\n tabClassName,\n )}\n style={needShape ? shapeStyle[resolvedShape!] : undefined}\n onFocus={() => setFocusedId(id)}\n onKeyDown={event => onTabKeyDown(event, id)}\n onClick={() => setActive(id)}\n >\n {label}\n </button>\n );\n })}\n </div>\n <div\n role=\"tabpanel\"\n id={`${baseId}-panel`}\n aria-labelledby={activePane ? `${baseId}-tab-${encodeURIComponent(activePane.props.id)}` : undefined}\n className={cn('mt-3 w-full', panelClassName, activePane?.props.className)}\n >\n {panel}\n </div>\n </div>\n );\n};\n\nexport type TabComponent = React.FC<TabProps> & { Pane: typeof TabPane };\nconst Tab = TabRoot as TabComponent;\nTab.Pane = TabPane;\n\nexport { Tab };\n\nexport default Tab;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Table/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\nimport './Table.css';\n\nexport type TableCardOptions = {\n /** Applied to each Table.Body grid. */\n gridClassName?: string;\n gridStyle?: React.CSSProperties;\n /** Applied to each body row card. */\n className?: string;\n style?: React.CSSProperties;\n fieldClassName?: string;\n fieldStyle?: React.CSSProperties;\n labelClassName?: string;\n labelStyle?: React.CSSProperties;\n};\n\nconst CardContext = React.createContext<TableCardOptions | null>(null);\nconst BodyContext = React.createContext(false);\nconst defaultCardOptions: TableCardOptions = {};\n\nexport type TableProps = {\n children: React.ReactNode;\n card?: boolean;\n cardOptions?: TableCardOptions;\n className?: string;\n onClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n} & React.TableHTMLAttributes<HTMLTableElement>;\n\nconst Table = ({\n children,\n className = '',\n card = false,\n cardOptions = defaultCardOptions,\n onClick,\n onMouseEnter,\n onMouseLeave,\n ...rest\n}: TableProps) => {\n const baseClass = 'table';\n \n const tableClasses = cn(baseClass, card && 'dishui-table-card', className);\n\n return (\n <CardContext.Provider value={card ? cardOptions : null}>\n <BodyContext.Provider value={false}>\n <table\n role={card ? 'table' : undefined}\n {...rest}\n className={tableClasses}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </table>\n </BodyContext.Provider>\n </CardContext.Provider>\n );\n};\n\n// Table.Head 组件\nexport type TableHeadProps = React.HTMLAttributes<HTMLTableSectionElement>;\n\nconst TableHead = ({\n children,\n className = '',\n ...rest\n}: TableHeadProps) => {\n const options = React.useContext(CardContext);\n const baseClass = 'table-header-group';\n \n const headClasses = cn(baseClass, className);\n\n return (\n <thead role={options ? 'rowgroup' : undefined} {...rest} className={headClasses}>\n {children}\n </thead>\n );\n};\n\n// Table.Body 组件\nexport type TableBodyProps = React.HTMLAttributes<HTMLTableSectionElement>;\n\nconst TableBody = ({\n children,\n className = '',\n style,\n ...rest\n}: TableBodyProps) => {\n const options = React.useContext(CardContext);\n const bodyClasses = cn('table-row-group', options && 'dishui-table-card__grid', options?.gridClassName, className);\n\n return (\n <BodyContext.Provider value={true}>\n <tbody\n role={options ? 'rowgroup' : undefined}\n {...rest}\n className={bodyClasses}\n style={options ? { ...options.gridStyle, ...style } : style}\n >\n {children}\n </tbody>\n </BodyContext.Provider>\n );\n};\n\n// Table.Row 组件\nexport type TableRowProps = {\n children: React.ReactNode;\n className?: string;\n selected?: boolean;\n onClick?: (e: React.MouseEvent) => void;\n onDoubleClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n} & Omit<\n React.HTMLAttributes<HTMLTableRowElement>,\n 'className' | 'onClick' | 'onDoubleClick' | 'onMouseEnter' | 'onMouseLeave'\n>;\n\nconst TableRow = ({\n children,\n className = '',\n selected = false,\n style,\n onClick,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n ...rest\n}: TableRowProps) => {\n const cardOptions = React.useContext(CardContext);\n const inBody = React.useContext(BodyContext);\n const options = inBody ? cardOptions : null;\n const baseClass = 'table-row';\n\n const rowClasses = cn(\n baseClass,\n selected && 'bg-base-200',\n 'hover:bg-base-100',\n options && 'dishui-table-card__row',\n options?.className,\n className\n );\n\n return (\n <tr\n role={cardOptions ? 'row' : undefined}\n data-card-selected={options && selected ? 'true' : undefined}\n style={options ? { ...options.style, ...style } : style}\n className={rowClasses}\n onClick={onClick}\n onDoubleClick={onDoubleClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n {...rest}\n >\n {children}\n </tr>\n );\n};\n\n// Table.Cell 组件\nexport type TableCellProps = {\n children?: React.ReactNode;\n /** Visible field label in card body cells only. */\n label?: React.ReactNode;\n className?: string;\n onClick?: (e: React.MouseEvent) => void;\n colSpan?: number;\n style?: React.CSSProperties;\n \n // 添加鼠标事件\n onDoubleClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n} & React.TdHTMLAttributes<HTMLTableCellElement>;\n\nconst TableCell = ({\n children,\n label,\n className = '',\n onClick,\n colSpan,\n style,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n ...rest\n}: TableCellProps) => {\n const cardOptions = React.useContext(CardContext);\n const inBody = React.useContext(BodyContext);\n const options = inBody ? cardOptions : null;\n const cellClasses = cn('table-cell', options && 'dishui-table-card__field', options?.fieldClassName, className);\n\n return (\n <td\n role={cardOptions ? 'cell' : undefined}\n {...rest}\n className={cellClasses}\n onClick={onClick}\n colSpan={colSpan}\n style={options ? { ...options.fieldStyle, ...style } : style}\n onDoubleClick={onDoubleClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {/* Keep children in a fixed slot so mode/label changes preserve local state. */}\n {options && label !== null && label !== undefined ? <div className={cn('dishui-table-card__label', options.labelClassName)} style={options.labelStyle}>{label}</div> : null}\n {children}\n </td>\n );\n};\n\n// Table.HeaderCell 组件\nexport type TableHeaderCellProps = {\n children: React.ReactNode;\n className?: string;\n onClick?: (e: React.MouseEvent) => void;\n sortable?: boolean;\n sortDirection?: 'asc' | 'desc' | null;\n \n // 拖拽相关属性\n draggable?: boolean;\n onDragStart?: (e: React.DragEvent) => void;\n onDragOver?: (e: React.DragEvent) => void;\n onDrop?: (e: React.DragEvent) => void;\n \n // 鼠标事件\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n} & React.ThHTMLAttributes<HTMLTableCellElement>;\n\nconst TableHeaderCell = ({\n children,\n className = '',\n style,\n onClick,\n sortable = false,\n sortDirection = null,\n \n // 拖拽相关属性\n draggable,\n onDragStart,\n onDragOver,\n onDrop,\n \n // 鼠标事件\n onMouseEnter,\n onMouseLeave,\n ...rest\n}: TableHeaderCellProps) => {\n const cardOptions = React.useContext(CardContext);\n const inBody = React.useContext(BodyContext);\n const options = inBody ? cardOptions : null;\n const baseClass = 'table-cell font-medium';\n \n const headerCellClasses = cn(\n baseClass,\n sortable && 'cursor-pointer',\n options && 'dishui-table-card__field',\n options?.fieldClassName,\n className\n );\n\n return (\n <th\n role={cardOptions ? (rest.scope === 'row' || rest.scope === 'rowgroup' || (inBody && !rest.scope) ? 'rowheader' : 'columnheader') : undefined}\n {...rest}\n style={options ? { ...options.fieldStyle, ...style } : style}\n className={headerCellClasses}\n onClick={onClick}\n draggable={draggable}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDrop={onDrop}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {sortable ? <div className=\"flex items-center gap-2\">\n {children}\n {sortable && (\n <div className=\"flex flex-col\">\n {sortDirection === 'asc' ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M5 15l7-7 7 7\" />\n </svg>\n ) : sortDirection === 'desc' ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n ) : (\n <div className=\"h-4 w-4 opacity-30\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4\" />\n </svg>\n </div>\n )}\n </div>\n )}\n </div> : children}\n </th>\n );\n};\n\nexport type TableCaptionProps = React.HTMLAttributes<HTMLTableCaptionElement>;\nexport type TableFooterProps = React.HTMLAttributes<HTMLTableSectionElement>;\nconst TableCaption = (props: TableCaptionProps) => <caption {...props} />;\nconst TableFooter = (props: TableFooterProps) => {\n const options = React.useContext(CardContext);\n return <tfoot role={options ? 'rowgroup' : undefined} {...props} />;\n};\n\n// 扩展Table组件,添加子组件\nexport type TableCardProps = Omit<TableProps, 'card'>;\n\ninterface TableSubcomponents {\n Caption: React.FC<TableCaptionProps>;\n Footer: React.FC<TableFooterProps>;\n Head: React.FC<TableHeadProps>;\n Body: React.FC<TableBodyProps>;\n Row: React.FC<TableRowProps>;\n Cell: React.FC<TableCellProps>;\n HeaderCell: React.FC<TableHeaderCellProps>;\n}\n\nconst subcomponents: TableSubcomponents = {\n Caption: TableCaption,\n Footer: TableFooter,\n Head: TableHead,\n Body: TableBody,\n Row: TableRow,\n Cell: TableCell,\n HeaderCell: TableHeaderCell,\n};\n\nconst TableCard = (props: TableCardProps) => <Table {...props} card />;\nconst TableWithCompounds = Object.assign(Table, subcomponents, {\n Card: Object.assign(TableCard, subcomponents),\n});\n\nexport default TableWithCompounds; "],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["React","CardContext","BodyContext","defaultCardOptions","Table","rest","tableClasses","cn","card","className","cardOptions","subcomponents","props","options","headClasses","bodyClasses","style","rowClasses","selected","cellClasses","label","children","inBody","headerCellClasses","sortable","sortDirection","TableWithCompounds"],"sources":["../../../src/components/Table/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\nimport './Table.css';\n\nexport type TableCardOptions = {\n /** Applied to each Table.Body grid. */\n gridClassName?: string;\n gridStyle?: React.CSSProperties;\n /** Applied to each body row card. */\n className?: string;\n style?: React.CSSProperties;\n fieldClassName?: string;\n fieldStyle?: React.CSSProperties;\n labelClassName?: string;\n labelStyle?: React.CSSProperties;\n};\n\nconst CardContext = React.createContext<TableCardOptions | null>(null);\nconst BodyContext = React.createContext(false);\nconst defaultCardOptions: TableCardOptions = {};\n\nexport type TableProps = {\n children: React.ReactNode;\n card?: boolean;\n cardOptions?: TableCardOptions;\n className?: string;\n onClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n} & React.TableHTMLAttributes<HTMLTableElement>;\n\nconst Table = ({\n children,\n className = '',\n card = false,\n cardOptions = defaultCardOptions,\n onClick,\n onMouseEnter,\n onMouseLeave,\n ...rest\n}: TableProps) => {\n const baseClass = 'table';\n \n const tableClasses = cn(baseClass, card && 'dishui-table-card', className);\n\n return (\n <CardContext.Provider value={card ? cardOptions : null}>\n <BodyContext.Provider value={false}>\n <table\n role={card ? 'table' : undefined}\n {...rest}\n className={tableClasses}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </table>\n </BodyContext.Provider>\n </CardContext.Provider>\n );\n};\n\n// Table.Head 组件\nexport type TableHeadProps = React.HTMLAttributes<HTMLTableSectionElement>;\n\nconst TableHead = ({\n children,\n className = '',\n ...rest\n}: TableHeadProps) => {\n const options = React.useContext(CardContext);\n const baseClass = 'table-header-group';\n \n const headClasses = cn(baseClass, className);\n\n return (\n <thead role={options ? 'rowgroup' : undefined} {...rest} className={headClasses}>\n {children}\n </thead>\n );\n};\n\n// Table.Body 组件\nexport type TableBodyProps = React.HTMLAttributes<HTMLTableSectionElement>;\n\nconst TableBody = ({\n children,\n className = '',\n style,\n ...rest\n}: TableBodyProps) => {\n const options = React.useContext(CardContext);\n const bodyClasses = cn('table-row-group', options && 'dishui-table-card__grid', options?.gridClassName, className);\n\n return (\n <BodyContext.Provider value={true}>\n <tbody\n role={options ? 'rowgroup' : undefined}\n {...rest}\n className={bodyClasses}\n style={options ? { ...options.gridStyle, ...style } : style}\n >\n {children}\n </tbody>\n </BodyContext.Provider>\n );\n};\n\n// Table.Row 组件\nexport type TableRowProps = {\n children: React.ReactNode;\n className?: string;\n selected?: boolean;\n onClick?: (e: React.MouseEvent) => void;\n onDoubleClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n} & Omit<\n React.HTMLAttributes<HTMLTableRowElement>,\n 'className' | 'onClick' | 'onDoubleClick' | 'onMouseEnter' | 'onMouseLeave'\n>;\n\nconst TableRow = ({\n children,\n className = '',\n selected = false,\n style,\n onClick,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n ...rest\n}: TableRowProps) => {\n const cardOptions = React.useContext(CardContext);\n const inBody = React.useContext(BodyContext);\n const options = inBody ? cardOptions : null;\n const baseClass = 'table-row';\n\n const rowClasses = cn(\n baseClass,\n selected && 'bg-base-200',\n 'hover:bg-base-100',\n options && 'dishui-table-card__row',\n options?.className,\n className\n );\n\n return (\n <tr\n role={cardOptions ? 'row' : undefined}\n data-card-selected={options && selected ? 'true' : undefined}\n style={options ? { ...options.style, ...style } : style}\n className={rowClasses}\n onClick={onClick}\n onDoubleClick={onDoubleClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n {...rest}\n >\n {children}\n </tr>\n );\n};\n\n// Table.Cell 组件\nexport type TableCellProps = {\n children?: React.ReactNode;\n /** Visible field label in card body cells only. */\n label?: React.ReactNode;\n className?: string;\n onClick?: (e: React.MouseEvent) => void;\n colSpan?: number;\n style?: React.CSSProperties;\n \n // 添加鼠标事件\n onDoubleClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n} & React.TdHTMLAttributes<HTMLTableCellElement>;\n\nconst TableCell = ({\n children,\n label,\n className = '',\n onClick,\n colSpan,\n style,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n ...rest\n}: TableCellProps) => {\n const cardOptions = React.useContext(CardContext);\n const inBody = React.useContext(BodyContext);\n const options = inBody ? cardOptions : null;\n const cellClasses = cn('table-cell', options && 'dishui-table-card__field', options?.fieldClassName, className);\n\n return (\n <td\n role={cardOptions ? 'cell' : undefined}\n {...rest}\n className={cellClasses}\n onClick={onClick}\n colSpan={colSpan}\n style={options ? { ...options.fieldStyle, ...style } : style}\n onDoubleClick={onDoubleClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {/* Keep children in a fixed slot so mode/label changes preserve local state. */}\n {options && label !== null && label !== undefined ? <div className={cn('dishui-table-card__label', options.labelClassName)} style={options.labelStyle}>{label}</div> : null}\n {children}\n </td>\n );\n};\n\n// Table.HeaderCell 组件\nexport type TableHeaderCellProps = {\n children: React.ReactNode;\n className?: string;\n onClick?: (e: React.MouseEvent) => void;\n sortable?: boolean;\n sortDirection?: 'asc' | 'desc' | null;\n \n // 拖拽相关属性\n draggable?: boolean;\n onDragStart?: (e: React.DragEvent) => void;\n onDragOver?: (e: React.DragEvent) => void;\n onDrop?: (e: React.DragEvent) => void;\n \n // 鼠标事件\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n} & React.ThHTMLAttributes<HTMLTableCellElement>;\n\nconst TableHeaderCell = ({\n children,\n className = '',\n style,\n onClick,\n sortable = false,\n sortDirection = null,\n \n // 拖拽相关属性\n draggable,\n onDragStart,\n onDragOver,\n onDrop,\n \n // 鼠标事件\n onMouseEnter,\n onMouseLeave,\n ...rest\n}: TableHeaderCellProps) => {\n const cardOptions = React.useContext(CardContext);\n const inBody = React.useContext(BodyContext);\n const options = inBody ? cardOptions : null;\n const baseClass = 'table-cell font-medium';\n \n const headerCellClasses = cn(\n baseClass,\n sortable && 'cursor-pointer',\n options && 'dishui-table-card__field',\n options?.fieldClassName,\n className\n );\n\n return (\n <th\n role={cardOptions ? (rest.scope === 'row' || rest.scope === 'rowgroup' || (inBody && !rest.scope) ? 'rowheader' : 'columnheader') : undefined}\n {...rest}\n style={options ? { ...options.fieldStyle, ...style } : style}\n className={headerCellClasses}\n onClick={onClick}\n draggable={draggable}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDrop={onDrop}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {sortable ? <div className=\"flex items-center gap-2\">\n {children}\n {sortable && (\n <div className=\"flex flex-col\">\n {sortDirection === 'asc' ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M5 15l7-7 7 7\" />\n </svg>\n ) : sortDirection === 'desc' ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n ) : (\n <div className=\"h-4 w-4 opacity-30\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4\" />\n </svg>\n </div>\n )}\n </div>\n )}\n </div> : children}\n </th>\n );\n};\n\nexport type TableCaptionProps = React.HTMLAttributes<HTMLTableCaptionElement>;\nexport type TableFooterProps = React.HTMLAttributes<HTMLTableSectionElement>;\nconst TableCaption = (props: TableCaptionProps) => <caption {...props} />;\nconst TableFooter = (props: TableFooterProps) => {\n const options = React.useContext(CardContext);\n return <tfoot role={options ? 'rowgroup' : undefined} {...props} />;\n};\n\n// 扩展Table组件,添加子组件\nexport type TableCardProps = Omit<TableProps, 'card'>;\n\ninterface TableSubcomponents {\n Caption: React.FC<TableCaptionProps>;\n Footer: React.FC<TableFooterProps>;\n Head: React.FC<TableHeadProps>;\n Body: React.FC<TableBodyProps>;\n Row: React.FC<TableRowProps>;\n Cell: React.FC<TableCellProps>;\n HeaderCell: React.FC<TableHeaderCellProps>;\n}\n\nconst subcomponents: TableSubcomponents = {\n Caption: TableCaption,\n Footer: TableFooter,\n Head: TableHead,\n Body: TableBody,\n Row: TableRow,\n Cell: TableCell,\n HeaderCell: TableHeaderCell,\n};\n\nconst TableCard = (props: TableCardProps) => <Table {...props} card />;\nconst TableWithCompounds = Object.assign(Table, subcomponents, {\n Card: Object.assign(TableCard, subcomponents),\n});\n\nexport default TableWithCompounds; "],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Tabs/index.tsx"],"sourcesContent":["import React, { useId, useRef, useState } from 'react';\nimport { cn } from '../../utils/cn';\nimport { isTabNavigationKey, nextTab } from './tabNavigation';\n\nexport type TabItem<T extends string = string> = {\n key: T;\n label: React.ReactNode;\n /** 可选:标签前的图标 */\n icon?: React.ReactNode;\n /** 禁用该标签 */\n disabled?: boolean;\n /** Stable tab ID; use as the external panel's aria-labelledby. Generated when omitted. */\n id?: string;\n /** ID of a caller-rendered role=\"tabpanel\". Omit when used only as a filter. */\n panelId?: string;\n};\n\nexport type TabsProps<T extends string = string> = {\n items: readonly TabItem<T>[];\n /** 当前激活的 tab key */\n value: T;\n /** 切换回调 */\n onChange: (key: T) => void;\n /**\n * 外观(基于 daisyUI 5 的 tabs 修饰类):\n * - `box` 实心分段(tabs-box)\n * - `border` 底部下划线(tabs-border)\n * - `lift` 抬升的文件夹页签(tabs-lift)\n * - `pill` 胶囊/圆角实心(DishUI 扩展)\n */\n variant?: 'box' | 'border' | 'lift' | 'pill';\n /** 尺寸:xs / sm / md / lg / xl */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** 占满可用宽度,各标签平分 */\n block?: boolean;\n /** Tablist ID and prefix for generated tab IDs. */\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n orientation?: 'horizontal' | 'vertical';\n /** Manual (default): arrows move focus; Enter/Space activate. Automatic: arrows also activate. */\n activationMode?: 'manual' | 'automatic';\n className?: string;\n};\n\nconst SIZE_CLASS: Record<NonNullable<TabsProps['size']>, string> = {\n xs: 'tabs-xs',\n sm: 'tabs-sm',\n md: 'tabs-md',\n lg: 'tabs-lg',\n xl: 'tabs-xl',\n};\n\n/**\n * 标签页切换条。基于 daisyUI 5 的 `tabs` 系列修饰类,\n * 支持 box / border / lift / pill 四种外观、五档尺寸与等宽(block)模式。\n */\nfunction Tabs<T extends string = string>({\n items,\n value,\n onChange,\n variant = 'box',\n size = 'sm',\n block = false,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n orientation = 'horizontal',\n activationMode = 'manual',\n className = '',\n}: TabsProps<T>) {\n const generatedId = useId();\n const listId = id ?? `tabs-${generatedId}`;\n const buttons = useRef(new Map<T, HTMLButtonElement>());\n const [focusedKey, setFocusedKey] = useState<T | null>(null);\n const enabledItems = items.filter(item => !item.disabled);\n const tabStop = enabledItems.find(item => item.key === focusedKey)?.key\n ?? enabledItems.find(item => item.key === value)?.key\n ?? enabledItems[0]?.key;\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, key: T) => {\n if (event.target !== event.currentTarget || event.defaultPrevented || event.nativeEvent.isComposing || event.altKey || event.ctrlKey || event.metaKey) return;\n if (!isTabNavigationKey(event.key, orientation)) return; // Native button Enter/Space activation goes through onClick once.\n const target = nextTab(enabledItems, enabledItems.findIndex(item => item.key === key), event.key, orientation);\n event.preventDefault();\n event.stopPropagation();\n if (!target) return;\n buttons.current.get(target.key)?.focus();\n if (activationMode === 'automatic' && target.key !== value) onChange(target.key);\n };\n // pill 是 DishUI 扩展:在 tabs-box 基础上追加胶囊圆角类(见 components.css)\n const variantClass =\n variant === 'border' ? 'tabs-border'\n : variant === 'lift' ? 'tabs-lift'\n : variant === 'pill' ? 'tabs-box dishui-tabs-pill'\n : 'tabs-box';\n\n return (\n <div\n id={listId}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-orientation={orientation}\n onBlur={event => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) setFocusedKey(null);\n }}\n className={cn(\n 'tabs h-auto min-h-0',\n SIZE_CLASS[size],\n variantClass,\n block && 'w-full',\n orientation === 'vertical' && 'flex flex-col',\n className,\n )}\n >\n {items.map((item) => (\n <button\n key={item.key}\n ref={element => {\n if (element) buttons.current.set(item.key, element);\n else buttons.current.delete(item.key);\n }}\n id={item.id ?? `${listId}-tab-${encodeURIComponent(item.key)}`}\n role=\"tab\"\n type=\"button\"\n aria-selected={value === item.key}\n aria-controls={item.panelId}\n tabIndex={!item.disabled && item.key === tabStop ? 0 : -1}\n disabled={item.disabled}\n onFocus={() => setFocusedKey(item.key)}\n onKeyDown={event => handleKeyDown(event, item.key)}\n onClick={() => onChange(item.key)}\n className={cn(\n 'tab min-h-0 gap-1.5',\n block && 'flex-1',\n value === item.key && 'tab-active',\n item.disabled && 'tab-disabled',\n )}\n >\n {item.icon && <span className=\"[&>svg]:h-[1.1em] [&>svg]:w-[1.1em]\">{item.icon}</span>}\n {item.label}\n </button>\n ))}\n </div>\n );\n}\n\nexport default Tabs;\n"],"mappings":";;;;;AA6CA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["SIZE_CLASS","Tabs","ariaLabel","ariaLabelledby","generatedId","useId","listId","id","buttons","useRef","focusedKey","setFocusedKey","useState","enabledItems","items","item","tabStop","value","handleKeyDown","event","isTabNavigationKey","orientation","target","nextTab","key","activationMode","onChange","variantClass","variant","cn","size","block","className","element"],"sources":["../../../src/components/Tabs/index.tsx"],"sourcesContent":["import React, { useId, useRef, useState } from 'react';\nimport { cn } from '../../utils/cn';\nimport { isTabNavigationKey, nextTab } from './tabNavigation';\n\nexport type TabItem<T extends string = string> = {\n key: T;\n label: React.ReactNode;\n /** 可选:标签前的图标 */\n icon?: React.ReactNode;\n /** 禁用该标签 */\n disabled?: boolean;\n /** Stable tab ID; use as the external panel's aria-labelledby. Generated when omitted. */\n id?: string;\n /** ID of a caller-rendered role=\"tabpanel\". Omit when used only as a filter. */\n panelId?: string;\n};\n\nexport type TabsProps<T extends string = string> = {\n items: readonly TabItem<T>[];\n /** 当前激活的 tab key */\n value: T;\n /** 切换回调 */\n onChange: (key: T) => void;\n /**\n * 外观(基于 daisyUI 5 的 tabs 修饰类):\n * - `box` 实心分段(tabs-box)\n * - `border` 底部下划线(tabs-border)\n * - `lift` 抬升的文件夹页签(tabs-lift)\n * - `pill` 胶囊/圆角实心(DishUI 扩展)\n */\n variant?: 'box' | 'border' | 'lift' | 'pill';\n /** 尺寸:xs / sm / md / lg / xl */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** 占满可用宽度,各标签平分 */\n block?: boolean;\n /** Tablist ID and prefix for generated tab IDs. */\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n orientation?: 'horizontal' | 'vertical';\n /** Manual (default): arrows move focus; Enter/Space activate. Automatic: arrows also activate. */\n activationMode?: 'manual' | 'automatic';\n className?: string;\n};\n\nconst SIZE_CLASS: Record<NonNullable<TabsProps['size']>, string> = {\n xs: 'tabs-xs',\n sm: 'tabs-sm',\n md: 'tabs-md',\n lg: 'tabs-lg',\n xl: 'tabs-xl',\n};\n\n/**\n * 标签页切换条。基于 daisyUI 5 的 `tabs` 系列修饰类,\n * 支持 box / border / lift / pill 四种外观、五档尺寸与等宽(block)模式。\n */\nfunction Tabs<T extends string = string>({\n items,\n value,\n onChange,\n variant = 'box',\n size = 'sm',\n block = false,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n orientation = 'horizontal',\n activationMode = 'manual',\n className = '',\n}: TabsProps<T>) {\n const generatedId = useId();\n const listId = id ?? `tabs-${generatedId}`;\n const buttons = useRef(new Map<T, HTMLButtonElement>());\n const [focusedKey, setFocusedKey] = useState<T | null>(null);\n const enabledItems = items.filter(item => !item.disabled);\n const tabStop = enabledItems.find(item => item.key === focusedKey)?.key\n ?? enabledItems.find(item => item.key === value)?.key\n ?? enabledItems[0]?.key;\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>, key: T) => {\n if (event.target !== event.currentTarget || event.defaultPrevented || event.nativeEvent.isComposing || event.altKey || event.ctrlKey || event.metaKey) return;\n if (!isTabNavigationKey(event.key, orientation)) return; // Native button Enter/Space activation goes through onClick once.\n const target = nextTab(enabledItems, enabledItems.findIndex(item => item.key === key), event.key, orientation);\n event.preventDefault();\n event.stopPropagation();\n if (!target) return;\n buttons.current.get(target.key)?.focus();\n if (activationMode === 'automatic' && target.key !== value) onChange(target.key);\n };\n // pill 是 DishUI 扩展:在 tabs-box 基础上追加胶囊圆角类(见 components.css)\n const variantClass =\n variant === 'border' ? 'tabs-border'\n : variant === 'lift' ? 'tabs-lift'\n : variant === 'pill' ? 'tabs-box dishui-tabs-pill'\n : 'tabs-box';\n\n return (\n <div\n id={listId}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-orientation={orientation}\n onBlur={event => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) setFocusedKey(null);\n }}\n className={cn(\n 'tabs h-auto min-h-0',\n SIZE_CLASS[size],\n variantClass,\n block && 'w-full',\n orientation === 'vertical' && 'flex flex-col',\n className,\n )}\n >\n {items.map((item) => (\n <button\n key={item.key}\n ref={element => {\n if (element) buttons.current.set(item.key, element);\n else buttons.current.delete(item.key);\n }}\n id={item.id ?? `${listId}-tab-${encodeURIComponent(item.key)}`}\n role=\"tab\"\n type=\"button\"\n aria-selected={value === item.key}\n aria-controls={item.panelId}\n tabIndex={!item.disabled && item.key === tabStop ? 0 : -1}\n disabled={item.disabled}\n onFocus={() => setFocusedKey(item.key)}\n onKeyDown={event => handleKeyDown(event, item.key)}\n onClick={() => onChange(item.key)}\n className={cn(\n 'tab min-h-0 gap-1.5',\n block && 'flex-1',\n value === item.key && 'tab-active',\n item.disabled && 'tab-disabled',\n )}\n >\n {item.icon && <span className=\"[&>svg]:h-[1.1em] [&>svg]:w-[1.1em]\">{item.icon}</span>}\n {item.label}\n </button>\n ))}\n </div>\n );\n}\n\nexport default Tabs;\n"],"mappings":";;;;;AA6CA,IAAMA,IAA6D;CAC/D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACR;AAMA,SAASC,EAAgC,EACrC,UACA,UACA,aACA,aAAU,OACV,UAAO,MACP,WAAQ,IACR,OACA,cAAcC,GACd,mBAAmBC,GACnB,iBAAc,cACd,oBAAiB,UACjB,eAAY,MACC;CACb,IAAMC,IAAcC,EAAM,GACpBC,IAASC,KAAM,QAAQH,KACvBI,IAAUC,kBAAO,IAAI,IAA0B,CAAC,GAChD,CAACC,GAAYC,KAAiBC,EAAmB,IAAI,GACrDC,IAAeC,EAAM,QAAO,MAAQ,CAACC,EAAK,QAAQ,GAClDC,IAAUH,EAAa,MAAK,MAAQE,EAAK,QAAQL,CAAU,CAAC,EAAE,OAC7DG,EAAa,MAAK,MAAQE,EAAK,QAAQE,CAAK,CAAC,EAAE,OAC/CJ,EAAa,EAAE,EAAE,KAElBK,KAAiB,GAA+C,MAAW;EAE7E,IADIC,EAAM,WAAWA,EAAM,iBAAiBA,EAAM,oBAAoBA,EAAM,YAAY,eAAeA,EAAM,UAAUA,EAAM,WAAWA,EAAM,WAC1I,CAACC,EAAmBD,EAAM,KAAKE,CAAW,GAAG;EACjD,IAAMC,IAASC,EAAQV,GAAcA,EAAa,WAAU,MAAQE,EAAK,QAAQS,CAAG,GAAGL,EAAM,KAAKE,CAAW;EAG7G,AAFAF,EAAM,eAAe,GACrBA,EAAM,gBAAgB,GACjBG,MACLd,EAAQ,QAAQ,IAAIc,EAAO,GAAG,CAAC,EAAE,MAAM,GACnCG,MAAmB,eAAeH,EAAO,QAAQL,KAAOS,EAASJ,EAAO,GAAG;CACnF,GAEMK,IACFC,MAAY,WAAW,gBACrBA,MAAY,SAAS,cACrBA,MAAY,SAAS,8BACrB;CAEN,OACI,kBAAC,OAAD;EACI,IAAItB;EACJ,MAAK;EACL,cAAYJ;EACZ,mBAAiBC;EACjB,oBAAkBkB;EAClB,SAAQ,MAAS;GACb,AAAKF,EAAM,cAAc,SAASA,EAAM,aAA4B,KAAGR,EAAc,IAAI;EAC7F;EACA,WAAWkB,EACP,uBACA7B,EAAW8B,IACXH,GACAI,KAAS,UACTV,MAAgB,cAAc,iBAC9BW,CACJ;EAEC,UAAAlB,EAAM,KAAK,MACR,kBAAC,UAAD;GAEI,MAAK,MAAW;IACZ,AAAImB,IAASzB,EAAQ,QAAQ,IAAIO,EAAK,KAAKkB,CAAO,IAC7CzB,EAAQ,QAAQ,OAAOO,EAAK,GAAG;GACxC;GACA,IAAIA,EAAK,MAAM,GAAGT,EAAO,OAAO,mBAAmBS,EAAK,GAAG;GAC3D,MAAK;GACL,MAAK;GACL,iBAAeE,MAAUF,EAAK;GAC9B,iBAAeA,EAAK;GACpB,UAAU,CAACA,EAAK,YAAYA,EAAK,QAAQC,IAAU,IAAI;GACvD,UAAUD,EAAK;GACf,eAAeJ,EAAcI,EAAK,GAAG;GACrC,YAAW,MAASG,EAAcC,GAAOJ,EAAK,GAAG;GACjD,eAAeW,EAASX,EAAK,GAAG;GAChC,WAAWc,EACP,uBACAE,KAAS,UACTd,MAAUF,EAAK,OAAO,cACtBA,EAAK,YAAY,cACrB;GArBJ,UAAA,CAuBKA,EAAK,QAAQ,kBAAC,QAAD;IAAM,WAAU;IAAuC,UAAAA,EAAK;GAAW,CAAA,GACpFA,EAAK,KACF;EAxBC,GAAAA,EAAK,GAwBN,CACX;CACA,CAAA;AAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabNavigation.js","names":[],"sources":["../../../src/components/Tabs/tabNavigation.ts"],"sourcesContent":["export function isTabNavigationKey(key: string, orientation: 'horizontal' | 'vertical' = 'horizontal'): boolean {\n return key === 'Home' || key === 'End' || key === (orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft') || key === (orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight');\n}\n\nexport function nextTab<T>(items: readonly T[], index: number, key: string, orientation: 'horizontal' | 'vertical' = 'horizontal'): T | undefined {\n if (key === 'Home') return items[0];\n if (key === 'End') return items[items.length - 1];\n const previous = orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft';\n const next = orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight';\n if (key !== previous && key !== next) return undefined;\n return items[(index + (key === next ? 1 : -1) + items.length) % items.length];\n}\n"],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"tabNavigation.js","names":["isTabNavigationKey","key","orientation","nextTab","items","previous","next","index"],"sources":["../../../src/components/Tabs/tabNavigation.ts"],"sourcesContent":["export function isTabNavigationKey(key: string, orientation: 'horizontal' | 'vertical' = 'horizontal'): boolean {\n return key === 'Home' || key === 'End' || key === (orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft') || key === (orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight');\n}\n\nexport function nextTab<T>(items: readonly T[], index: number, key: string, orientation: 'horizontal' | 'vertical' = 'horizontal'): T | undefined {\n if (key === 'Home') return items[0];\n if (key === 'End') return items[items.length - 1];\n const previous = orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft';\n const next = orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight';\n if (key !== previous && key !== next) return undefined;\n return items[(index + (key === next ? 1 : -1) + items.length) % items.length];\n}\n"],"mappings":";AAAA,SAAgBA,EAAmB,GAAa,IAAyC,cAAuB;CAC5G,OAAOC,MAAQ,UAAUA,MAAQ,SAASA,OAASC,MAAgB,aAAa,YAAY,gBAAgBD,OAASC,MAAgB,aAAa,cAAc;AACpK;AAEA,SAAgBC,EAAW,GAAqB,GAAe,GAAa,IAAyC,cAA6B;CAC9I,IAAIF,MAAQ,QAAQ,OAAOG,EAAM;CACjC,IAAIH,MAAQ,OAAO,OAAOG,EAAMA,EAAM,SAAS;CAC/C,IAAMC,IAAWH,MAAgB,aAAa,YAAY,aACpDI,IAAOJ,MAAgB,aAAa,cAAc;CACxD,IAAID,MAAQI,KAAYJ,MAAQK,GAChC,OAAOF,GAAOG,KAASN,MAAQK,IAAO,IAAI,MAAMF,EAAM,UAAUA,EAAM;AAC1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Text/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type TextElement =\n | 'span'\n | 'p'\n | 'div'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'strong'\n | 'em'\n | 'small'\n | 'code';\n\nexport type TextSize =\n | 'xs'\n | 'sm'\n | 'base'\n | 'lg'\n | 'xl'\n | '2xl'\n | '3xl'\n | '4xl';\n\nexport type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold';\n\nexport type TextColor =\n | 'default'\n | 'muted'\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'info'\n | 'success'\n | 'warning'\n | 'error'\n | 'inherit';\n\nexport type TextAlign = 'left' | 'center' | 'right' | 'justify';\n\nexport type TextProps = Omit<React.HTMLAttributes<HTMLElement>, 'color'> & {\n children?: React.ReactNode;\n /** Rendered HTML element. */\n as?: TextElement;\n /** Font size preset. */\n size?: TextSize;\n /** Font weight. */\n weight?: TextWeight;\n /** `muted` is neutral supporting text; `secondary` is the explicit theme brand color. */\n color?: TextColor;\n /** Text alignment. */\n align?: TextAlign;\n /** Single-line ellipsis. */\n truncate?: boolean;\n /** Multi-line clamp (number of lines). */\n clamp?: number;\n /** Italic style. */\n italic?: boolean;\n /** Underline decoration. */\n underline?: boolean;\n /** Uppercase + letter-spacing (overline style). */\n uppercase?: boolean;\n /** Monospace font. */\n mono?: boolean;\n /** Extra class names. */\n className?: string;\n /** Inline styles. */\n style?: React.CSSProperties;\n /** Click handler. */\n onClick?: (e: React.MouseEvent<HTMLElement>) => void;\n};\n\nconst SIZE_CLASS: Record<TextSize, string> = {\n xs: 'text-xs',\n sm: 'text-sm',\n base: 'text-base',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n '3xl': 'text-3xl',\n '4xl': 'text-4xl',\n};\n\nconst WEIGHT_CLASS: Record<TextWeight, string> = {\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n};\n\nconst COLOR_CLASS: Record<TextColor, string> = {\n default: 'text-base-content',\n muted: 'text-[color:var(--dishui-text-secondary)]',\n primary: 'text-primary',\n secondary: 'text-[color:var(--color-secondary)]',\n accent: 'text-accent',\n info: 'text-info',\n success: 'text-success',\n warning: 'text-warning',\n error: 'text-error',\n inherit: '',\n};\n\nconst ALIGN_CLASS: Record<TextAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n justify: 'text-justify',\n};\n\n/**\n * Text —— A2UI 展示组件:文本排版原语。\n * 统一字号 / 字重 / 语义色 / 对齐与截断,替代散落各处的裸 `text-*` 组合。\n */\nconst Text: React.FC<TextProps> = ({\n children,\n as = 'span',\n size = 'base',\n weight = 'normal',\n color = 'default',\n align,\n truncate = false,\n clamp,\n italic = false,\n underline = false,\n uppercase = false,\n mono = false,\n className = '',\n style,\n onClick,\n ...attributes\n}) => {\n const Tag = as as React.ElementType;\n\n const classes = cn(\n SIZE_CLASS[size],\n WEIGHT_CLASS[weight],\n COLOR_CLASS[color],\n align && ALIGN_CLASS[align],\n truncate && 'truncate',\n italic && 'italic',\n underline && 'underline',\n uppercase && 'uppercase tracking-wider',\n mono && 'font-mono',\n !truncate && clamp && clamp > 0 && 'overflow-hidden',\n className,\n );\n\n const clampStyle: React.CSSProperties =\n !truncate && clamp && clamp > 0\n ? {\n display: '-webkit-box',\n WebkitLineClamp: clamp,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n }\n : {};\n\n return (\n <Tag {...attributes} className={classes} style={{ ...clampStyle, ...style }} onClick={onClick}>\n {children}\n </Tag>\n );\n};\n\nexport default Text;\n"],"mappings":";;;;AA4EA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["SIZE_CLASS","WEIGHT_CLASS","COLOR_CLASS","ALIGN_CLASS","Text","attributes","Tag","as","classes","cn","size","weight","color","align","truncate","italic","underline","uppercase","mono","clamp","className","clampStyle","style"],"sources":["../../../src/components/Text/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type TextElement =\n | 'span'\n | 'p'\n | 'div'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'strong'\n | 'em'\n | 'small'\n | 'code';\n\nexport type TextSize =\n | 'xs'\n | 'sm'\n | 'base'\n | 'lg'\n | 'xl'\n | '2xl'\n | '3xl'\n | '4xl';\n\nexport type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold';\n\nexport type TextColor =\n | 'default'\n | 'muted'\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'info'\n | 'success'\n | 'warning'\n | 'error'\n | 'inherit';\n\nexport type TextAlign = 'left' | 'center' | 'right' | 'justify';\n\nexport type TextProps = Omit<React.HTMLAttributes<HTMLElement>, 'color'> & {\n children?: React.ReactNode;\n /** Rendered HTML element. */\n as?: TextElement;\n /** Font size preset. */\n size?: TextSize;\n /** Font weight. */\n weight?: TextWeight;\n /** `muted` is neutral supporting text; `secondary` is the explicit theme brand color. */\n color?: TextColor;\n /** Text alignment. */\n align?: TextAlign;\n /** Single-line ellipsis. */\n truncate?: boolean;\n /** Multi-line clamp (number of lines). */\n clamp?: number;\n /** Italic style. */\n italic?: boolean;\n /** Underline decoration. */\n underline?: boolean;\n /** Uppercase + letter-spacing (overline style). */\n uppercase?: boolean;\n /** Monospace font. */\n mono?: boolean;\n /** Extra class names. */\n className?: string;\n /** Inline styles. */\n style?: React.CSSProperties;\n /** Click handler. */\n onClick?: (e: React.MouseEvent<HTMLElement>) => void;\n};\n\nconst SIZE_CLASS: Record<TextSize, string> = {\n xs: 'text-xs',\n sm: 'text-sm',\n base: 'text-base',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n '3xl': 'text-3xl',\n '4xl': 'text-4xl',\n};\n\nconst WEIGHT_CLASS: Record<TextWeight, string> = {\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n};\n\nconst COLOR_CLASS: Record<TextColor, string> = {\n default: 'text-base-content',\n muted: 'text-[color:var(--dishui-text-secondary)]',\n primary: 'text-primary',\n secondary: 'text-[color:var(--color-secondary)]',\n accent: 'text-accent',\n info: 'text-info',\n success: 'text-success',\n warning: 'text-warning',\n error: 'text-error',\n inherit: '',\n};\n\nconst ALIGN_CLASS: Record<TextAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n justify: 'text-justify',\n};\n\n/**\n * Text —— A2UI 展示组件:文本排版原语。\n * 统一字号 / 字重 / 语义色 / 对齐与截断,替代散落各处的裸 `text-*` 组合。\n */\nconst Text: React.FC<TextProps> = ({\n children,\n as = 'span',\n size = 'base',\n weight = 'normal',\n color = 'default',\n align,\n truncate = false,\n clamp,\n italic = false,\n underline = false,\n uppercase = false,\n mono = false,\n className = '',\n style,\n onClick,\n ...attributes\n}) => {\n const Tag = as as React.ElementType;\n\n const classes = cn(\n SIZE_CLASS[size],\n WEIGHT_CLASS[weight],\n COLOR_CLASS[color],\n align && ALIGN_CLASS[align],\n truncate && 'truncate',\n italic && 'italic',\n underline && 'underline',\n uppercase && 'uppercase tracking-wider',\n mono && 'font-mono',\n !truncate && clamp && clamp > 0 && 'overflow-hidden',\n className,\n );\n\n const clampStyle: React.CSSProperties =\n !truncate && clamp && clamp > 0\n ? {\n display: '-webkit-box',\n WebkitLineClamp: clamp,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n }\n : {};\n\n return (\n <Tag {...attributes} className={classes} style={{ ...clampStyle, ...style }} onClick={onClick}>\n {children}\n </Tag>\n );\n};\n\nexport default Text;\n"],"mappings":";;;;AA4EA,IAAMA,IAAuC;CAC3C,IAAI;CACJ,IAAI;CACJ,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT,GAEMC,IAA2C;CAC/C,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,MAAM;AACR,GAEMC,IAAyC;CAC7C,SAAS;CACT,OAAO;CACP,SAAS;CACT,WAAW;CACX,QAAQ;CACR,MAAM;CACN,SAAS;CACT,SAAS;CACT,OAAO;CACP,SAAS;AACX,GAEMC,IAAyC;CAC7C,MAAM;CACN,QAAQ;CACR,OAAO;CACP,SAAS;AACX,GAMMC,KAA6B,EACjC,aACA,QAAK,QACL,UAAO,QACP,YAAS,UACT,WAAQ,WACR,UACA,cAAW,IACX,UACA,YAAS,IACT,eAAY,IACZ,eAAY,IACZ,UAAO,IACP,eAAY,IACZ,UACA,YACA,GAAGC,QACC;CACJ,IAAMC,IAAMC,GAENC,IAAUC,EACdT,EAAWU,IACXT,EAAaU,IACbT,EAAYU,IACZC,KAASV,EAAYU,IACrBC,KAAY,YACZC,KAAU,UACVC,KAAa,aACbC,KAAa,4BACbC,KAAQ,aACR,CAACJ,KAAYK,KAASA,IAAQ,KAAK,mBACnCC,CACF,GAEMC,IACJ,CAACP,KAAYK,KAASA,IAAQ,IAC1B;EACE,SAAS;EACT,iBAAiBA;EACjB,iBAAiB;EACjB,UAAU;CACZ,IACA,CAAC;CAEP,OACE,kBAACb,GAAD;EAAK,GAAID;EAAY,WAAWG;EAAS,OAAO;GAAE,GAAGa;GAAY,GAAGC;EAAM;EAAY;EACnF;CACE,CAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Textarea/index.tsx"],"sourcesContent":["import React, { forwardRef, useId } from 'react';\nimport './Textarea.css';\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {\n label?: React.ReactNode;\n description?: React.ReactNode;\n error?: React.ReactNode;\n wrapperClassName?: string;\n};\n\nconst hasContent = (node: React.ReactNode) => node !== undefined && node !== null && typeof node !== 'boolean' && node !== '';\n\nconst Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea({\n label,\n description,\n error,\n wrapperClassName = '',\n className = '',\n id,\n 'aria-describedby': describedBy,\n 'aria-invalid': invalid,\n ...attributes\n}, ref) {\n const generatedId = useId();\n const fieldId = id ?? generatedId;\n const descriptionId = `${generatedId}-description`;\n const errorId = `${generatedId}-error`;\n const showDescription = hasContent(description);\n const showError = hasContent(error);\n const descriptionIds = [describedBy, showDescription ? descriptionId : undefined, showError ? errorId : undefined].filter(Boolean).join(' ') || undefined;\n\n return (\n <div className={`w-full space-y-2 ${wrapperClassName}`.trim()}>\n {hasContent(label) && <label htmlFor={fieldId} className=\"block text-sm font-medium\">{label}</label>}\n <textarea\n {...attributes}\n ref={ref}\n id={fieldId}\n aria-describedby={descriptionIds}\n aria-invalid={showError ? true : invalid}\n className={`textarea dishui-textarea w-full resize-y rounded-md border-strong bg-page p-3 text-sm text-primary placeholder:text-tertiary ${className}`.trim()}\n />\n {showDescription && <div id={descriptionId} className=\"text-xs leading-5 text-secondary\">{description}</div>}\n {showError && <div id={errorId} role=\"alert\" className=\"text-xs leading-5 text-error\">{error}</div>}\n </div>\n );\n});\n\nexport default Textarea;\n"],"mappings":";;;;AAUA,
|
|
1
|
+
{"version":3,"file":"index.js","names":["hasContent","node","Textarea","forwardRef","describedBy","invalid","attributes","generatedId","useId","fieldId","id","descriptionId","errorId","showDescription","description","showError","error","descriptionIds","wrapperClassName","label","className"],"sources":["../../../src/components/Textarea/index.tsx"],"sourcesContent":["import React, { forwardRef, useId } from 'react';\nimport './Textarea.css';\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {\n label?: React.ReactNode;\n description?: React.ReactNode;\n error?: React.ReactNode;\n wrapperClassName?: string;\n};\n\nconst hasContent = (node: React.ReactNode) => node !== undefined && node !== null && typeof node !== 'boolean' && node !== '';\n\nconst Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea({\n label,\n description,\n error,\n wrapperClassName = '',\n className = '',\n id,\n 'aria-describedby': describedBy,\n 'aria-invalid': invalid,\n ...attributes\n}, ref) {\n const generatedId = useId();\n const fieldId = id ?? generatedId;\n const descriptionId = `${generatedId}-description`;\n const errorId = `${generatedId}-error`;\n const showDescription = hasContent(description);\n const showError = hasContent(error);\n const descriptionIds = [describedBy, showDescription ? descriptionId : undefined, showError ? errorId : undefined].filter(Boolean).join(' ') || undefined;\n\n return (\n <div className={`w-full space-y-2 ${wrapperClassName}`.trim()}>\n {hasContent(label) && <label htmlFor={fieldId} className=\"block text-sm font-medium\">{label}</label>}\n <textarea\n {...attributes}\n ref={ref}\n id={fieldId}\n aria-describedby={descriptionIds}\n aria-invalid={showError ? true : invalid}\n className={`textarea dishui-textarea w-full resize-y rounded-md border-strong bg-page p-3 text-sm text-primary placeholder:text-tertiary ${className}`.trim()}\n />\n {showDescription && <div id={descriptionId} className=\"text-xs leading-5 text-secondary\">{description}</div>}\n {showError && <div id={errorId} role=\"alert\" className=\"text-xs leading-5 text-error\">{error}</div>}\n </div>\n );\n});\n\nexport default Textarea;\n"],"mappings":";;;;AAUA,IAAMA,KAAc,MAA0BC,KAA+B,QAAQ,OAAOA,KAAS,aAAaA,MAAS,IAErHC,IAAWC,EAA+C,SAAkB,EAC9E,UACA,gBACA,UACA,sBAAmB,IACnB,eAAY,IACZ,OACA,oBAAoBC,GACpB,gBAAgBC,GAChB,GAAGC,KACJ,GAAK;CACJ,IAAMC,IAAcC,EAAM,GACpBC,IAAUC,KAAMH,GAChBI,IAAgB,GAAGJ,EAAY,eAC/BK,IAAU,GAAGL,EAAY,SACzBM,IAAkBb,EAAWc,CAAW,GACxCC,IAAYf,EAAWgB,CAAK,GAC5BC,IAAiB;EAACb;EAAaS,IAAkBF,IAAgB,KAAA;EAAWI,IAAYH,IAAU,KAAA;CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,KAAK,KAAA;CAEhJ,OACI,kBAAC,OAAD;EAAK,WAAW,oBAAoBM,IAAmB,KAAK;EAA5D,UAAA;GACKlB,EAAWmB,CAAK,KAAK,kBAAC,SAAD;IAAO,SAASV;IAAS,WAAU;IAA6B,UAAAU;GAAa,CAAA;GACnG,kBAAC,YAAD;IACI,GAAIb;IACC;IACL,IAAIG;IACJ,oBAAkBQ;IAClB,gBAAcF,IAAY,KAAOV;IACjC,WAAW,gIAAgIe,IAAY,KAAK;GAC/J,CAAA;GACAP,KAAmB,kBAAC,OAAD;IAAK,IAAIF;IAAe,WAAU;IAAoC,UAAAG;GAAiB,CAAA;GAC1GC,KAAa,kBAAC,OAAD;IAAK,IAAIH;IAAS,MAAK;IAAQ,WAAU;IAAgC,UAAAI;GAAW,CAAA;EACjG;;AAEb,CAAC"}
|