@zerodep-dev/vue-tsx-pro-ui 0.1.0 → 0.3.0
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/base/Badge.js +3 -3
- package/dist/base/Badge.js.map +1 -1
- package/dist/base/Can.d.ts +12 -0
- package/dist/base/Can.js +20 -0
- package/dist/base/Can.js.map +1 -0
- package/dist/base/ClientOnly.d.ts +10 -0
- package/dist/base/ClientOnly.js +18 -0
- package/dist/base/ClientOnly.js.map +1 -0
- package/dist/base/CloseButton.js +3 -3
- package/dist/base/CloseButton.js.map +1 -1
- package/dist/base/CodeBlock.js +5 -5
- package/dist/base/CodeBlock.js.map +1 -1
- package/dist/base/CopyButton.js +3 -3
- package/dist/base/CopyButton.js.map +1 -1
- package/dist/base/Icon.js +3 -3
- package/dist/base/Icon.js.map +1 -1
- package/dist/base/Indicator.js +3 -3
- package/dist/base/Indicator.js.map +1 -1
- package/dist/base/StatusDot.js +3 -3
- package/dist/base/StatusDot.js.map +1 -1
- package/dist/base/Tag.js +5 -5
- package/dist/base/Tag.js.map +1 -1
- package/dist/base/button-core.js +4 -4
- package/dist/base/button-core.js.map +1 -1
- package/dist/charts/AreaChart.js +3 -3
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.js +3 -3
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/ChordChart.js +3 -3
- package/dist/charts/ChordChart.js.map +1 -1
- package/dist/charts/ComboChart.js +3 -3
- package/dist/charts/ComboChart.js.map +1 -1
- package/dist/charts/DonutChart.js +3 -3
- package/dist/charts/DonutChart.js.map +1 -1
- package/dist/charts/FunnelChart.js +5 -5
- package/dist/charts/FunnelChart.js.map +1 -1
- package/dist/charts/GraphChart.js +3 -3
- package/dist/charts/GraphChart.js.map +1 -1
- package/dist/charts/LineChart.js +3 -3
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/MapChart.js +7 -7
- package/dist/charts/MapChart.js.map +1 -1
- package/dist/charts/RadarChart.js +16 -15
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/SankeyChart.js +3 -3
- package/dist/charts/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart.js +3 -3
- package/dist/charts/ScatterChart.js.map +1 -1
- package/dist/charts/TimelineChart.js +6 -5
- package/dist/charts/TimelineChart.js.map +1 -1
- package/dist/charts/TreemapChart.js +3 -3
- package/dist/charts/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart.js +3 -3
- package/dist/charts/WaterfallChart.js.map +1 -1
- package/dist/charts/XYChart.js +9 -7
- package/dist/charts/XYChart.js.map +1 -1
- package/dist/charts/frame.js +10 -8
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/single.js +4 -3
- package/dist/charts/single.js.map +1 -1
- package/dist/code-editor/CodeEditor.d.ts +18 -0
- package/dist/code-editor/CodeEditor.js +57 -0
- package/dist/code-editor/CodeEditor.js.map +1 -0
- package/dist/code-editor/editor.d.ts +52 -0
- package/dist/code-editor/editor.js +225 -0
- package/dist/code-editor/editor.js.map +1 -0
- package/dist/code-editor/index.d.ts +9 -0
- package/dist/code-editor/index.js +3 -0
- package/dist/config/Provider.d.ts +3 -1
- package/dist/config/Provider.js +9 -4
- package/dist/config/Provider.js.map +1 -1
- package/dist/config/context.d.ts +18 -0
- package/dist/config/context.js +16 -1
- package/dist/config/context.js.map +1 -1
- package/dist/config/createUi.d.ts +20 -3
- package/dist/config/createUi.js +80 -49
- package/dist/config/createUi.js.map +1 -1
- package/dist/config/lang/en-US.js +21 -3
- package/dist/config/lang/en-US.js.map +1 -1
- package/dist/config/lang/format.d.ts +2 -1
- package/dist/config/lang/format.js +9 -2
- package/dist/config/lang/format.js.map +1 -1
- package/dist/config/lang/lang.d.ts +19 -6
- package/dist/config/lang/lang.js +11 -2
- package/dist/config/lang/lang.js.map +1 -1
- package/dist/config/lang/zh-CN.js +21 -3
- package/dist/config/lang/zh-CN.js.map +1 -1
- package/dist/config/layout/preference.d.ts +43 -0
- package/dist/config/layout/preference.js +108 -0
- package/dist/config/layout/preference.js.map +1 -0
- package/dist/date/Calendar.js +3 -3
- package/dist/date/Calendar.js.map +1 -1
- package/dist/date/CalendarBoard.js +9 -9
- package/dist/date/CalendarBoard.js.map +1 -1
- package/dist/date/CalendarView.js +7 -7
- package/dist/date/CalendarView.js.map +1 -1
- package/dist/date/DateField.js +3 -3
- package/dist/date/DateField.js.map +1 -1
- package/dist/date/DatePicker.js +5 -5
- package/dist/date/DatePicker.js.map +1 -1
- package/dist/date/DateRangePicker.js +5 -5
- package/dist/date/DateRangePicker.js.map +1 -1
- package/dist/date/DateSegmentGroup.js +5 -5
- package/dist/date/DateSegmentGroup.js.map +1 -1
- package/dist/date/QuarterCalendar.js +6 -6
- package/dist/date/QuarterCalendar.js.map +1 -1
- package/dist/date/RangeCalendar.js +3 -3
- package/dist/date/RangeCalendar.js.map +1 -1
- package/dist/date/SegmentedField.js +3 -3
- package/dist/date/SegmentedField.js.map +1 -1
- package/dist/date/TimeField.js +3 -3
- package/dist/date/TimeField.js.map +1 -1
- package/dist/date/TimePicker.js +4 -4
- package/dist/date/TimePicker.js.map +1 -1
- package/dist/date/date-segments.js +1 -1
- package/dist/date/date-segments.js.map +1 -1
- package/dist/date/picker-popover.js +3 -2
- package/dist/date/picker-popover.js.map +1 -1
- package/dist/diagram/Diagram.js +12 -12
- package/dist/diagram/Diagram.js.map +1 -1
- package/dist/diagram/DiagramLanes.js +3 -3
- package/dist/diagram/DiagramLanes.js.map +1 -1
- package/dist/diagram/DiagramMinimap.js +4 -4
- package/dist/diagram/DiagramMinimap.js.map +1 -1
- package/dist/diagram/index.d.ts +2 -1
- package/dist/diagram/index.js +2 -1
- package/dist/diagram/layout.d.ts +57 -0
- package/dist/diagram/layout.js +50 -0
- package/dist/diagram/layout.js.map +1 -0
- package/dist/display/Accordion.js +6 -6
- package/dist/display/Accordion.js.map +1 -1
- package/dist/display/AnimatedNumber.js +4 -4
- package/dist/display/AnimatedNumber.js.map +1 -1
- package/dist/display/Avatar.js +4 -4
- package/dist/display/Avatar.js.map +1 -1
- package/dist/display/Checklist.js +7 -7
- package/dist/display/Checklist.js.map +1 -1
- package/dist/display/Collapse.js +8 -5
- package/dist/display/Collapse.js.map +1 -1
- package/dist/display/Collapsible.js +3 -3
- package/dist/display/Collapsible.js.map +1 -1
- package/dist/display/Descriptions.js +5 -5
- package/dist/display/Descriptions.js.map +1 -1
- package/dist/display/Ellipsis.js +3 -3
- package/dist/display/Ellipsis.js.map +1 -1
- package/dist/display/FieldCompare.js +4 -4
- package/dist/display/FieldCompare.js.map +1 -1
- package/dist/display/Gauge.js +11 -11
- package/dist/display/Gauge.js.map +1 -1
- package/dist/display/Image.js +4 -4
- package/dist/display/Image.js.map +1 -1
- package/dist/display/Marquee.js +3 -3
- package/dist/display/Marquee.js.map +1 -1
- package/dist/display/ProportionBar.js +4 -4
- package/dist/display/ProportionBar.js.map +1 -1
- package/dist/display/Sortable.js +4 -4
- package/dist/display/Sortable.js.map +1 -1
- package/dist/display/Sparkline.js +6 -6
- package/dist/display/Sparkline.js.map +1 -1
- package/dist/display/Stat.js +3 -3
- package/dist/display/Stat.js.map +1 -1
- package/dist/display/Timeline.js +7 -7
- package/dist/display/Timeline.js.map +1 -1
- package/dist/display/Tree.js +10 -10
- package/dist/display/Tree.js.map +1 -1
- package/dist/display/VirtualList.js +7 -7
- package/dist/display/VirtualList.js.map +1 -1
- package/dist/display/Watermark.js +3 -3
- package/dist/display/Watermark.js.map +1 -1
- package/dist/docs-kit/CodeGroup.js +5 -5
- package/dist/docs-kit/CodeGroup.js.map +1 -1
- package/dist/docs-kit/CodePreview.js +6 -6
- package/dist/docs-kit/CodePreview.js.map +1 -1
- package/dist/docs-kit/PropsTable.js +4 -4
- package/dist/docs-kit/PropsTable.js.map +1 -1
- package/dist/feedback/Alert.js +5 -5
- package/dist/feedback/Alert.js.map +1 -1
- package/dist/feedback/Banner.js +5 -5
- package/dist/feedback/Banner.js.map +1 -1
- package/dist/feedback/Empty.js +4 -4
- package/dist/feedback/Empty.js.map +1 -1
- package/dist/feedback/LoadingBar.js +20 -13
- package/dist/feedback/LoadingBar.js.map +1 -1
- package/dist/feedback/LoadingOverlay.js +3 -3
- package/dist/feedback/LoadingOverlay.js.map +1 -1
- package/dist/feedback/Progress.js +14 -14
- package/dist/feedback/Progress.js.map +1 -1
- package/dist/feedback/Result.js +4 -4
- package/dist/feedback/Result.js.map +1 -1
- package/dist/feedback/SkeletonText.js +3 -3
- package/dist/feedback/SkeletonText.js.map +1 -1
- package/dist/feedback/Toast.js +6 -6
- package/dist/feedback/Toast.js.map +1 -1
- package/dist/form/Field.d.ts +7 -0
- package/dist/form/Field.js +20 -9
- package/dist/form/Field.js.map +1 -1
- package/dist/form/Form.js +3 -3
- package/dist/form/Form.js.map +1 -1
- package/dist/form/FormErrorSummary.js +3 -3
- package/dist/form/FormErrorSummary.js.map +1 -1
- package/dist/form/FormSection.js +6 -6
- package/dist/form/FormSection.js.map +1 -1
- package/dist/form/useForm.d.ts +4 -1
- package/dist/form/useForm.js +35 -13
- package/dist/form/useForm.js.map +1 -1
- package/dist/index.d.ts +18 -10
- package/dist/index.js +17 -9
- package/dist/input/Autocomplete.js +3 -3
- package/dist/input/Autocomplete.js.map +1 -1
- package/dist/input/Cascader.js +7 -7
- package/dist/input/Cascader.js.map +1 -1
- package/dist/input/CharacterCount.js +3 -3
- package/dist/input/CharacterCount.js.map +1 -1
- package/dist/input/Checkbox.js +5 -5
- package/dist/input/Checkbox.js.map +1 -1
- package/dist/input/ColorField.js +4 -4
- package/dist/input/ColorField.js.map +1 -1
- package/dist/input/Combobox.js +5 -5
- package/dist/input/Combobox.js.map +1 -1
- package/dist/input/ConditionBuilder.js +15 -14
- package/dist/input/ConditionBuilder.js.map +1 -1
- package/dist/input/FileDrop.js +3 -3
- package/dist/input/FileDrop.js.map +1 -1
- package/dist/input/Listbox.js +9 -9
- package/dist/input/Listbox.js.map +1 -1
- package/dist/input/Mentions.js +4 -4
- package/dist/input/Mentions.js.map +1 -1
- package/dist/input/NumberField.js +3 -3
- package/dist/input/NumberField.js.map +1 -1
- package/dist/input/NumberRangeField.js +5 -5
- package/dist/input/NumberRangeField.js.map +1 -1
- package/dist/input/OtpField.js +5 -5
- package/dist/input/OtpField.js.map +1 -1
- package/dist/input/PeoplePicker.js +6 -6
- package/dist/input/PeoplePicker.js.map +1 -1
- package/dist/input/PeoplePickerPanel.js +15 -15
- package/dist/input/PeoplePickerPanel.js.map +1 -1
- package/dist/input/Radio.js +4 -4
- package/dist/input/Radio.js.map +1 -1
- package/dist/input/Rating.js +5 -5
- package/dist/input/Rating.js.map +1 -1
- package/dist/input/Select.js +5 -5
- package/dist/input/Select.js.map +1 -1
- package/dist/input/SelectedTags.js +4 -4
- package/dist/input/SelectedTags.js.map +1 -1
- package/dist/input/Slider.js +6 -6
- package/dist/input/Slider.js.map +1 -1
- package/dist/input/Switch.js +3 -3
- package/dist/input/Switch.js.map +1 -1
- package/dist/input/TagsInput.js +5 -5
- package/dist/input/TagsInput.js.map +1 -1
- package/dist/input/TextField.js +5 -5
- package/dist/input/TextField.js.map +1 -1
- package/dist/input/Textarea.js +4 -4
- package/dist/input/Textarea.js.map +1 -1
- package/dist/input/ToggleGroup.js +4 -4
- package/dist/input/ToggleGroup.js.map +1 -1
- package/dist/input/Transfer.js +8 -8
- package/dist/input/Transfer.js.map +1 -1
- package/dist/input/TreeSelect.js +7 -7
- package/dist/input/TreeSelect.js.map +1 -1
- package/dist/input/Upload.js +10 -9
- package/dist/input/Upload.js.map +1 -1
- package/dist/input/condition.d.ts +1 -1
- package/dist/input/condition.js +32 -14
- package/dist/input/condition.js.map +1 -1
- package/dist/input/people.d.ts +15 -14
- package/dist/input/people.js +5 -5
- package/dist/input/people.js.map +1 -1
- package/dist/input/remote-items.d.ts +4 -2
- package/dist/input/remote-items.js +7 -2
- package/dist/input/remote-items.js.map +1 -1
- package/dist/layout/Affix.js +4 -4
- package/dist/layout/Affix.js.map +1 -1
- package/dist/layout/ResizeHandle.d.ts +6 -2
- package/dist/layout/ResizeHandle.js +32 -9
- package/dist/layout/ResizeHandle.js.map +1 -1
- package/dist/layout/ScrollArea.js +3 -3
- package/dist/layout/ScrollArea.js.map +1 -1
- package/dist/layout/Separator.js +3 -3
- package/dist/layout/Separator.js.map +1 -1
- package/dist/layout/Splitter.js +3 -3
- package/dist/layout/Splitter.js.map +1 -1
- package/dist/layout/ViewportFill.d.ts +2 -2
- package/dist/layout/ViewportFill.js +4 -4
- package/dist/layout/ViewportFill.js.map +1 -1
- package/dist/navigation/Breadcrumbs.js +4 -4
- package/dist/navigation/Breadcrumbs.js.map +1 -1
- package/dist/navigation/NavBar.js +6 -6
- package/dist/navigation/NavBar.js.map +1 -1
- package/dist/navigation/NavList.d.ts +1 -0
- package/dist/navigation/NavList.js +20 -12
- package/dist/navigation/NavList.js.map +1 -1
- package/dist/navigation/NavMenu.d.ts +27 -0
- package/dist/navigation/NavMenu.js +54 -0
- package/dist/navigation/NavMenu.js.map +1 -0
- package/dist/navigation/PageJump.js +3 -3
- package/dist/navigation/PageJump.js.map +1 -1
- package/dist/navigation/PageSizeSelect.js +4 -4
- package/dist/navigation/PageSizeSelect.js.map +1 -1
- package/dist/navigation/Pagination.js +6 -6
- package/dist/navigation/Pagination.js.map +1 -1
- package/dist/navigation/PaginationBar.js +5 -5
- package/dist/navigation/PaginationBar.js.map +1 -1
- package/dist/navigation/Steps.js +4 -4
- package/dist/navigation/Steps.js.map +1 -1
- package/dist/navigation/TableOfContents.js +5 -5
- package/dist/navigation/TableOfContents.js.map +1 -1
- package/dist/navigation/Tabs.js +7 -7
- package/dist/navigation/Tabs.js.map +1 -1
- package/dist/navigation/Toolbar.js +3 -3
- package/dist/navigation/Toolbar.js.map +1 -1
- package/dist/overlay/AlertDialog.js +4 -4
- package/dist/overlay/AlertDialog.js.map +1 -1
- package/dist/overlay/CommandPalette.js +4 -4
- package/dist/overlay/CommandPalette.js.map +1 -1
- package/dist/overlay/ContextMenu.js +3 -3
- package/dist/overlay/ContextMenu.js.map +1 -1
- package/dist/overlay/Dialog.js +4 -4
- package/dist/overlay/Dialog.js.map +1 -1
- package/dist/overlay/Drawer.js +5 -5
- package/dist/overlay/Drawer.js.map +1 -1
- package/dist/overlay/HoverCard.js +5 -3
- package/dist/overlay/HoverCard.js.map +1 -1
- package/dist/overlay/Lightbox.js +5 -5
- package/dist/overlay/Lightbox.js.map +1 -1
- package/dist/overlay/Menu.js +7 -7
- package/dist/overlay/Menu.js.map +1 -1
- package/dist/overlay/ModalCore.js +9 -9
- package/dist/overlay/ModalCore.js.map +1 -1
- package/dist/overlay/Popconfirm.js +6 -6
- package/dist/overlay/Popconfirm.js.map +1 -1
- package/dist/overlay/Popover.js +5 -3
- package/dist/overlay/Popover.js.map +1 -1
- package/dist/overlay/Tooltip.js +5 -3
- package/dist/overlay/Tooltip.js.map +1 -1
- package/dist/overlay/Tour.js +8 -8
- package/dist/overlay/Tour.js.map +1 -1
- package/dist/overlay/detached.d.ts +2 -0
- package/dist/overlay/detached.js +73 -42
- package/dist/overlay/detached.js.map +1 -1
- package/dist/patterns/ActionBar.js +3 -3
- package/dist/patterns/ActionBar.js.map +1 -1
- package/dist/patterns/AppShell.d.ts +28 -1
- package/dist/patterns/AppShell.js +158 -52
- package/dist/patterns/AppShell.js.map +1 -1
- package/dist/patterns/AuthLayout.d.ts +28 -0
- package/dist/patterns/AuthLayout.js +77 -0
- package/dist/patterns/AuthLayout.js.map +1 -0
- package/dist/patterns/CommentThread.js +9 -9
- package/dist/patterns/CommentThread.js.map +1 -1
- package/dist/patterns/DataImport.js +4 -4
- package/dist/patterns/DataImport.js.map +1 -1
- package/dist/patterns/DeadlineBadge.js +3 -3
- package/dist/patterns/DeadlineBadge.js.map +1 -1
- package/dist/patterns/FilterBar.d.ts +11 -1
- package/dist/patterns/FilterBar.js +39 -10
- package/dist/patterns/FilterBar.js.map +1 -1
- package/dist/patterns/FormDialog.d.ts +18 -0
- package/dist/patterns/FormDialog.js +46 -0
- package/dist/patterns/FormDialog.js.map +1 -0
- package/dist/patterns/KanbanBoard.js +8 -8
- package/dist/patterns/KanbanBoard.js.map +1 -1
- package/dist/patterns/LayoutSwitcher.d.ts +12 -0
- package/dist/patterns/LayoutSwitcher.js +79 -0
- package/dist/patterns/LayoutSwitcher.js.map +1 -0
- package/dist/patterns/NotificationCenter.js +8 -8
- package/dist/patterns/NotificationCenter.js.map +1 -1
- package/dist/patterns/PageTabs.d.ts +12 -7
- package/dist/patterns/PageTabs.js +41 -29
- package/dist/patterns/PageTabs.js.map +1 -1
- package/dist/patterns/QueryTable.d.ts +10 -1
- package/dist/patterns/QueryTable.js +128 -68
- package/dist/patterns/QueryTable.js.map +1 -1
- package/dist/patterns/SlideCaptcha.d.ts +80 -0
- package/dist/patterns/SlideCaptcha.js +354 -0
- package/dist/patterns/SlideCaptcha.js.map +1 -0
- package/dist/patterns/StepsForm.js +7 -7
- package/dist/patterns/StepsForm.js.map +1 -1
- package/dist/patterns/ThemeSwitcher.js +3 -3
- package/dist/patterns/ThemeSwitcher.js.map +1 -1
- package/dist/patterns/index.d.ts +7 -3
- package/dist/patterns/index.js +5 -1
- package/dist/patterns/messages.d.ts +39 -1
- package/dist/patterns/messages.js +40 -2
- package/dist/patterns/messages.js.map +1 -1
- package/dist/table/ColumnHeaderActions.js +3 -3
- package/dist/table/ColumnHeaderActions.js.map +1 -1
- package/dist/table/ColumnResizer.js +3 -3
- package/dist/table/ColumnResizer.js.map +1 -1
- package/dist/table/ColumnSettings.js +5 -5
- package/dist/table/ColumnSettings.js.map +1 -1
- package/dist/table/ColumnTable.js +8 -8
- package/dist/table/ColumnTable.js.map +1 -1
- package/dist/table/DataTable.js +8 -8
- package/dist/table/DataTable.js.map +1 -1
- package/dist/table/DataTableView.js +21 -21
- package/dist/table/DataTableView.js.map +1 -1
- package/dist/table/PivotTable.js +3 -3
- package/dist/table/PivotTable.js.map +1 -1
- package/dist/table/SelectionBar.js +4 -4
- package/dist/table/SelectionBar.js.map +1 -1
- package/dist/table/TreeDataTable.js +5 -5
- package/dist/table/TreeDataTable.js.map +1 -1
- package/dist/theme-customize/ThemeCustomizer.js +7 -6
- package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
- package/dist/theme-customize/ThemeThumbnail.js +3 -3
- package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
- package/dist/three/background/AuroraBackground.js +3 -3
- package/dist/three/background/AuroraBackground.js.map +1 -1
- package/dist/three/background/MeshGradient.js +3 -3
- package/dist/three/background/MeshGradient.js.map +1 -1
- package/dist/three/background/ShaderBackground.js +3 -3
- package/dist/three/background/ShaderBackground.js.map +1 -1
- package/dist/three/core/EffectSurface.js +3 -3
- package/dist/three/core/EffectSurface.js.map +1 -1
- package/dist/three/core/ThreeCanvas.js +4 -4
- package/dist/three/core/ThreeCanvas.js.map +1 -1
- package/dist/three/effects/Confetti.js +3 -3
- package/dist/three/effects/Confetti.js.map +1 -1
- package/dist/three/effects/ParticleField.js +3 -3
- package/dist/three/effects/ParticleField.js.map +1 -1
- package/dist/three/effects/WaveGrid.js +3 -3
- package/dist/three/effects/WaveGrid.js.map +1 -1
- package/dist/three/globe/Globe.js +3 -3
- package/dist/three/globe/Globe.js.map +1 -1
- package/dist/three/model/ModelViewer.js +3 -3
- package/dist/three/model/ModelViewer.js.map +1 -1
- package/dist/utils/data/clone.d.ts +8 -0
- package/dist/utils/data/clone.js +21 -0
- package/dist/utils/data/clone.js.map +1 -0
- package/dist/utils/data/date.d.ts +10 -0
- package/dist/utils/data/date.js +13 -1
- package/dist/utils/data/date.js.map +1 -1
- package/dist/utils/data/number.d.ts +5 -0
- package/dist/utils/data/number.js +8 -1
- package/dist/utils/data/number.js.map +1 -1
- package/dist/utils/data/numeric.d.ts +7 -0
- package/dist/utils/data/numeric.js +46 -1
- package/dist/utils/data/numeric.js.map +1 -1
- package/dist/utils/dom/download.d.ts +8 -1
- package/dist/utils/dom/download.js +19 -2
- package/dist/utils/dom/download.js.map +1 -1
- package/dist/utils/dom/element.d.ts +3 -1
- package/dist/utils/dom/element.js +8 -4
- package/dist/utils/dom/element.js.map +1 -1
- package/dist/utils/dom/fullscreen.d.ts +1 -1
- package/dist/utils/dom/fullscreen.js +12 -8
- package/dist/utils/dom/fullscreen.js.map +1 -1
- package/dist/utils/dom/mounted.d.ts +7 -0
- package/dist/utils/dom/mounted.js +16 -0
- package/dist/utils/dom/mounted.js.map +1 -0
- package/dist/utils/dom/overflow.js +2 -1
- package/dist/utils/dom/overflow.js.map +1 -1
- package/dist/utils/dom/pan-zoom.js +2 -1
- package/dist/utils/dom/pan-zoom.js.map +1 -1
- package/dist/utils/props.js +3 -13
- package/dist/utils/props.js.map +1 -1
- package/dist/utils/request/error-message.d.ts +17 -0
- package/dist/utils/request/error-message.js +50 -0
- package/dist/utils/request/error-message.js.map +1 -0
- package/dist/utils/request/http.d.ts +80 -4
- package/dist/utils/request/http.js +121 -24
- package/dist/utils/request/http.js.map +1 -1
- package/dist/utils/request/use-autosave.d.ts +35 -0
- package/dist/utils/request/use-autosave.js +69 -0
- package/dist/utils/request/use-autosave.js.map +1 -0
- package/dist/utils/request/use-request.js +4 -2
- package/dist/utils/request/use-request.js.map +1 -1
- package/package.json +57 -4
|
@@ -6,8 +6,8 @@ import { IconButton } from "../base/IconButton.js";
|
|
|
6
6
|
import { Link } from "../base/Link.js";
|
|
7
7
|
import { FlexOrderedList } from "../layout/Flex.js";
|
|
8
8
|
import { Menu as Menu$1, MenuItem, MenuLinkItem } from "../overlay/Menu.js";
|
|
9
|
-
import { createVNode, isVNode
|
|
10
|
-
import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
9
|
+
import { createVNode, isVNode } from "vue";
|
|
10
|
+
import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
11
11
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
12
12
|
import { ChevronRight, Ellipsis } from "@lucide/icons";
|
|
13
13
|
//#region src/navigation/Breadcrumbs.tsx
|
|
@@ -92,7 +92,7 @@ var Breadcrumbs = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
92
92
|
gap: "xs",
|
|
93
93
|
sx: breadcrumbsStyles.list
|
|
94
94
|
}, propsList.value), _isSlot(_slot = shown.map((entry, position) => {
|
|
95
|
-
if (entry === "collapsed") return createVNode("li",
|
|
95
|
+
if (entry === "collapsed") return createVNode("li", mergeJsxProps({ "key": "collapsed" }, mergeAttrs({ sx: breadcrumbsStyles.item }, propsCollapsedItem.value)), [createVNode(Menu$1, mergePartProps({
|
|
96
96
|
lazy: false,
|
|
97
97
|
trigger: (props) => createVNode(IconButton, mergePartProps({
|
|
98
98
|
sx: breadcrumbsStyles.expand,
|
|
@@ -116,7 +116,7 @@ var Breadcrumbs = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
116
116
|
const index = items.value.indexOf(entry);
|
|
117
117
|
const own = typeof propsItem.value === "function" ? propsItem.value(entry, index) : propsItem.value;
|
|
118
118
|
const label = createVNode("span", mergeAttrs({ sx: breadcrumbsStyles.label }, propsLabel.value), [entry.icon && createVNode(Icon, { "icon": entry.icon }, null), entry.label]);
|
|
119
|
-
return createVNode("li",
|
|
119
|
+
return createVNode("li", mergeJsxProps({ "key": entry.key ?? entry.href ?? index }, mergeAttrs({ sx: breadcrumbsStyles.item }, own)), [index === last ? createVNode("span", mergeAttrs({ sx: breadcrumbsStyles.current }, propsCurrent.value, { "aria-current": onNavigate.value ? "location" : "page" }), [label]) : entry.href != null ? createVNode(Link, mergePartProps({
|
|
120
120
|
tone: "muted",
|
|
121
121
|
underline: "hover",
|
|
122
122
|
href: entry.href
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumbs.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps","Menu"],"sources":["../../src/navigation/Breadcrumbs.tsx"],"sourcesContent":["/**\n * 面包屑(nav > ol):当前页在站点层级里的位置。最后一项是当前页(aria-current=\"page\",不是链接)。\n * 链接用 Link(站内链接经路由适配跳转),分隔符默认是 Lucide 的 ChevronRight,从右到左排版时翻转。\n *\n * <Breadcrumbs items={[{ label: '首页', href: '/' }, { label: '订单', href: '/orders' }, { label: '#1024' }]} />\n *\n * 路径太长时用 maxItems 折叠中间部分:折叠处是一个菜单按钮,被折叠的各级在菜单里(链接菜单项),\n * 同 Radix Themes / shadcn 的做法;展开整条路径会把布局撑乱,菜单不会。\n *\n * 应用内的层级(文件夹、组织架构的下钻)没有地址:给 onNavigate 时没有 href 的各级是链接样式的按钮,\n * 点了交给它;当前一级标 aria-current=\"location\"(是“在哪一级”,不是“哪一页”)。\n *\n * <Breadcrumbs items={path.map((dept) => ({ key: dept.id, label: dept.name }))} onNavigate={(_, index) => (path = path.slice(0, index + 1))} />\n */\nimport { ChevronRight, Ellipsis } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { Button } from '../base/Button';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { Icon, type IconData } from '../base/Icon';\nimport { Link, type LinkProps } from '../base/Link';\nimport { useLang } from '../config/context';\nimport { Menu, MenuItem, MenuLinkItem, type MenuProps } from '../overlay/Menu';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { FlexOrderedList, type FlexProps } from '../layout/Flex';\n\n/** 一级路径 */\nexport interface BreadcrumbItem {\n /** 唯一的 key;不写时用 href,再没有时用位置 */\n key?: string;\n /** 显示的文字 */\n label: VNodeChild;\n /** 地址;最后一项(当前页)不需要 */\n href?: string;\n /** 文字前的图标 */\n icon?: IconData;\n}\n\n/** 未声明的属性落到 nav 上;aria-label 默认取语言包(面包屑) */\nexport interface BreadcrumbsProps extends PartProps<'nav'> {\n /** 路径,从根到当前页;最后一项是当前页 */\n items: readonly BreadcrumbItem[];\n /** 分隔符,默认是右向的 chevron 图标 */\n separator?: VNodeChild;\n /** 超过这么多项时折叠中间部分(保留第一项与最后两项),被折叠的各级放进菜单 */\n maxItems?: number;\n /** 列表(ol)的部件属性 */\n propsList?: Partial<FlexProps<'ol'>>;\n /** 每一项(li)的部件属性,可以按项计算 */\n propsItem?: PartProps<'li'> | ((item: BreadcrumbItem, index: number) => PartProps<'li'>);\n /** 折叠处那一项(li,里面是折叠按钮与菜单)的部件属性 */\n propsCollapsedItem?: PartProps<'li'>;\n /** 链接的部件属性 */\n propsLink?: Partial<LinkProps>;\n /** 每一项文字(图标加文字)的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 当前页(最后一项)的部件属性 */\n propsCurrent?: PartProps<'span'>;\n /** 分隔符的部件属性 */\n propsSeparator?: PartProps<'span'>;\n /** 折叠按钮(菜单的触发器)的部件属性 */\n propsExpand?: Partial<IconButtonProps>;\n /** 被折叠各级的菜单的部件属性 */\n propsMenu?: Partial<MenuProps>;\n /** 应用内的层级导航:给了时没有 href 的各级是按钮,点了调用它(index 是在 items 里的位置) */\n onNavigate?: (item: BreadcrumbItem, index: number) => void;\n}\n\n/** Breadcrumbs 的样式:list、item、current、separator、label、expand */\nexport const breadcrumbsStyles = css.create({\n // 横排、换行、间距由 FlexOrderedList 给\n list: { fontSize: '_sm' },\n item: { display: 'inline-flex', alignItems: 'center', gap: '_xs', minWidth: 0 },\n current: { color: '_text', fontWeight: '_medium' },\n separator: { display: 'inline-flex', color: '_textMuted' },\n label: { display: 'inline-flex', alignItems: 'center', gap: '_xs' },\n expand: { width: '1.75em', minHeight: '1.75em' },\n});\n\n/** 面包屑:链接 + 分隔符,最后一项是当前页 */\nexport const Breadcrumbs = _component(\n ({\n items,\n separator,\n maxItems,\n propsList,\n propsItem,\n propsCollapsedItem,\n propsLink,\n propsLabel,\n propsCurrent,\n propsSeparator,\n propsExpand,\n propsMenu,\n onNavigate,\n ...rest\n }: BreadcrumbsProps) => {\n const lang = useLang();\n\n return () => {\n const collapse = maxItems != null && items.length > maxItems;\n // 折叠时保留第一项与最后两项,中间换成展开按钮\n const shown: (BreadcrumbItem | 'collapsed')[] = collapse\n ? [items[0]!, 'collapsed', ...items.slice(-2)]\n : [...items];\n const last = items.length - 1;\n // 每处各生成一个节点:同一个 VNode 不能放在多个位置\n const sep = () => (\n <span\n {...mergeAttrs<'span'>({ sx: breadcrumbsStyles.separator }, propsSeparator, {\n 'aria-hidden': true,\n })}\n >\n {separator ?? <Icon icon={ChevronRight} flipInRtl />}\n </span>\n );\n\n return (\n <nav {...mergeAttrs<'nav'>({ 'aria-label': lang.breadcrumbs }, rest)}>\n <FlexOrderedList\n {...mergePartProps<FlexProps<'ol'>>(\n { wrap: true, align: 'center', gap: 'xs', sx: breadcrumbsStyles.list },\n propsList,\n )}\n >\n {shown.map((entry, position) => {\n if (entry === 'collapsed') {\n return (\n <li\n key=\"collapsed\"\n {...mergeAttrs<'li'>({ sx: breadcrumbsStyles.item }, propsCollapsedItem)}\n >\n <Menu\n {...mergePartProps<MenuProps>(\n {\n // 被折叠的各级链接一直在 DOM 里:页内搜索、爬虫找得到;一页只有一个,不必延迟\n lazy: false,\n trigger: (props) => (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n sx: breadcrumbsStyles.expand,\n size: 'sm',\n icon: Ellipsis,\n 'aria-label': lang.breadcrumbsExpand,\n },\n propsExpand,\n props,\n )}\n />\n ),\n },\n propsMenu,\n )}\n >\n {items.slice(1, -2).map((hidden, offset) =>\n hidden.href != null ? (\n <MenuLinkItem key={offset} href={hidden.href} icon={hidden.icon}>\n {hidden.label}\n </MenuLinkItem>\n ) : (\n <MenuItem\n key={offset}\n icon={hidden.icon}\n disabled={!onNavigate}\n onAction={() => onNavigate?.(hidden, offset + 1)}\n >\n {hidden.label}\n </MenuItem>\n ),\n )}\n </Menu>\n {sep()}\n </li>\n );\n }\n const index = items.indexOf(entry);\n const own = typeof propsItem === 'function' ? propsItem(entry, index) : propsItem;\n const label = (\n <span {...mergeAttrs<'span'>({ sx: breadcrumbsStyles.label }, propsLabel)}>\n {entry.icon && <Icon icon={entry.icon} />}\n {entry.label}\n </span>\n );\n return (\n <li\n key={entry.key ?? entry.href ?? index}\n {...mergeAttrs<'li'>({ sx: breadcrumbsStyles.item }, own)}\n >\n {index === last ? (\n <span\n {...mergeAttrs<'span'>({ sx: breadcrumbsStyles.current }, propsCurrent, {\n 'aria-current': onNavigate ? 'location' : 'page',\n })}\n >\n {label}\n </span>\n ) : entry.href != null ? (\n <Link\n {...mergePartProps<LinkProps>(\n { tone: 'muted', underline: 'hover', href: entry.href },\n propsLink,\n )}\n >\n {label}\n </Link>\n ) : onNavigate ? (\n <Button variant=\"link\" onClick={() => onNavigate(entry, index)}>\n {label}\n </Button>\n ) : (\n label\n )}\n {position < shown.length - 1 && sep()}\n </li>\n );\n })}\n </FlexOrderedList>\n </nav>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Breadcrumbs.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps","Menu"],"sources":["../../src/navigation/Breadcrumbs.tsx"],"sourcesContent":["/**\n * 面包屑(nav > ol):当前页在站点层级里的位置。最后一项是当前页(aria-current=\"page\",不是链接)。\n * 链接用 Link(站内链接经路由适配跳转),分隔符默认是 Lucide 的 ChevronRight,从右到左排版时翻转。\n *\n * <Breadcrumbs items={[{ label: '首页', href: '/' }, { label: '订单', href: '/orders' }, { label: '#1024' }]} />\n *\n * 路径太长时用 maxItems 折叠中间部分:折叠处是一个菜单按钮,被折叠的各级在菜单里(链接菜单项),\n * 同 Radix Themes / shadcn 的做法;展开整条路径会把布局撑乱,菜单不会。\n *\n * 应用内的层级(文件夹、组织架构的下钻)没有地址:给 onNavigate 时没有 href 的各级是链接样式的按钮,\n * 点了交给它;当前一级标 aria-current=\"location\"(是“在哪一级”,不是“哪一页”)。\n *\n * <Breadcrumbs items={path.map((dept) => ({ key: dept.id, label: dept.name }))} onNavigate={(_, index) => (path = path.slice(0, index + 1))} />\n */\nimport { ChevronRight, Ellipsis } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { Button } from '../base/Button';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { Icon, type IconData } from '../base/Icon';\nimport { Link, type LinkProps } from '../base/Link';\nimport { useLang } from '../config/context';\nimport { Menu, MenuItem, MenuLinkItem, type MenuProps } from '../overlay/Menu';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { FlexOrderedList, type FlexProps } from '../layout/Flex';\n\n/** 一级路径 */\nexport interface BreadcrumbItem {\n /** 唯一的 key;不写时用 href,再没有时用位置 */\n key?: string;\n /** 显示的文字 */\n label: VNodeChild;\n /** 地址;最后一项(当前页)不需要 */\n href?: string;\n /** 文字前的图标 */\n icon?: IconData;\n}\n\n/** 未声明的属性落到 nav 上;aria-label 默认取语言包(面包屑) */\nexport interface BreadcrumbsProps extends PartProps<'nav'> {\n /** 路径,从根到当前页;最后一项是当前页 */\n items: readonly BreadcrumbItem[];\n /** 分隔符,默认是右向的 chevron 图标 */\n separator?: VNodeChild;\n /** 超过这么多项时折叠中间部分(保留第一项与最后两项),被折叠的各级放进菜单 */\n maxItems?: number;\n /** 列表(ol)的部件属性 */\n propsList?: Partial<FlexProps<'ol'>>;\n /** 每一项(li)的部件属性,可以按项计算 */\n propsItem?: PartProps<'li'> | ((item: BreadcrumbItem, index: number) => PartProps<'li'>);\n /** 折叠处那一项(li,里面是折叠按钮与菜单)的部件属性 */\n propsCollapsedItem?: PartProps<'li'>;\n /** 链接的部件属性 */\n propsLink?: Partial<LinkProps>;\n /** 每一项文字(图标加文字)的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 当前页(最后一项)的部件属性 */\n propsCurrent?: PartProps<'span'>;\n /** 分隔符的部件属性 */\n propsSeparator?: PartProps<'span'>;\n /** 折叠按钮(菜单的触发器)的部件属性 */\n propsExpand?: Partial<IconButtonProps>;\n /** 被折叠各级的菜单的部件属性 */\n propsMenu?: Partial<MenuProps>;\n /** 应用内的层级导航:给了时没有 href 的各级是按钮,点了调用它(index 是在 items 里的位置) */\n onNavigate?: (item: BreadcrumbItem, index: number) => void;\n}\n\n/** Breadcrumbs 的样式:list、item、current、separator、label、expand */\nexport const breadcrumbsStyles = css.create({\n // 横排、换行、间距由 FlexOrderedList 给\n list: { fontSize: '_sm' },\n item: { display: 'inline-flex', alignItems: 'center', gap: '_xs', minWidth: 0 },\n current: { color: '_text', fontWeight: '_medium' },\n separator: { display: 'inline-flex', color: '_textMuted' },\n label: { display: 'inline-flex', alignItems: 'center', gap: '_xs' },\n expand: { width: '1.75em', minHeight: '1.75em' },\n});\n\n/** 面包屑:链接 + 分隔符,最后一项是当前页 */\nexport const Breadcrumbs = _component(\n ({\n items,\n separator,\n maxItems,\n propsList,\n propsItem,\n propsCollapsedItem,\n propsLink,\n propsLabel,\n propsCurrent,\n propsSeparator,\n propsExpand,\n propsMenu,\n onNavigate,\n ...rest\n }: BreadcrumbsProps) => {\n const lang = useLang();\n\n return () => {\n const collapse = maxItems != null && items.length > maxItems;\n // 折叠时保留第一项与最后两项,中间换成展开按钮\n const shown: (BreadcrumbItem | 'collapsed')[] = collapse\n ? [items[0]!, 'collapsed', ...items.slice(-2)]\n : [...items];\n const last = items.length - 1;\n // 每处各生成一个节点:同一个 VNode 不能放在多个位置\n const sep = () => (\n <span\n {...mergeAttrs<'span'>({ sx: breadcrumbsStyles.separator }, propsSeparator, {\n 'aria-hidden': true,\n })}\n >\n {separator ?? <Icon icon={ChevronRight} flipInRtl />}\n </span>\n );\n\n return (\n <nav {...mergeAttrs<'nav'>({ 'aria-label': lang.breadcrumbs }, rest)}>\n <FlexOrderedList\n {...mergePartProps<FlexProps<'ol'>>(\n { wrap: true, align: 'center', gap: 'xs', sx: breadcrumbsStyles.list },\n propsList,\n )}\n >\n {shown.map((entry, position) => {\n if (entry === 'collapsed') {\n return (\n <li\n key=\"collapsed\"\n {...mergeAttrs<'li'>({ sx: breadcrumbsStyles.item }, propsCollapsedItem)}\n >\n <Menu\n {...mergePartProps<MenuProps>(\n {\n // 被折叠的各级链接一直在 DOM 里:页内搜索、爬虫找得到;一页只有一个,不必延迟\n lazy: false,\n trigger: (props) => (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n sx: breadcrumbsStyles.expand,\n size: 'sm',\n icon: Ellipsis,\n 'aria-label': lang.breadcrumbsExpand,\n },\n propsExpand,\n props,\n )}\n />\n ),\n },\n propsMenu,\n )}\n >\n {items.slice(1, -2).map((hidden, offset) =>\n hidden.href != null ? (\n <MenuLinkItem key={offset} href={hidden.href} icon={hidden.icon}>\n {hidden.label}\n </MenuLinkItem>\n ) : (\n <MenuItem\n key={offset}\n icon={hidden.icon}\n disabled={!onNavigate}\n onAction={() => onNavigate?.(hidden, offset + 1)}\n >\n {hidden.label}\n </MenuItem>\n ),\n )}\n </Menu>\n {sep()}\n </li>\n );\n }\n const index = items.indexOf(entry);\n const own = typeof propsItem === 'function' ? propsItem(entry, index) : propsItem;\n const label = (\n <span {...mergeAttrs<'span'>({ sx: breadcrumbsStyles.label }, propsLabel)}>\n {entry.icon && <Icon icon={entry.icon} />}\n {entry.label}\n </span>\n );\n return (\n <li\n key={entry.key ?? entry.href ?? index}\n {...mergeAttrs<'li'>({ sx: breadcrumbsStyles.item }, own)}\n >\n {index === last ? (\n <span\n {...mergeAttrs<'span'>({ sx: breadcrumbsStyles.current }, propsCurrent, {\n 'aria-current': onNavigate ? 'location' : 'page',\n })}\n >\n {label}\n </span>\n ) : entry.href != null ? (\n <Link\n {...mergePartProps<LinkProps>(\n { tone: 'muted', underline: 'hover', href: entry.href },\n propsLink,\n )}\n >\n {label}\n </Link>\n ) : onNavigate ? (\n <Button variant=\"link\" onClick={() => onNavigate(entry, index)}>\n {label}\n </Button>\n ) : (\n label\n )}\n {position < shown.length - 1 && sep()}\n </li>\n );\n })}\n </FlexOrderedList>\n </nav>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
@@ -8,8 +8,8 @@ import { ButtonBase } from "../base/ButtonBase.js";
|
|
|
8
8
|
import { useRouterLink } from "../utils/dom/link.js";
|
|
9
9
|
import { Menu as Menu$1, MenuGroup, MenuLinkItem } from "../overlay/Menu.js";
|
|
10
10
|
import { useOverflowItems } from "../utils/dom/overflow.js";
|
|
11
|
-
import { createVNode, isVNode,
|
|
12
|
-
import { _component, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
11
|
+
import { createVNode, isVNode, shallowRef } from "vue";
|
|
12
|
+
import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
13
13
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
14
14
|
import { ChevronDown, Ellipsis } from "@lucide/icons";
|
|
15
15
|
//#region src/navigation/NavBar.tsx
|
|
@@ -131,13 +131,13 @@ var NavBar = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
131
131
|
];
|
|
132
132
|
if (item.children?.length) {
|
|
133
133
|
let _slot;
|
|
134
|
-
return createVNode(Menu$1, { "trigger": (props) => createVNode(ButtonBase,
|
|
134
|
+
return createVNode(Menu$1, { "trigger": (props) => createVNode(ButtonBase, mergeJsxProps(props, {
|
|
135
135
|
"sx": sx,
|
|
136
136
|
"disabled": item.disabled,
|
|
137
137
|
"data-state": current ? "active" : "inactive"
|
|
138
138
|
}), { default: () => [content, createVNode(Icon, { "icon": ChevronDown }, null)] }) }, _isSlot(_slot = menuLinks(item.children)) ? _slot : { default: () => [_slot] });
|
|
139
139
|
}
|
|
140
|
-
return createVNode("a",
|
|
140
|
+
return createVNode("a", mergeJsxProps(css.attrs(...sx), {
|
|
141
141
|
"href": item.disabled || item.href == null ? void 0 : router.href(item.href),
|
|
142
142
|
"aria-current": current ? "page" : void 0,
|
|
143
143
|
"aria-disabled": item.disabled || void 0,
|
|
@@ -152,7 +152,7 @@ var NavBar = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
152
152
|
const current = hidden.some((item) => hasActive(item, router.isActive));
|
|
153
153
|
return createVNode(Menu$1, {
|
|
154
154
|
"placement": "bottom-end",
|
|
155
|
-
"trigger": (props) => createVNode(ButtonBase,
|
|
155
|
+
"trigger": (props) => createVNode(ButtonBase, mergeJsxProps(props, {
|
|
156
156
|
"sx": [
|
|
157
157
|
navBarStyles.link,
|
|
158
158
|
focusRingStyles.visible,
|
|
@@ -171,7 +171,7 @@ var NavBar = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
171
171
|
}, _isSlot(_slot2 = menuLinks(item.children)) ? _slot2 : { default: () => [_slot2] }) : menuLinks([item]);
|
|
172
172
|
})) ? _slot3 : { default: () => [_slot3] });
|
|
173
173
|
}
|
|
174
|
-
return () => createVNode("nav", mergeAttrs({}, rest), [createVNode("ul", mergeAttrs({ sx: navBarStyles.list }, propsList.value, { ref: list }), [items.value.map((item, index) => createVNode("li",
|
|
174
|
+
return () => createVNode("nav", mergeAttrs({}, rest), [createVNode("ul", mergeAttrs({ sx: navBarStyles.list }, propsList.value, { ref: list }), [items.value.map((item, index) => createVNode("li", mergeJsxProps({ "key": item.href ?? item.label }, css.attrs(navBarStyles.item), overflow.itemProps(index)), [renderItem(item)])), createVNode("li", mergeJsxProps(css.attrs(navBarStyles.item), overflow.restProps()), [renderMore()])])]);
|
|
175
175
|
}, {
|
|
176
176
|
name: "NavBar",
|
|
177
177
|
props: ["items", "propsList"]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavBar.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","Menu","_mergeProps"],"sources":["../../src/navigation/NavBar.tsx"],"sourcesContent":["/**\n * 横向导航(顶部菜单):一行链接,有子项的是下拉菜单;放不下时后面的收进“更多”菜单。后台的顶栏、门户的主导航。\n * 参考 Ant Design Menu 的 horizontal 模式(溢出收进“…”)。侧边的多级导航用 NavList。\n *\n * <NavBar\n * items={[\n * { label: '工作台', href: '/' },\n * { label: '采购', children: [{ label: '采购单', href: '/po' }, { label: '供应商', href: '/suppliers' }] },\n * { label: '报表', href: '/reports', badge: 3 },\n * ]}\n * aria-label=\"主导航\"\n * />\n *\n * - 当前页按路由适配的 isActive 判断(同 NavList),链接带 aria-current=\"page\" 与下划线;子项是当前页时它的菜单按钮也高亮。\n * - 下拉菜单是 Menu(↑↓ 移动、Esc 关闭回到按钮),菜单项是链接(MenuLinkItem)。\n * - 放不下:useOverflowItems 量出前几项,其余收进“更多”(菜单里有子项的项按分组列出);藏起来的项不占位、读屏与 Tab 跳过。\n *\n * 部件:Root(nav)、List(ul)、Item(li)、Link(a)、Trigger(有子项时的按钮)、More(“更多”按钮)。\n */\nimport { ChevronDown, Ellipsis } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Badge } from '../base/Badge';\nimport { ButtonBase } from '../base/ButtonBase';\nimport { Icon, type IconData } from '../base/Icon';\nimport { useLang } from '../config/context';\nimport { Menu, MenuGroup, MenuLinkItem } from '../overlay/Menu';\nimport { useRouterLink } from '../utils/dom/link';\nimport { useOverflowItems } from '../utils/dom/overflow';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { t } from '../config/theme/tokens';\n\n/** 横向导航的一项:有 href 是链接,有 children 是下拉菜单(一层) */\nexport interface NavBarItem {\n /** 文字 */\n label: string;\n /** 链接地址 */\n href?: string;\n /** 文字前的图标 */\n icon?: IconData;\n /** 下拉菜单里的子项 */\n children?: readonly NavBarItem[];\n /** 计数角标(待办、未读),0 不显示 */\n badge?: number;\n /** 不可用 */\n disabled?: boolean;\n}\n\n/** 未声明的属性落到 nav 上;aria-label 是导航的名称 */\nexport interface NavBarProps extends PartProps<'nav'> {\n /** 各项 */\n items: readonly NavBarItem[];\n /** 列表(ul)的部件属性 */\n propsList?: PartProps<'ul'>;\n}\n\n/** NavBar 的样式:list、item、link、current、badge、more */\nexport const navBarStyles = css.create({\n // 一行:放不下的项由 useOverflowItems 移出排版(容器要 position: relative,间距用 column-gap)\n list: {\n position: 'relative',\n display: 'flex',\n alignItems: 'stretch',\n columnGap: '_xs',\n minWidth: 0,\n margin: 0,\n padding: 0,\n listStyle: 'none',\n },\n item: { display: 'flex', flexShrink: 0 },\n link: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '_xs',\n minHeight: `max(${t.sizes.control}, ${t.sizes.minTarget})`,\n paddingInline: '_md',\n borderRadius: '_md',\n color: { default: '_textMuted', ':hover': '_text' },\n fontWeight: '_medium',\n whiteSpace: 'nowrap',\n textDecoration: 'none',\n backgroundColor: { default: 'transparent', ':hover': '_fillHover' },\n // 当前页的下划线画在底边(与 Tabs 的下划线同色)\n boxShadow: 'none',\n transition: `color ${t.durations.sm} ${t.easings.standard}, background-color ${t.durations.sm} ${t.easings.standard}`,\n },\n current: {\n color: { default: '_accentText', ':hover': '_accentText' },\n boxShadow: `inset 0 calc(-1 * ${t.borderWidths.sm}) 0 ${t.colors.accent}`,\n borderEndStartRadius: 0,\n borderEndEndRadius: 0,\n },\n disabled: { opacity: '_disabled', pointerEvents: 'none' },\n});\n\n/** 子项里有没有当前页 */\nconst hasActive = (item: NavBarItem, isActive: (href: string) => boolean): boolean =>\n (item.href != null && isActive(item.href)) ||\n (item.children ?? []).some((child) => hasActive(child, isActive));\n\n/** 横向导航:一行链接与下拉菜单,放不下的收进“更多” */\nexport const NavBar = _component(({ items, propsList, ...rest }: NavBarProps) => {\n const lang = useLang();\n const router = useRouterLink();\n let list = _state.raw<HTMLElement | null>(null);\n const overflow = useOverflowItems({ container: () => list, count: () => items.length });\n\n const badge = (count = 0) =>\n count > 0 && (\n <Badge size=\"xs\" variant=\"solid\" tone=\"danger\" radius=\"full\">\n {count > 99 ? '99+' : count}\n </Badge>\n );\n\n /** 菜单里的链接(下拉菜单、“更多”菜单共用) */\n const menuLinks = (children: readonly NavBarItem[]) =>\n children.map((child) => (\n <MenuLinkItem\n key={child.href ?? child.label}\n href={child.href ?? ''}\n icon={child.icon}\n disabled={child.disabled}\n aria-current={child.href && router.isActive(child.href) ? 'page' : undefined}\n >\n {child.label}\n </MenuLinkItem>\n ));\n\n function renderItem(item: NavBarItem) {\n const current = hasActive(item, router.isActive);\n const sx = [\n navBarStyles.link,\n focusRingStyles.visible,\n current && navBarStyles.current,\n item.disabled && navBarStyles.disabled,\n ];\n const content = [item.icon && <Icon icon={item.icon} />, item.label, badge(item.badge)];\n if (item.children?.length) {\n return (\n <Menu\n trigger={(props) => (\n <ButtonBase\n {...props}\n sx={sx}\n disabled={item.disabled}\n data-state={current ? 'active' : 'inactive'}\n >\n {content}\n <Icon icon={ChevronDown} />\n </ButtonBase>\n )}\n >\n {menuLinks(item.children)}\n </Menu>\n );\n }\n return (\n <a\n {...css.attrs(...sx)}\n href={item.disabled || item.href == null ? undefined : router.href(item.href)}\n aria-current={current ? 'page' : undefined}\n aria-disabled={item.disabled || undefined}\n data-state={current ? 'active' : 'inactive'}\n onClick={(event: MouseEvent) => item.href && router.onClick(event, item.href)}\n >\n {content}\n </a>\n );\n }\n\n /** “更多”菜单:收起来的各项,有子项的按分组列出 */\n function renderMore() {\n const hidden = items.slice(overflow.visible);\n const current = hidden.some((item) => hasActive(item, router.isActive));\n return (\n <Menu\n placement=\"bottom-end\"\n trigger={(props) => (\n <ButtonBase\n {...props}\n sx={[navBarStyles.link, focusRingStyles.visible, current && navBarStyles.current]}\n aria-label={lang.navBarMore}\n >\n <Icon icon={Ellipsis} />\n </ButtonBase>\n )}\n >\n {hidden.map((item) =>\n item.children?.length ? (\n <MenuGroup key={item.label} label={item.label}>\n {menuLinks(item.children)}\n </MenuGroup>\n ) : (\n menuLinks([item])\n ),\n )}\n </Menu>\n );\n }\n\n return () => (\n <nav {...mergeAttrs<'nav'>({}, rest)}>\n <ul {...mergeAttrs<'ul'>({ sx: navBarStyles.list }, propsList, { ref: _toRef(list) })}>\n {items.map((item, index) => (\n <li\n key={item.href ?? item.label}\n {...css.attrs(navBarStyles.item)}\n {...overflow.itemProps(index)}\n >\n {renderItem(item)}\n </li>\n ))}\n <li {...css.attrs(navBarStyles.item)} {...overflow.restProps()}>\n {renderMore()}\n </li>\n </ul>\n </nav>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,SAAA,QAAA,GAAA;CAAA,OAAA,OAAA,MAAA,cAAA,OAAA,UAAA,SAAA,KAAA,CAAA,MAAA,qBAAA,CAAAA,QAAA,CAAA;AAAA;;AASA,IAAa,eAAe,IAAI,OAAO;CAErC,MAAM;EACJ,UAAU;EACV,SAAS;EACT,YAAY;EACZ,WAAW;EACX,UAAU;EACV,QAAQ;EACR,SAAS;EACT,WAAW;CACb;CACA,MAAM;EAAE,SAAS;EAAQ,YAAY;CAAE;CACvC,MAAM;EACJ,SAAS;EACT,YAAY;EACZ,KAAK;EACL,WAAW,OAAO,EAAE,MAAM,QAAO,IAAK,EAAE,MAAM,UAAS;EACvD,eAAe;EACf,cAAc;EACd,OAAO;GAAE,SAAS;GAAc,UAAU;EAAQ;EAClD,YAAY;EACZ,YAAY;EACZ,gBAAgB;EAChB,iBAAiB;GAAE,SAAS;GAAe,UAAU;EAAa;EAElE,WAAW;EACX,YAAY,SAAS,EAAE,UAAU,GAAE,GAAI,EAAE,QAAQ,SAAQ,qBAAsB,EAAE,UAAU,GAAE,GAAI,EAAE,QAAQ;CAC7G;CACA,SAAS;EACP,OAAO;GAAE,SAAS;GAAe,UAAU;EAAc;EACzD,WAAW,qBAAqB,EAAE,aAAa,GAAE,MAAO,EAAE,OAAO;EACjE,sBAAsB;EACtB,oBAAoB;CACtB;CACA,UAAU;EAAE,SAAS;EAAa,eAAe;CAAO;AAC1D,CAAC;;AAGD,IAAM,aAAa,MAAkB,aAClC,KAAK,QAAQ,QAAQ,SAAS,KAAK,IAAI,MACvC,KAAK,YAAY,CAAA,EAAA,CAAI,MAAM,UAAU,UAAU,OAAO,QAAQ,CAAC;;AAGlE,IAAa,SAAS,0BAAW,QAAA,SAAgD;CAAA,MAAA,QAAAC,aAAA,QAAA,OAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAxB,OAAIC,UAAA,QAAA,MAAA,IAAA;CAC3D,MAAM,OAAO,QAAQ;CACrB,MAAM,SAAS,cAAc;CAC7B,IAAI,OAAIC,WAAkC,IAAI;CAC9C,MAAM,WAAW,iBAAiB;EAAE,iBAAW,KAAA;EAAY,aAAa,MAAA,MAAM;CAAO,CAAC;CAEtF,MAAM,SAAS,QAAQ,MACrB,QAAQ,KAACC,YAAA,OAAA;EAAA,QAAA;EAAA,WAAA;EAAA,QAAA;EAAA,UAAA;CAAA,GAAA,EAAA,eAAA,CAEJ,QAAQ,KAAK,QAAQ,KAAK,EAAA,CAAA;;CAKjC,MAAM,aAAa,aACjB,SAAS,KAAK,UAAKA,YAAA,cAAA;EAAA,OAEV,MAAM,QAAQ,MAAM;EAAK,QACxB,MAAM,QAAQ;EAAE,QAChB,MAAM;EAAI,YACN,MAAM;EAAQ,gBACV,MAAM,QAAQ,OAAO,SAAS,MAAM,IAAI,IAAI,SAAS,KAAA;CAAS,GAAA,EAAA,eAAA,CAE3E,MAAM,KAAK,EAAA,CAAA,CAEf;CAEH,SAAS,WAAW,MAAkB;EACpC,MAAM,UAAU,UAAU,MAAM,OAAO,QAAQ;EAC/C,MAAM,KAAK;GACT,aAAa;GACb,gBAAgB;GAChB,WAAW,aAAa;GACxB,KAAK,YAAY,aAAa;EAAQ;EAExC,MAAM,UAAU;GAAC,KAAK,QAAIA,YAAA,MAAA,EAAA,QAAgB,KAAK,KAAI,GAAA,IAAA;GAAM,KAAK;GAAO,MAAM,KAAK,KAAK;EAAC;EACtF,IAAI,KAAK,UAAU,QAAQ;GAAA,IAAA;GACzB,OAAAA,YAAAC,QAAA,EAAA,YAEc,UAAKD,YAAA,YAAAE,WAEP,OAAK;IAAA,MACL;IAAE,YACI,KAAK;IAAQ,cACX,UAAU,WAAW;GAAU,CAAA,GAAA,EAAA,eAAA,CAE1C,SAAOF,YAAA,MAAA,EAAA,QACI,YAAW,GAAA,IAAA,CAAA,EAAA,CAAA,EAE1B,GAAA,QAAA,QAEA,UAAU,KAAK,QAAQ,CAAC,IAAA,QAAA,EAAA,eAAA,CAAA,KAAA,EAAA,CAAA;EAG/B;EACA,OAAAA,YAAA,KAAAE,WAEQ,IAAI,MAAM,GAAG,EAAE,GAAC;GAAA,QACd,KAAK,YAAY,KAAK,QAAQ,OAAO,KAAA,IAAY,OAAO,KAAK,KAAK,IAAI;GAAC,gBAC/D,UAAU,SAAS,KAAA;GAAS,iBAC3B,KAAK,YAAY,KAAA;GAAS,cAC7B,UAAU,WAAW;GAAU,YACjC,UAAsB,KAAK,QAAQ,OAAO,QAAQ,OAAO,KAAK,IAAI;EAAC,CAAA,GAAA,CAE5E,OAAO,CAAA;CAGd;;CAGA,SAAS,aAAa;EAAA,IAAA;EACpB,MAAM,SAAS,MAAA,MAAM,MAAM,SAAS,OAAO;EAC3C,MAAM,UAAU,OAAO,MAAM,SAAS,UAAU,MAAM,OAAO,QAAQ,CAAC;EACtE,OAAAF,YAAAC,QAAA;GAAA,aAAA;GAAA,YAGc,UAAKD,YAAA,YAAAE,WAEP,OAAK;IAAA,MACL;KAAC,aAAa;KAAM,gBAAgB;KAAS,WAAW,aAAa;IAAO;IAAC,cACrE,KAAK;GAAU,CAAA,GAAA;IAAA,eAAA,CAAAF,YAAA,MAAA,EAAA,QAEf,SAAQ,GAAA,IAAA,CAAA;IAAA,SAAA;GAAA,CAAA;EAEvB,GAAA,QAAA,SAEA,OAAO,KAAK,SAAI;GAAA,IAAA;GAAA,OACf,KAAK,UAAU,SAAMA,YAAA,WAAA;IAAA,OACH,KAAK;IAAK,SAAS,KAAK;GAAK,GAAA,QAAA,SAC1C,UAAU,KAAK,QAAQ,CAAC,IAAA,SAAA,EAAA,eAAA,CAAA,MAAA,EAAA,CAAA,IAG3B,UAAU,CAAC,IAAI,CAAC;EACjB,CACH,CAAC,IAAA,SAAA,EAAA,eAAA,CAAA,MAAA,EAAA,CAAA;CAGP;CAEA,aAAOA,YAAA,OACI,WAAkB,CAAC,GAAG,IAAI,GAAC,CAAAA,YAAA,MAC1B,WAAiB,EAAE,IAAI,aAAa,KAAK,GAAC,UAAA,OAAa,EAAE,KAAG,KAAe,CAAC,GAAC,CAClF,MAAA,MAAM,KAAK,MAAM,UAAKA,YAAA,MAAAE,WAAA,EAAA,OAEd,KAAK,QAAQ,KAAK,MAAK,GACxB,IAAI,MAAM,aAAa,IAAI,GAC3B,SAAS,UAAU,KAAK,CAAC,GAAA,CAE5B,WAAW,IAAI,CAAC,CAAA,CAEpB,GAACF,YAAA,MAAAE,WACM,IAAI,MAAM,aAAa,IAAI,GAAO,SAAS,UAAU,CAAC,GAAA,CAC3D,WAAW,CAAC,CAAA,CAAA,CAAA,CAAA,CAAA;AAKvB,GAAC;CAAA,MAAA;CAAA,OAAA,CAAA,SAAA,WAAA;AAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"NavBar.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","Menu","_mergeProps"],"sources":["../../src/navigation/NavBar.tsx"],"sourcesContent":["/**\n * 横向导航(顶部菜单):一行链接,有子项的是下拉菜单;放不下时后面的收进“更多”菜单。后台的顶栏、门户的主导航。\n * 参考 Ant Design Menu 的 horizontal 模式(溢出收进“…”)。侧边的多级导航用 NavList。\n *\n * <NavBar\n * items={[\n * { label: '工作台', href: '/' },\n * { label: '采购', children: [{ label: '采购单', href: '/po' }, { label: '供应商', href: '/suppliers' }] },\n * { label: '报表', href: '/reports', badge: 3 },\n * ]}\n * aria-label=\"主导航\"\n * />\n *\n * - 当前页按路由适配的 isActive 判断(同 NavList),链接带 aria-current=\"page\" 与下划线;子项是当前页时它的菜单按钮也高亮。\n * - 下拉菜单是 Menu(↑↓ 移动、Esc 关闭回到按钮),菜单项是链接(MenuLinkItem)。\n * - 放不下:useOverflowItems 量出前几项,其余收进“更多”(菜单里有子项的项按分组列出);藏起来的项不占位、读屏与 Tab 跳过。\n *\n * 部件:Root(nav)、List(ul)、Item(li)、Link(a)、Trigger(有子项时的按钮)、More(“更多”按钮)。\n */\nimport { ChevronDown, Ellipsis } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Badge } from '../base/Badge';\nimport { ButtonBase } from '../base/ButtonBase';\nimport { Icon, type IconData } from '../base/Icon';\nimport { useLang } from '../config/context';\nimport { Menu, MenuGroup, MenuLinkItem } from '../overlay/Menu';\nimport { useRouterLink } from '../utils/dom/link';\nimport { useOverflowItems } from '../utils/dom/overflow';\nimport { mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { t } from '../config/theme/tokens';\n\n/** 横向导航的一项:有 href 是链接,有 children 是下拉菜单(一层) */\nexport interface NavBarItem {\n /** 文字 */\n label: string;\n /** 链接地址 */\n href?: string;\n /** 文字前的图标 */\n icon?: IconData;\n /** 下拉菜单里的子项 */\n children?: readonly NavBarItem[];\n /** 计数角标(待办、未读),0 不显示 */\n badge?: number;\n /** 不可用 */\n disabled?: boolean;\n}\n\n/** 未声明的属性落到 nav 上;aria-label 是导航的名称 */\nexport interface NavBarProps extends PartProps<'nav'> {\n /** 各项 */\n items: readonly NavBarItem[];\n /** 列表(ul)的部件属性 */\n propsList?: PartProps<'ul'>;\n}\n\n/** NavBar 的样式:list、item、link、current、badge、more */\nexport const navBarStyles = css.create({\n // 一行:放不下的项由 useOverflowItems 移出排版(容器要 position: relative,间距用 column-gap)\n list: {\n position: 'relative',\n display: 'flex',\n alignItems: 'stretch',\n columnGap: '_xs',\n minWidth: 0,\n margin: 0,\n padding: 0,\n listStyle: 'none',\n },\n item: { display: 'flex', flexShrink: 0 },\n link: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '_xs',\n minHeight: `max(${t.sizes.control}, ${t.sizes.minTarget})`,\n paddingInline: '_md',\n borderRadius: '_md',\n color: { default: '_textMuted', ':hover': '_text' },\n fontWeight: '_medium',\n whiteSpace: 'nowrap',\n textDecoration: 'none',\n backgroundColor: { default: 'transparent', ':hover': '_fillHover' },\n // 当前页的下划线画在底边(与 Tabs 的下划线同色)\n boxShadow: 'none',\n transition: `color ${t.durations.sm} ${t.easings.standard}, background-color ${t.durations.sm} ${t.easings.standard}`,\n },\n current: {\n color: { default: '_accentText', ':hover': '_accentText' },\n boxShadow: `inset 0 calc(-1 * ${t.borderWidths.sm}) 0 ${t.colors.accent}`,\n borderEndStartRadius: 0,\n borderEndEndRadius: 0,\n },\n disabled: { opacity: '_disabled', pointerEvents: 'none' },\n});\n\n/** 子项里有没有当前页 */\nconst hasActive = (item: NavBarItem, isActive: (href: string) => boolean): boolean =>\n (item.href != null && isActive(item.href)) ||\n (item.children ?? []).some((child) => hasActive(child, isActive));\n\n/** 横向导航:一行链接与下拉菜单,放不下的收进“更多” */\nexport const NavBar = _component(({ items, propsList, ...rest }: NavBarProps) => {\n const lang = useLang();\n const router = useRouterLink();\n let list = _state.raw<HTMLElement | null>(null);\n const overflow = useOverflowItems({ container: () => list, count: () => items.length });\n\n const badge = (count = 0) =>\n count > 0 && (\n <Badge size=\"xs\" variant=\"solid\" tone=\"danger\" radius=\"full\">\n {count > 99 ? '99+' : count}\n </Badge>\n );\n\n /** 菜单里的链接(下拉菜单、“更多”菜单共用) */\n const menuLinks = (children: readonly NavBarItem[]) =>\n children.map((child) => (\n <MenuLinkItem\n key={child.href ?? child.label}\n href={child.href ?? ''}\n icon={child.icon}\n disabled={child.disabled}\n aria-current={child.href && router.isActive(child.href) ? 'page' : undefined}\n >\n {child.label}\n </MenuLinkItem>\n ));\n\n function renderItem(item: NavBarItem) {\n const current = hasActive(item, router.isActive);\n const sx = [\n navBarStyles.link,\n focusRingStyles.visible,\n current && navBarStyles.current,\n item.disabled && navBarStyles.disabled,\n ];\n const content = [item.icon && <Icon icon={item.icon} />, item.label, badge(item.badge)];\n if (item.children?.length) {\n return (\n <Menu\n trigger={(props) => (\n <ButtonBase\n {...props}\n sx={sx}\n disabled={item.disabled}\n data-state={current ? 'active' : 'inactive'}\n >\n {content}\n <Icon icon={ChevronDown} />\n </ButtonBase>\n )}\n >\n {menuLinks(item.children)}\n </Menu>\n );\n }\n return (\n <a\n {...css.attrs(...sx)}\n href={item.disabled || item.href == null ? undefined : router.href(item.href)}\n aria-current={current ? 'page' : undefined}\n aria-disabled={item.disabled || undefined}\n data-state={current ? 'active' : 'inactive'}\n onClick={(event: MouseEvent) => item.href && router.onClick(event, item.href)}\n >\n {content}\n </a>\n );\n }\n\n /** “更多”菜单:收起来的各项,有子项的按分组列出 */\n function renderMore() {\n const hidden = items.slice(overflow.visible);\n const current = hidden.some((item) => hasActive(item, router.isActive));\n return (\n <Menu\n placement=\"bottom-end\"\n trigger={(props) => (\n <ButtonBase\n {...props}\n sx={[navBarStyles.link, focusRingStyles.visible, current && navBarStyles.current]}\n aria-label={lang.navBarMore}\n >\n <Icon icon={Ellipsis} />\n </ButtonBase>\n )}\n >\n {hidden.map((item) =>\n item.children?.length ? (\n <MenuGroup key={item.label} label={item.label}>\n {menuLinks(item.children)}\n </MenuGroup>\n ) : (\n menuLinks([item])\n ),\n )}\n </Menu>\n );\n }\n\n return () => (\n <nav {...mergeAttrs<'nav'>({}, rest)}>\n <ul {...mergeAttrs<'ul'>({ sx: navBarStyles.list }, propsList, { ref: _toRef(list) })}>\n {items.map((item, index) => (\n <li\n key={item.href ?? item.label}\n {...css.attrs(navBarStyles.item)}\n {...overflow.itemProps(index)}\n >\n {renderItem(item)}\n </li>\n ))}\n <li {...css.attrs(navBarStyles.item)} {...overflow.restProps()}>\n {renderMore()}\n </li>\n </ul>\n </nav>\n );\n});\n"],"mappings":"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"}
|
|
@@ -30,6 +30,7 @@ export declare const navListStyles: Readonly<{
|
|
|
30
30
|
section: css.CompiledStyles;
|
|
31
31
|
sectionIcon: css.CompiledStyles;
|
|
32
32
|
sectionLabel: css.CompiledStyles;
|
|
33
|
+
sectionText: css.CompiledStyles;
|
|
33
34
|
}>;
|
|
34
35
|
/** 未声明的属性落到 nav 上;aria-label 是导航的名称 */
|
|
35
36
|
export interface NavListProps extends PartProps<'nav'> {
|
|
@@ -14,8 +14,8 @@ import { Collapsible } from "../display/Collapsible.js";
|
|
|
14
14
|
import { Tooltip } from "../overlay/Tooltip.js";
|
|
15
15
|
import { itemStyles } from "../utils/style/item-styles.js";
|
|
16
16
|
import { HoverCard } from "../overlay/HoverCard.js";
|
|
17
|
-
import { Fragment, computed, createVNode, isVNode,
|
|
18
|
-
import { _component, bindable, childrenProp, childrenStable, createContext, forwardChildren, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
17
|
+
import { Fragment, computed, createVNode, isVNode, onBeforeUnmount, ref, useId, watch } from "vue";
|
|
18
|
+
import { _component, bindable, childrenProp, childrenStable, createContext, forwardChildren, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
19
19
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
20
20
|
import { ChevronRight } from "@lucide/icons";
|
|
21
21
|
//#region src/navigation/NavList.tsx
|
|
@@ -72,17 +72,25 @@ var navListStyles = css.create({
|
|
|
72
72
|
disabled: { pointerEvents: "none" },
|
|
73
73
|
chevron: { transition: `transform ${t.durations.md} ${t.easings.standard}` },
|
|
74
74
|
chevronOpen: { transform: "rotate(90deg)" },
|
|
75
|
-
section: {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
section: {
|
|
76
|
+
display: "flex",
|
|
77
|
+
flexDirection: "column",
|
|
78
|
+
gap: "_xs",
|
|
79
|
+
marginBlockStart: {
|
|
80
|
+
default: "_lg",
|
|
81
|
+
":first-child": 0
|
|
82
|
+
},
|
|
83
|
+
breakInside: "avoid"
|
|
84
|
+
},
|
|
79
85
|
sectionLabel: {
|
|
80
86
|
display: "flex",
|
|
81
87
|
alignItems: "center",
|
|
82
88
|
gap: "_sm",
|
|
83
89
|
paddingBlock: "_xs",
|
|
84
90
|
paddingInline: "_md",
|
|
85
|
-
color: "_text"
|
|
91
|
+
color: "_text"
|
|
92
|
+
},
|
|
93
|
+
sectionText: {
|
|
86
94
|
fontSize: "_sm",
|
|
87
95
|
fontWeight: "_semibold",
|
|
88
96
|
letterSpacing: "_wide"
|
|
@@ -121,7 +129,7 @@ var NavList = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
121
129
|
NavCompactContext.provide(isCompact);
|
|
122
130
|
return () => {
|
|
123
131
|
let _slot;
|
|
124
|
-
return createVNode("nav",
|
|
132
|
+
return createVNode("nav", mergeJsxProps(mergeAttrs({}, rest), { "data-compact": isCompact() || void 0 }), [createVNode(FlexList, mergePartProps({
|
|
125
133
|
direction: "column",
|
|
126
134
|
gap: "xs"
|
|
127
135
|
}, propsList.value), _isSlot(_slot = forwardChildren(_props)) ? _slot : { default: () => [_slot] })]);
|
|
@@ -159,7 +167,7 @@ var NavItem = /*#__PURE__*/ _component((_props2, _ctx2) => {
|
|
|
159
167
|
onBeforeUnmount(() => group.report(id, false));
|
|
160
168
|
}
|
|
161
169
|
const iconOnly = () => compact() && icon.value != null;
|
|
162
|
-
const link = (tooltip) => createVNode("a",
|
|
170
|
+
const link = (tooltip) => createVNode("a", mergeJsxProps(mergeAttrs({
|
|
163
171
|
...tooltip,
|
|
164
172
|
sx: [
|
|
165
173
|
itemStyles.row,
|
|
@@ -253,7 +261,7 @@ var NavGroup = /*#__PURE__*/ _component((_props3, _ctx3) => {
|
|
|
253
261
|
"delay": 150,
|
|
254
262
|
"lazy": false,
|
|
255
263
|
"sx": navListStyles.flyout,
|
|
256
|
-
"trigger": _cache[0] || (_cache[0] = (props) => createVNode(ButtonBase,
|
|
264
|
+
"trigger": _cache[0] || (_cache[0] = (props) => createVNode(ButtonBase, mergeJsxProps(mergePartProps({ sx: [
|
|
257
265
|
itemStyles.row,
|
|
258
266
|
itemStyles.hoverable,
|
|
259
267
|
navListStyles.row,
|
|
@@ -274,7 +282,7 @@ var NavGroup = /*#__PURE__*/ _component((_props3, _ctx3) => {
|
|
|
274
282
|
$stable: childrenStable()
|
|
275
283
|
})]);
|
|
276
284
|
}
|
|
277
|
-
return () => iconOnly() ? renderFlyout() : createVNode("li", mergeAttrs({}, rest), [createVNode(Collapsible,
|
|
285
|
+
return () => iconOnly() ? renderFlyout() : createVNode("li", mergeAttrs({}, rest), [createVNode(Collapsible, mergeJsxProps(mergePartProps({ trigger: (props) => createVNode(ButtonBase, mergePartProps({ sx: [
|
|
278
286
|
itemStyles.row,
|
|
279
287
|
itemStyles.hoverable,
|
|
280
288
|
navListStyles.row,
|
|
@@ -354,7 +362,7 @@ var NavSection = /*#__PURE__*/ _component((_props5, _ctx5) => {
|
|
|
354
362
|
return createVNode("li", mergeAttrs({ sx: navListStyles.section }, rest), [createVNode("span", mergeAttrs({ sx: [navListStyles.sectionLabel, css.select(() => iconOnly() && navListStyles.compactSection, true)] }, propsLabel.value), [icon.value && createVNode(Icon, mergePartProps({
|
|
355
363
|
icon: icon.value,
|
|
356
364
|
sx: navListStyles.sectionIcon
|
|
357
|
-
}, propsIcon.value), null), createVNode("span",
|
|
365
|
+
}, propsIcon.value), null), createVNode("span", mergeJsxProps({ "id": labelId }, css.attrs(navListStyles.sectionText, iconOnly() && visuallyHiddenStyles.hidden)), [label.value])]), createVNode(FlexList, mergePartProps({
|
|
358
366
|
direction: "column",
|
|
359
367
|
gap: "xs"
|
|
360
368
|
}, propsList.value, { "aria-labelledby": labelId }), _isSlot(_slot6 = forwardChildren(_props5)) ? _slot6 : { default: () => [_slot6] })]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavList.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps","_vtp_forwardChildren","_vtp_childrenProp","_vue_computed","_vtp_bindable","_vue_ref","_vtp_childrenStable","_Fragment"],"sources":["../../src/navigation/NavList.tsx"],"sourcesContent":["/**\n * 侧边导航,复合组件:NavList(nav > ul)> NavItem(链接)/ NavGroup(可展开的一组)/ NavSection(带小标题的一组,\n * 不能收起:文档站这类链接多、按主题分组的侧栏),里面再放 NavItem。\n * 当前页按路由适配的 isActive 判断(也可以用 active 指定),带 aria-current=\"page\" 与高亮;\n * 含当前页的分组自动展开。分组用 Collapsible(触发器带 aria-expanded / aria-controls)。\n *\n * <NavList aria-label=\"后台\">\n * <NavItem href=\"/\" icon={House}>概览</NavItem>\n * <NavGroup label=\"订单\" icon={Package}>\n * <NavItem href=\"/orders\">全部订单</NavItem>\n * <NavItem href=\"/orders/refunds\">退款</NavItem>\n * </NavGroup>\n * </NavList>\n *\n * 用 vue-router 时 vueRouterAdapter(router, { match: 'prefix' }) 能让 /orders 在 /orders/42 页面也高亮。\n *\n * 紧凑(compact):侧栏窄到只放得下图标时,各项只显示图标(文字留给读屏,悬停、聚焦时用 Tooltip 显示),\n * 小节标题换成它的图标(不能点);分组也只剩图标,悬停、聚焦时子项从右边弹出来(HoverCard,完整的文字,\n * Tab 进入),组里有当前页时图标高亮。AppShell 的抽屉式侧栏拖窄时自动进入(NavCompactContext),\n * 也可以直接写 <NavList compact>。\n *\n * NavItem 的 badge 是计数角标(待办、未读):展开时在文字后面,紧凑时是图标右上角的小圆点(读屏照样念出数目)。\n */\nimport { ChevronRight } from '@lucide/icons';\nimport { createContext, _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onBeforeUnmount, useId, watch, type VNodeChild } from 'vue';\nimport { ButtonBase, type ButtonBaseProps } from '../base/ButtonBase';\nimport { Badge } from '../base/Badge';\nimport { Icon, type IconData, type IconProps } from '../base/Icon';\nimport { Indicator } from '../base/Indicator';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { Collapsible, type CollapsibleProps } from '../display/Collapsible';\nimport { HoverCard } from '../overlay/HoverCard';\nimport { Tooltip, type TooltipTriggerProps } from '../overlay/Tooltip';\nimport { useLang } from '../config/context';\nimport { useRouterLink } from '../utils/dom/link';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { rippleHostStyles, useRipple } from '../utils/dom/ripple';\nimport { itemStyles } from '../utils/style/item-styles';\nimport { focusRingStyles } from '../utils/style/styles';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport { FlexList, type FlexProps } from '../layout/Flex';\nimport { t } from '../config/theme/tokens';\n\n/** 分组向里面的项要的信息:哪些项是当前页(有当前页时自动展开) */\nexport interface NavGroupState {\n /** 组内的一项报告自己是不是当前页(item 是这一项的标识) */\n report(item: symbol, active: boolean): void;\n}\n\n/** NavGroup 的上下文:组内的项据此缩进;不在组内时为 null */\nexport const NavGroupContext = createContext<NavGroupState | null>('NavGroup');\n\n/** 导航是不是紧凑(只显示图标):AppShell 按侧栏宽度提供,NavList 的 compact 可以覆盖 */\nexport const NavCompactContext = createContext<() => boolean>('NavCompact');\n\n/** NavList 的样式:nested、row、current、disabled、chevron、section、sectionLabel 等 */\nexport const navListStyles = css.create({\n nested: { paddingInlineStart: '_lg', paddingTop: '_xs' },\n // 链接与分组的触发器共用:列表行(itemStyles)之上,导航项更宽松、字重更重,平时是次要颜色\n row: {\n paddingInline: '_md',\n borderRadius: '_md',\n color: { default: '_textMuted', ':hover': '_text' },\n fontWeight: '_medium',\n },\n // 当前页的颜色来自 itemStyles.current;悬停时也保持品牌色\n current: { color: { default: '_accentText', ':hover': '_accentText' } },\n disabled: { pointerEvents: 'none' },\n chevron: { transition: `transform ${t.durations.md} ${t.easings.standard}` },\n chevronOpen: { transform: 'rotate(90deg)' },\n // 小节之间留出间隔,第一节贴着顶部\n section: { marginBlockStart: { default: '_lg', ':first-child': 0 } },\n sectionLabel: {\n display: 'flex',\n alignItems: 'center',\n gap: '_sm',\n paddingBlock: '_xs',\n paddingInline: '_md',\n color: '_text',\n fontSize: '_sm',\n fontWeight: '_semibold',\n letterSpacing: '_wide',\n },\n // 小节标题的图标只是标记,比链接的图标淡\n sectionIcon: { color: '_textMuted', flexShrink: 0 },\n // 紧凑:图标居中;小节标题只剩图标,上面一条细线与上一节隔开\n compactRow: { justifyContent: 'center', paddingInline: 0 },\n compactSection: {\n justifyContent: 'center',\n paddingInline: 0,\n paddingBlockStart: '_sm',\n borderBlockStartWidth: '_xs',\n borderBlockStartStyle: 'solid',\n borderBlockStartColor: '_borderMuted',\n },\n compactNested: { paddingInlineStart: 0 },\n // 紧凑分组弹出的卡片:比侧栏宽,放得下完整的文字\n flyout: { padding: '_xs', minWidth: '12em' },\n});\n\n// ─────────────── NavList ───────────────\n\n/** 未声明的属性落到 nav 上;aria-label 是导航的名称 */\nexport interface NavListProps extends PartProps<'nav'> {\n /** 紧凑:只显示图标;不写时跟随所在的 AppShell 侧栏(拖窄时紧凑) */\n compact?: boolean;\n /** 列表(ul)的部件属性 */\n propsList?: Partial<FlexProps<'ul'>>;\n children?: VNodeChild;\n}\n\n/** 侧边导航(nav > ul),里面放 NavItem 与 NavGroup */\nexport const NavList = _component(({ compact, propsList, children, ...rest }: NavListProps) => {\n const inherited = NavCompactContext.inject(() => false);\n const isCompact = () => compact ?? inherited();\n NavCompactContext.provide(isCompact);\n return () => (\n <nav {...mergeAttrs<'nav'>({}, rest)} data-compact={isCompact() || undefined}>\n <FlexList {...mergePartProps<FlexProps<'ul'>>({ direction: 'column', gap: 'xs' }, propsList)}>\n {children}\n </FlexList>\n </nav>\n );\n});\n\n// ─────────────── NavItem ───────────────\n\n/** 地址与当前页由组件管理 */\nexport type NavItemManaged = 'href' | 'aria-current';\n\n/** 未声明的属性落到链接(a)上 */\nexport interface NavItemProps extends PartProps<'a', NavItemManaged> {\n /** 链接地址 */\n href: string;\n /** 文字前的图标 */\n icon?: IconData;\n /** 是否是当前页;不写时按路由适配的 isActive 判断 */\n active?: boolean;\n /** 不可用:不能点、不能聚焦 */\n disabled?: boolean;\n /** 文字后面的内容(自定义的标记);只是计数时用 badge */\n end?: VNodeChild;\n /** 计数角标(待办、未读):展开时是文字后面的 Badge,紧凑时是图标右上角的小圆点;0 不显示 */\n badge?: number;\n /** 角标的色调,默认 danger */\n badgeTone?: StatusTone;\n /** 按下时的波纹;不写时沿用全局配置 */\n ripple?: boolean;\n /** 外层 li 的部件属性 */\n propsItem?: PartProps<'li'>;\n /** 图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n children?: VNodeChild;\n}\n\n/** 导航项(li > a):当前页高亮并带 aria-current=\"page\" */\nexport const NavItem = _component(\n ({\n href,\n icon,\n active,\n disabled = false,\n end,\n badge = 0,\n badgeTone = 'danger',\n ripple,\n propsItem,\n propsIcon,\n propsLabel,\n children,\n ...rest\n }: NavItemProps) => {\n const lang = useLang();\n const router = useRouterLink();\n const group = NavGroupContext.inject(null);\n const rippleHandlers = useRipple(() => ripple);\n const current = _derived(active ?? router.isActive(href));\n const compact = NavCompactContext.inject(() => false);\n const id = Symbol('NavItem');\n\n // 告诉所在的分组自己是不是当前页(分组据此自动展开)\n if (group) {\n watch(\n () => current,\n (value) => group.report(id, value),\n { immediate: true },\n );\n onBeforeUnmount(() => group.report(id, false));\n }\n\n const iconOnly = () => compact() && icon != null;\n // tooltip:只剩图标时 Tooltip 给触发器的属性(定位用的 ref、悬停与聚焦的事件)\n const link = (tooltip?: TooltipTriggerProps) => (\n <a\n {...mergeAttrs<'a'>(\n {\n ...tooltip,\n sx: [\n itemStyles.row,\n itemStyles.hoverable,\n navListStyles.row,\n focusRingStyles.visible,\n rippleHostStyles.host,\n iconOnly() && navListStyles.compactRow,\n current && [itemStyles.current, navListStyles.current],\n disabled && [itemStyles.disabled, navListStyles.disabled],\n ],\n },\n rest,\n {\n href: disabled ? undefined : router.href(href),\n 'aria-current': current ? 'page' : undefined,\n 'aria-disabled': disabled || undefined,\n // 使用方的 onClick 先执行,preventDefault 可以拦下路由跳转\n onClick: (event: MouseEvent) => router.onClick(event, href),\n ...rippleHandlers,\n },\n )}\n data-state={current ? 'active' : 'inactive'}\n >\n {icon &&\n (iconOnly() && badge > 0 ? (\n // 紧凑:图标右上角一个小圆点(图标太小,叠不下数字);读屏照样念出数目\n <Indicator dot tone={badgeTone} label={lang.indicatorCount(badge)}>\n <Icon {...mergePartProps<IconProps>({ icon }, propsIcon)} />\n </Indicator>\n ) : (\n <Icon {...mergePartProps<IconProps>({ icon }, propsIcon)} />\n ))}\n <span\n {...mergeAttrs<'span'>(\n { sx: [itemStyles.label, iconOnly() && visuallyHiddenStyles.hidden] },\n propsLabel,\n )}\n >\n {children}\n </span>\n {!iconOnly() && end}\n {!iconOnly() && badge > 0 && (\n <Badge size=\"xs\" variant=\"solid\" tone={badgeTone} radius=\"full\">\n {badge > 99 ? '99+' : badge}\n </Badge>\n )}\n </a>\n );\n\n return () => (\n <li {...mergeAttrs<'li'>({}, propsItem)}>\n {iconOnly() ? (\n // 只剩图标:名称在读屏的文字里,看的人悬停、聚焦时从提示里读\n <Tooltip placement=\"right\" delay={200} trigger={link}>\n {children}\n </Tooltip>\n ) : (\n link()\n )}\n </li>\n );\n },\n);\n\n// ─────────────── NavGroup ───────────────\n\n/** 未声明的属性落到外层 li 上 */\nexport interface NavGroupProps extends PartProps<'li'> {\n /** 分组标题 */\n label: VNodeChild;\n /** 标题前的图标 */\n icon?: IconData;\n /** 是否展开:父级写 _open={x};含当前页时自动展开 */\n _open?: boolean;\n /** 标题按钮的部件属性 */\n propsTrigger?: Omit<Partial<ButtonBaseProps>, 'aria-expanded' | 'aria-controls'>;\n /** 展开区(Collapsible)的部件属性 */\n propsContent?: Partial<CollapsibleProps>;\n /** 里面的列表(ul)的部件属性 */\n propsList?: Partial<FlexProps<'ul'>>;\n /** 标题文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 标题图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n children?: VNodeChild;\n}\n\n/** 可展开的导航分组(li > 按钮 + 子列表) */\nexport const NavGroup = _component(\n ({\n label,\n icon,\n _open: open = _bindable(false),\n propsTrigger,\n propsContent,\n propsList,\n propsLabel,\n propsIcon,\n children,\n ...rest\n }: NavGroupProps) => {\n const compact = NavCompactContext.inject(() => false);\n const iconOnly = () => compact() && icon != null;\n const activeItems = new Set<symbol>();\n // 组里有当前页:紧凑时分组的图标也高亮\n let hasCurrent = _state(false);\n NavGroupContext.provide({\n report(item, active) {\n if (active) activeItems.add(item);\n else activeItems.delete(item);\n hasCurrent = activeItems.size > 0;\n // 进入含当前页的分组时自动展开;离开时不自动收起(用户可能还想看)\n if (activeItems.size > 0) open = true;\n },\n });\n\n /** 紧凑时:只剩图标,悬停、聚焦时子项从右边弹出来(完整的文字,不再紧凑) */\n function renderFlyout() {\n return (\n <li {...mergeAttrs<'li'>({}, rest)}>\n <HoverCard\n placement=\"right-start\"\n delay={150}\n // 子项一直渲染:它们要报告自己是不是当前页,分组的图标才知道要不要高亮\n lazy={false}\n sx={navListStyles.flyout}\n trigger={(props) => (\n <ButtonBase\n {...mergePartProps<ButtonBaseProps>(\n {\n sx: [\n itemStyles.row,\n itemStyles.hoverable,\n navListStyles.row,\n navListStyles.compactRow,\n hasCurrent && [itemStyles.current, navListStyles.current],\n ],\n },\n propsTrigger,\n props as Partial<ButtonBaseProps>,\n )}\n data-state={hasCurrent ? 'active' : 'inactive'}\n >\n <Icon {...mergePartProps<IconProps>({ icon: icon! }, propsIcon)} />\n <span {...mergeAttrs<'span'>({ sx: visuallyHiddenStyles.hidden }, propsLabel)}>\n {label}\n </span>\n </ButtonBase>\n )}\n >\n <NavFlyoutContent label={label} propsList={propsList}>\n {children}\n </NavFlyoutContent>\n </HoverCard>\n </li>\n );\n }\n\n return () =>\n iconOnly() ? (\n renderFlyout()\n ) : (\n <li {...mergeAttrs<'li'>({}, rest)}>\n <Collapsible\n {...mergePartProps<CollapsibleProps>(\n {\n trigger: (props) => (\n <ButtonBase\n {...mergePartProps<ButtonBaseProps>(\n {\n sx: [\n itemStyles.row,\n itemStyles.hoverable,\n navListStyles.row,\n iconOnly() && navListStyles.compactRow,\n ],\n },\n propsTrigger,\n props,\n )}\n >\n {icon && <Icon {...mergePartProps<IconProps>({ icon }, propsIcon)} />}\n <span\n {...mergeAttrs<'span'>(\n { sx: [itemStyles.label, iconOnly() && visuallyHiddenStyles.hidden] },\n propsLabel,\n )}\n >\n {label}\n </span>\n {!iconOnly() && (\n <Icon\n icon={ChevronRight}\n flipInRtl\n sx={[navListStyles.chevron, open && navListStyles.chevronOpen]}\n />\n )}\n </ButtonBase>\n ),\n },\n propsContent,\n )}\n _open={open}\n >\n <FlexList\n {...mergePartProps<FlexProps<'ul'>>(\n {\n direction: 'column',\n gap: 'xs',\n sx: [navListStyles.nested, compact() && navListStyles.compactNested],\n },\n propsList,\n )}\n >\n {children}\n </FlexList>\n </Collapsible>\n </li>\n );\n },\n);\n\n/** 紧凑分组弹出来的内容:标题加完整的导航项(里面不再紧凑) */\nconst NavFlyoutContent = _component(\n ({\n label,\n propsList,\n children,\n }: {\n label: VNodeChild;\n propsList?: Partial<FlexProps<'ul'>>;\n children?: VNodeChild;\n }) => {\n NavCompactContext.provide(() => false);\n return () => (\n <>\n <span {...css.attrs(navListStyles.sectionLabel)}>{label}</span>\n <FlexList\n {...mergePartProps<FlexProps<'ul'>>({ direction: 'column', gap: 'xs' }, propsList)}\n >\n {children}\n </FlexList>\n </>\n );\n },\n);\n\n// ─────────────── NavSection ───────────────\n\n/** 未声明的属性落到外层 li 上 */\nexport interface NavSectionProps extends PartProps<'li'> {\n /** 小节标题,同时是这组链接的无障碍名称 */\n label: VNodeChild;\n /** 标题前的图标:只是标记、不能点;紧凑时标题只剩它 */\n icon?: IconData;\n /** 标题的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 标题图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 里面的列表(ul)的部件属性 */\n propsList?: Partial<FlexProps<'ul'>>;\n /** 小节里的 NavItem */\n children?: VNodeChild;\n}\n\n/** 带小标题的一组导航链接(li > 标题 + ul):一直展开,不能收起;要收起用 NavGroup */\nexport const NavSection = _component(\n ({ label, icon, propsLabel, propsIcon, propsList, children, ...rest }: NavSectionProps) => {\n const labelId = useId();\n const compact = NavCompactContext.inject(() => false);\n const iconOnly = () => compact() && icon != null;\n return () => (\n <li {...mergeAttrs<'li'>({ sx: navListStyles.section }, rest)}>\n <span\n {...mergeAttrs<'span'>(\n { sx: [navListStyles.sectionLabel, iconOnly() && navListStyles.compactSection] },\n propsLabel,\n )}\n >\n {icon && (\n <Icon\n {...mergePartProps<IconProps>({ icon, sx: navListStyles.sectionIcon }, propsIcon)}\n />\n )}\n <span id={labelId} {...css.attrs(iconOnly() && visuallyHiddenStyles.hidden)}>\n {label}\n </span>\n </span>\n <FlexList\n {...mergePartProps<FlexProps<'ul'>>({ direction: 'column', gap: 'xs' }, propsList, {\n 'aria-labelledby': labelId,\n })}\n >\n {children}\n </FlexList>\n </li>\n );\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NavList.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_createVNode","_mergeProps","_vtp_forwardChildren","_vtp_childrenProp","_vue_computed","_vtp_bindable","_vue_ref","_vtp_childrenStable","_Fragment"],"sources":["../../src/navigation/NavList.tsx"],"sourcesContent":["/**\n * 侧边导航,复合组件:NavList(nav > ul)> NavItem(链接)/ NavGroup(可展开的一组)/ NavSection(带小标题的一组,\n * 不能收起:文档站这类链接多、按主题分组的侧栏),里面再放 NavItem。\n * 当前页按路由适配的 isActive 判断(也可以用 active 指定),带 aria-current=\"page\" 与高亮;\n * 含当前页的分组自动展开。分组用 Collapsible(触发器带 aria-expanded / aria-controls)。\n *\n * <NavList aria-label=\"后台\">\n * <NavItem href=\"/\" icon={House}>概览</NavItem>\n * <NavGroup label=\"订单\" icon={Package}>\n * <NavItem href=\"/orders\">全部订单</NavItem>\n * <NavItem href=\"/orders/refunds\">退款</NavItem>\n * </NavGroup>\n * </NavList>\n *\n * 用 vue-router 时 vueRouterAdapter(router, { match: 'prefix' }) 能让 /orders 在 /orders/42 页面也高亮。\n *\n * 紧凑(compact):侧栏窄到只放得下图标时,各项只显示图标(文字留给读屏,悬停、聚焦时用 Tooltip 显示),\n * 小节标题换成它的图标(不能点);分组也只剩图标,悬停、聚焦时子项从右边弹出来(HoverCard,完整的文字,\n * Tab 进入),组里有当前页时图标高亮。AppShell 的抽屉式侧栏拖窄时自动进入(NavCompactContext),\n * 也可以直接写 <NavList compact>。\n *\n * NavItem 的 badge 是计数角标(待办、未读):展开时在文字后面,紧凑时是图标右上角的小圆点(读屏照样念出数目)。\n */\nimport { ChevronRight } from '@lucide/icons';\nimport { createContext, _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onBeforeUnmount, useId, watch, type VNodeChild } from 'vue';\nimport { ButtonBase, type ButtonBaseProps } from '../base/ButtonBase';\nimport { Badge } from '../base/Badge';\nimport { Icon, type IconData, type IconProps } from '../base/Icon';\nimport { Indicator } from '../base/Indicator';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { Collapsible, type CollapsibleProps } from '../display/Collapsible';\nimport { HoverCard } from '../overlay/HoverCard';\nimport { Tooltip, type TooltipTriggerProps } from '../overlay/Tooltip';\nimport { useLang } from '../config/context';\nimport { useRouterLink } from '../utils/dom/link';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { rippleHostStyles, useRipple } from '../utils/dom/ripple';\nimport { itemStyles } from '../utils/style/item-styles';\nimport { focusRingStyles } from '../utils/style/styles';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport { FlexList, type FlexProps } from '../layout/Flex';\nimport { t } from '../config/theme/tokens';\n\n/** 分组向里面的项要的信息:哪些项是当前页(有当前页时自动展开) */\nexport interface NavGroupState {\n /** 组内的一项报告自己是不是当前页(item 是这一项的标识) */\n report(item: symbol, active: boolean): void;\n}\n\n/** NavGroup 的上下文:组内的项据此缩进;不在组内时为 null */\nexport const NavGroupContext = createContext<NavGroupState | null>('NavGroup');\n\n/** 导航是不是紧凑(只显示图标):AppShell 按侧栏宽度提供,NavList 的 compact 可以覆盖 */\nexport const NavCompactContext = createContext<() => boolean>('NavCompact');\n\n/** NavList 的样式:nested、row、current、disabled、chevron、section、sectionLabel 等 */\nexport const navListStyles = css.create({\n nested: { paddingInlineStart: '_lg', paddingTop: '_xs' },\n // 链接与分组的触发器共用:列表行(itemStyles)之上,导航项更宽松、字重更重,平时是次要颜色\n row: {\n paddingInline: '_md',\n borderRadius: '_md',\n color: { default: '_textMuted', ':hover': '_text' },\n fontWeight: '_medium',\n },\n // 当前页的颜色来自 itemStyles.current;悬停时也保持品牌色\n current: { color: { default: '_accentText', ':hover': '_accentText' } },\n disabled: { pointerEvents: 'none' },\n chevron: { transition: `transform ${t.durations.md} ${t.easings.standard}` },\n chevronOpen: { transform: 'rotate(90deg)' },\n // 小节之间留出间隔,第一节贴着顶部\n // 多栏排版(AppShell 的上下抽屉)时一个小节不被拆到两栏\n section: {\n display: 'flex',\n flexDirection: 'column',\n gap: '_xs',\n marginBlockStart: { default: '_lg', ':first-child': 0 },\n breakInside: 'avoid',\n },\n // 标题行的内边距、图标与间距和链接行同一套(随所在字号),图标与文字才和下面的项上下对齐;只有文字小一档、加粗\n sectionLabel: {\n display: 'flex',\n alignItems: 'center',\n gap: '_sm',\n paddingBlock: '_xs',\n paddingInline: '_md',\n color: '_text',\n },\n sectionText: { fontSize: '_sm', fontWeight: '_semibold', letterSpacing: '_wide' },\n // 小节标题的图标只是标记,比链接的图标淡\n sectionIcon: { color: '_textMuted', flexShrink: 0 },\n // 紧凑:图标居中;小节标题只剩图标,上面一条细线与上一节隔开\n compactRow: { justifyContent: 'center', paddingInline: 0 },\n compactSection: {\n justifyContent: 'center',\n paddingInline: 0,\n paddingBlockStart: '_sm',\n borderBlockStartWidth: '_xs',\n borderBlockStartStyle: 'solid',\n borderBlockStartColor: '_borderMuted',\n },\n compactNested: { paddingInlineStart: 0 },\n // 紧凑分组弹出的卡片:比侧栏宽,放得下完整的文字\n flyout: { padding: '_xs', minWidth: '12em' },\n});\n\n// ─────────────── NavList ───────────────\n\n/** 未声明的属性落到 nav 上;aria-label 是导航的名称 */\nexport interface NavListProps extends PartProps<'nav'> {\n /** 紧凑:只显示图标;不写时跟随所在的 AppShell 侧栏(拖窄时紧凑) */\n compact?: boolean;\n /** 列表(ul)的部件属性 */\n propsList?: Partial<FlexProps<'ul'>>;\n children?: VNodeChild;\n}\n\n/** 侧边导航(nav > ul),里面放 NavItem 与 NavGroup */\nexport const NavList = _component(({ compact, propsList, children, ...rest }: NavListProps) => {\n const inherited = NavCompactContext.inject(() => false);\n const isCompact = () => compact ?? inherited();\n NavCompactContext.provide(isCompact);\n return () => (\n <nav {...mergeAttrs<'nav'>({}, rest)} data-compact={isCompact() || undefined}>\n <FlexList {...mergePartProps<FlexProps<'ul'>>({ direction: 'column', gap: 'xs' }, propsList)}>\n {children}\n </FlexList>\n </nav>\n );\n});\n\n// ─────────────── NavItem ───────────────\n\n/** 地址与当前页由组件管理 */\nexport type NavItemManaged = 'href' | 'aria-current';\n\n/** 未声明的属性落到链接(a)上 */\nexport interface NavItemProps extends PartProps<'a', NavItemManaged> {\n /** 链接地址 */\n href: string;\n /** 文字前的图标 */\n icon?: IconData;\n /** 是否是当前页;不写时按路由适配的 isActive 判断 */\n active?: boolean;\n /** 不可用:不能点、不能聚焦 */\n disabled?: boolean;\n /** 文字后面的内容(自定义的标记);只是计数时用 badge */\n end?: VNodeChild;\n /** 计数角标(待办、未读):展开时是文字后面的 Badge,紧凑时是图标右上角的小圆点;0 不显示 */\n badge?: number;\n /** 角标的色调,默认 danger */\n badgeTone?: StatusTone;\n /** 按下时的波纹;不写时沿用全局配置 */\n ripple?: boolean;\n /** 外层 li 的部件属性 */\n propsItem?: PartProps<'li'>;\n /** 图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n children?: VNodeChild;\n}\n\n/** 导航项(li > a):当前页高亮并带 aria-current=\"page\" */\nexport const NavItem = _component(\n ({\n href,\n icon,\n active,\n disabled = false,\n end,\n badge = 0,\n badgeTone = 'danger',\n ripple,\n propsItem,\n propsIcon,\n propsLabel,\n children,\n ...rest\n }: NavItemProps) => {\n const lang = useLang();\n const router = useRouterLink();\n const group = NavGroupContext.inject(null);\n const rippleHandlers = useRipple(() => ripple);\n const current = _derived(active ?? router.isActive(href));\n const compact = NavCompactContext.inject(() => false);\n const id = Symbol('NavItem');\n\n // 告诉所在的分组自己是不是当前页(分组据此自动展开)\n if (group) {\n watch(\n () => current,\n (value) => group.report(id, value),\n { immediate: true },\n );\n onBeforeUnmount(() => group.report(id, false));\n }\n\n const iconOnly = () => compact() && icon != null;\n // tooltip:只剩图标时 Tooltip 给触发器的属性(定位用的 ref、悬停与聚焦的事件)\n const link = (tooltip?: TooltipTriggerProps) => (\n <a\n {...mergeAttrs<'a'>(\n {\n ...tooltip,\n sx: [\n itemStyles.row,\n itemStyles.hoverable,\n navListStyles.row,\n focusRingStyles.visible,\n rippleHostStyles.host,\n iconOnly() && navListStyles.compactRow,\n current && [itemStyles.current, navListStyles.current],\n disabled && [itemStyles.disabled, navListStyles.disabled],\n ],\n },\n rest,\n {\n href: disabled ? undefined : router.href(href),\n 'aria-current': current ? 'page' : undefined,\n 'aria-disabled': disabled || undefined,\n // 使用方的 onClick 先执行,preventDefault 可以拦下路由跳转\n onClick: (event: MouseEvent) => router.onClick(event, href),\n ...rippleHandlers,\n },\n )}\n data-state={current ? 'active' : 'inactive'}\n >\n {icon &&\n (iconOnly() && badge > 0 ? (\n // 紧凑:图标右上角一个小圆点(图标太小,叠不下数字);读屏照样念出数目\n <Indicator dot tone={badgeTone} label={lang.indicatorCount(badge)}>\n <Icon {...mergePartProps<IconProps>({ icon }, propsIcon)} />\n </Indicator>\n ) : (\n <Icon {...mergePartProps<IconProps>({ icon }, propsIcon)} />\n ))}\n <span\n {...mergeAttrs<'span'>(\n { sx: [itemStyles.label, iconOnly() && visuallyHiddenStyles.hidden] },\n propsLabel,\n )}\n >\n {children}\n </span>\n {!iconOnly() && end}\n {!iconOnly() && badge > 0 && (\n <Badge size=\"xs\" variant=\"solid\" tone={badgeTone} radius=\"full\">\n {badge > 99 ? '99+' : badge}\n </Badge>\n )}\n </a>\n );\n\n return () => (\n <li {...mergeAttrs<'li'>({}, propsItem)}>\n {iconOnly() ? (\n // 只剩图标:名称在读屏的文字里,看的人悬停、聚焦时从提示里读\n <Tooltip placement=\"right\" delay={200} trigger={link}>\n {children}\n </Tooltip>\n ) : (\n link()\n )}\n </li>\n );\n },\n);\n\n// ─────────────── NavGroup ───────────────\n\n/** 未声明的属性落到外层 li 上 */\nexport interface NavGroupProps extends PartProps<'li'> {\n /** 分组标题 */\n label: VNodeChild;\n /** 标题前的图标 */\n icon?: IconData;\n /** 是否展开:父级写 _open={x};含当前页时自动展开 */\n _open?: boolean;\n /** 标题按钮的部件属性 */\n propsTrigger?: Omit<Partial<ButtonBaseProps>, 'aria-expanded' | 'aria-controls'>;\n /** 展开区(Collapsible)的部件属性 */\n propsContent?: Partial<CollapsibleProps>;\n /** 里面的列表(ul)的部件属性 */\n propsList?: Partial<FlexProps<'ul'>>;\n /** 标题文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 标题图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n children?: VNodeChild;\n}\n\n/** 可展开的导航分组(li > 按钮 + 子列表) */\nexport const NavGroup = _component(\n ({\n label,\n icon,\n _open: open = _bindable(false),\n propsTrigger,\n propsContent,\n propsList,\n propsLabel,\n propsIcon,\n children,\n ...rest\n }: NavGroupProps) => {\n const compact = NavCompactContext.inject(() => false);\n const iconOnly = () => compact() && icon != null;\n const activeItems = new Set<symbol>();\n // 组里有当前页:紧凑时分组的图标也高亮\n let hasCurrent = _state(false);\n NavGroupContext.provide({\n report(item, active) {\n if (active) activeItems.add(item);\n else activeItems.delete(item);\n hasCurrent = activeItems.size > 0;\n // 进入含当前页的分组时自动展开;离开时不自动收起(用户可能还想看)\n if (activeItems.size > 0) open = true;\n },\n });\n\n /** 紧凑时:只剩图标,悬停、聚焦时子项从右边弹出来(完整的文字,不再紧凑) */\n function renderFlyout() {\n return (\n <li {...mergeAttrs<'li'>({}, rest)}>\n <HoverCard\n placement=\"right-start\"\n delay={150}\n // 子项一直渲染:它们要报告自己是不是当前页,分组的图标才知道要不要高亮\n lazy={false}\n sx={navListStyles.flyout}\n trigger={(props) => (\n <ButtonBase\n {...mergePartProps<ButtonBaseProps>(\n {\n sx: [\n itemStyles.row,\n itemStyles.hoverable,\n navListStyles.row,\n navListStyles.compactRow,\n hasCurrent && [itemStyles.current, navListStyles.current],\n ],\n },\n propsTrigger,\n props as Partial<ButtonBaseProps>,\n )}\n data-state={hasCurrent ? 'active' : 'inactive'}\n >\n <Icon {...mergePartProps<IconProps>({ icon: icon! }, propsIcon)} />\n <span {...mergeAttrs<'span'>({ sx: visuallyHiddenStyles.hidden }, propsLabel)}>\n {label}\n </span>\n </ButtonBase>\n )}\n >\n <NavFlyoutContent label={label} propsList={propsList}>\n {children}\n </NavFlyoutContent>\n </HoverCard>\n </li>\n );\n }\n\n return () =>\n iconOnly() ? (\n renderFlyout()\n ) : (\n <li {...mergeAttrs<'li'>({}, rest)}>\n <Collapsible\n {...mergePartProps<CollapsibleProps>(\n {\n trigger: (props) => (\n <ButtonBase\n {...mergePartProps<ButtonBaseProps>(\n {\n sx: [\n itemStyles.row,\n itemStyles.hoverable,\n navListStyles.row,\n iconOnly() && navListStyles.compactRow,\n ],\n },\n propsTrigger,\n props,\n )}\n >\n {icon && <Icon {...mergePartProps<IconProps>({ icon }, propsIcon)} />}\n <span\n {...mergeAttrs<'span'>(\n { sx: [itemStyles.label, iconOnly() && visuallyHiddenStyles.hidden] },\n propsLabel,\n )}\n >\n {label}\n </span>\n {!iconOnly() && (\n <Icon\n icon={ChevronRight}\n flipInRtl\n sx={[navListStyles.chevron, open && navListStyles.chevronOpen]}\n />\n )}\n </ButtonBase>\n ),\n },\n propsContent,\n )}\n _open={open}\n >\n <FlexList\n {...mergePartProps<FlexProps<'ul'>>(\n {\n direction: 'column',\n gap: 'xs',\n sx: [navListStyles.nested, compact() && navListStyles.compactNested],\n },\n propsList,\n )}\n >\n {children}\n </FlexList>\n </Collapsible>\n </li>\n );\n },\n);\n\n/** 紧凑分组弹出来的内容:标题加完整的导航项(里面不再紧凑) */\nconst NavFlyoutContent = _component(\n ({\n label,\n propsList,\n children,\n }: {\n label: VNodeChild;\n propsList?: Partial<FlexProps<'ul'>>;\n children?: VNodeChild;\n }) => {\n NavCompactContext.provide(() => false);\n return () => (\n <>\n <span {...css.attrs(navListStyles.sectionLabel)}>{label}</span>\n <FlexList\n {...mergePartProps<FlexProps<'ul'>>({ direction: 'column', gap: 'xs' }, propsList)}\n >\n {children}\n </FlexList>\n </>\n );\n },\n);\n\n// ─────────────── NavSection ───────────────\n\n/** 未声明的属性落到外层 li 上 */\nexport interface NavSectionProps extends PartProps<'li'> {\n /** 小节标题,同时是这组链接的无障碍名称 */\n label: VNodeChild;\n /** 标题前的图标:只是标记、不能点;紧凑时标题只剩它 */\n icon?: IconData;\n /** 标题的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 标题图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 里面的列表(ul)的部件属性 */\n propsList?: Partial<FlexProps<'ul'>>;\n /** 小节里的 NavItem */\n children?: VNodeChild;\n}\n\n/** 带小标题的一组导航链接(li > 标题 + ul):一直展开,不能收起;要收起用 NavGroup */\nexport const NavSection = _component(\n ({ label, icon, propsLabel, propsIcon, propsList, children, ...rest }: NavSectionProps) => {\n const labelId = useId();\n const compact = NavCompactContext.inject(() => false);\n const iconOnly = () => compact() && icon != null;\n return () => (\n <li {...mergeAttrs<'li'>({ sx: navListStyles.section }, rest)}>\n <span\n {...mergeAttrs<'span'>(\n { sx: [navListStyles.sectionLabel, iconOnly() && navListStyles.compactSection] },\n propsLabel,\n )}\n >\n {icon && (\n <Icon\n {...mergePartProps<IconProps>({ icon, sx: navListStyles.sectionIcon }, propsIcon)}\n />\n )}\n <span\n id={labelId}\n {...css.attrs(navListStyles.sectionText, iconOnly() && visuallyHiddenStyles.hidden)}\n >\n {label}\n </span>\n </span>\n <FlexList\n {...mergePartProps<FlexProps<'ul'>>({ direction: 'column', gap: 'xs' }, propsList, {\n 'aria-labelledby': labelId,\n })}\n >\n {children}\n </FlexList>\n </li>\n );\n },\n);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { NavBarItem } from './NavBar';
|
|
2
|
+
import { type NavListProps } from './NavList';
|
|
3
|
+
/** 菜单树的一项:字段同 NavBarItem(同一份菜单数据可以同时给顶部的 NavBar 和侧栏的 NavMenu),多层嵌套 */
|
|
4
|
+
export interface NavMenuItem extends Omit<NavBarItem, 'children'> {
|
|
5
|
+
/** 同一层里唯一的标识(列表的 key),默认取 href,没有 href 时取 label */
|
|
6
|
+
key?: string;
|
|
7
|
+
/** 是否是当前页;不写时按路由适配判断 */
|
|
8
|
+
active?: boolean;
|
|
9
|
+
/** 子项:有可显示的子项时这一项是一组 */
|
|
10
|
+
children?: readonly NavMenuItem[];
|
|
11
|
+
}
|
|
12
|
+
/** 顶层有子项的项怎么显示:section 带小标题、一直展开;group 可收起 */
|
|
13
|
+
export interface NavMenuTopLevels {
|
|
14
|
+
/** 带小标题的小节,一直展开(默认) */
|
|
15
|
+
section: unknown;
|
|
16
|
+
/** 可收起的分组 */
|
|
17
|
+
group: unknown;
|
|
18
|
+
}
|
|
19
|
+
/** 未声明的属性落到 nav 上;aria-label 是导航的名称 */
|
|
20
|
+
export interface NavMenuProps extends Omit<NavListProps, 'children'> {
|
|
21
|
+
/** 菜单树 */
|
|
22
|
+
items: readonly NavMenuItem[];
|
|
23
|
+
/** 顶层有子项的项怎么显示,默认 section */
|
|
24
|
+
topLevel?: keyof NavMenuTopLevels;
|
|
25
|
+
}
|
|
26
|
+
/** 数据驱动的侧边导航:菜单树 → NavList、NavSection、NavGroup、NavItem */
|
|
27
|
+
export declare const NavMenu: import("@zerodep-dev/vue-tsx-pro-tsx").TsxComponent<NavMenuProps>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { NavGroup, NavItem, NavList, NavSection } from "./NavList.js";
|
|
2
|
+
import { createVNode, isVNode } from "vue";
|
|
3
|
+
import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
4
|
+
//#region src/navigation/NavMenu.tsx
|
|
5
|
+
/** 菜单树的一项:字段同 NavBarItem(同一份菜单数据可以同时给顶部的 NavBar 和侧栏的 NavMenu),多层嵌套 */
|
|
6
|
+
/** 顶层有子项的项怎么显示:section 带小标题、一直展开;group 可收起 */
|
|
7
|
+
/** 未声明的属性落到 nav 上;aria-label 是导航的名称 */
|
|
8
|
+
function _isSlot(s) {
|
|
9
|
+
return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
|
|
10
|
+
}
|
|
11
|
+
/** 这一项(或它的子孙)有没有能显示的页面:没有的目录不画 */
|
|
12
|
+
var visible = (item) => item.children?.length ? item.children.some(visible) : item.href !== void 0;
|
|
13
|
+
var keyOf = (item) => item.key ?? item.href ?? item.label;
|
|
14
|
+
function renderLink(item) {
|
|
15
|
+
return createVNode(NavItem, {
|
|
16
|
+
"key": keyOf(item),
|
|
17
|
+
"href": item.href,
|
|
18
|
+
"icon": item.icon,
|
|
19
|
+
"badge": item.badge,
|
|
20
|
+
"disabled": item.disabled,
|
|
21
|
+
"active": item.active
|
|
22
|
+
}, { default: () => [item.label] });
|
|
23
|
+
}
|
|
24
|
+
function renderNode(item, depth, topLevel) {
|
|
25
|
+
if (!visible(item)) return null;
|
|
26
|
+
if (!item.children?.length) return renderLink(item);
|
|
27
|
+
const children = item.children.map((child) => renderNode(child, depth + 1, topLevel));
|
|
28
|
+
return depth === 0 && topLevel === "section" ? createVNode(NavSection, {
|
|
29
|
+
"key": keyOf(item),
|
|
30
|
+
"label": item.label,
|
|
31
|
+
"icon": item.icon
|
|
32
|
+
}, _isSlot(children) ? children : { default: () => [children] }) : createVNode(NavGroup, {
|
|
33
|
+
"key": keyOf(item),
|
|
34
|
+
"label": item.label,
|
|
35
|
+
"icon": item.icon
|
|
36
|
+
}, _isSlot(children) ? children : { default: () => [children] });
|
|
37
|
+
}
|
|
38
|
+
/** 数据驱动的侧边导航:菜单树 → NavList、NavSection、NavGroup、NavItem */
|
|
39
|
+
var NavMenu = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
40
|
+
const items = readonlyProp(_props, "items");
|
|
41
|
+
const topLevel = readonlyProp(_props, "topLevel", "section");
|
|
42
|
+
const rest = restProps(_props, _ctx, true);
|
|
43
|
+
return () => createVNode(NavList, mergeJsxProps(rest, { "key": "__site0" }), {
|
|
44
|
+
default: () => [items.value.map((item) => renderNode(item, 0, topLevel.value))],
|
|
45
|
+
$stable: true
|
|
46
|
+
});
|
|
47
|
+
}, {
|
|
48
|
+
name: "NavMenu",
|
|
49
|
+
props: ["items", "topLevel"]
|
|
50
|
+
});
|
|
51
|
+
//#endregion
|
|
52
|
+
export { NavMenu };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=NavMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NavMenu.js","names":["_isVNode","_createVNode","_vtp_readonlyProp","_vtp_restProps","_mergeProps"],"sources":["../../src/navigation/NavMenu.tsx"],"sourcesContent":["/**\n * 数据驱动的侧边导航:菜单是一棵树(后端按角色返回、或配置文件里写的),直接交给 NavMenu 渲染,不用自己递归拼 NavItem。\n *\n * <NavMenu\n * aria-label=\"主菜单\"\n * items={[\n * { label: '首页', href: '/', icon: House },\n * { label: '降本管理', icon: Boxes, children: [\n * { label: '降本项目', href: '/projects', badge: 3 },\n * { label: '台账', href: '/ledger' },\n * ] },\n * ]}\n * />\n *\n * 有 children 的项是一组:顶层的显示成带小标题、一直展开的小节(topLevel=\"section\",默认)或可收起的分组(topLevel=\"group\"),\n * 更深的层级都是可收起的分组(含当前页的组自动展开);没有 children 的项是链接。没有 href 又没有可显示子项的项不显示\n * (后端返回的目录下没有该用户能看的页面时,目录自然消失)。当前页按路由适配判断(NavItem 的 active),也可以逐项写 active。\n * 紧凑与抽屉里的表现同 NavList,由所在的 AppShell 决定。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport type { VNodeChild } from 'vue';\nimport type { NavBarItem } from './NavBar';\nimport { NavGroup, NavItem, NavList, NavSection, type NavListProps } from './NavList';\n\n/** 菜单树的一项:字段同 NavBarItem(同一份菜单数据可以同时给顶部的 NavBar 和侧栏的 NavMenu),多层嵌套 */\nexport interface NavMenuItem extends Omit<NavBarItem, 'children'> {\n /** 同一层里唯一的标识(列表的 key),默认取 href,没有 href 时取 label */\n key?: string;\n /** 是否是当前页;不写时按路由适配判断 */\n active?: boolean;\n /** 子项:有可显示的子项时这一项是一组 */\n children?: readonly NavMenuItem[];\n}\n\n/** 顶层有子项的项怎么显示:section 带小标题、一直展开;group 可收起 */\nexport interface NavMenuTopLevels {\n /** 带小标题的小节,一直展开(默认) */\n section: unknown;\n /** 可收起的分组 */\n group: unknown;\n}\n\n/** 未声明的属性落到 nav 上;aria-label 是导航的名称 */\nexport interface NavMenuProps extends Omit<NavListProps, 'children'> {\n /** 菜单树 */\n items: readonly NavMenuItem[];\n /** 顶层有子项的项怎么显示,默认 section */\n topLevel?: keyof NavMenuTopLevels;\n}\n\n/** 这一项(或它的子孙)有没有能显示的页面:没有的目录不画 */\nconst visible = (item: NavMenuItem): boolean =>\n item.children?.length ? item.children.some(visible) : item.href !== undefined;\n\nconst keyOf = (item: NavMenuItem) => item.key ?? item.href ?? item.label;\n\nfunction renderLink(item: NavMenuItem): VNodeChild {\n return (\n <NavItem\n key={keyOf(item)}\n href={item.href!}\n icon={item.icon}\n badge={item.badge}\n disabled={item.disabled}\n active={item.active}\n >\n {item.label}\n </NavItem>\n );\n}\n\nfunction renderNode(\n item: NavMenuItem,\n depth: number,\n topLevel: keyof NavMenuTopLevels,\n): VNodeChild {\n if (!visible(item)) return null;\n if (!item.children?.length) return renderLink(item);\n const children = item.children.map((child) => renderNode(child, depth + 1, topLevel));\n return depth === 0 && topLevel === 'section' ? (\n <NavSection key={keyOf(item)} label={item.label} icon={item.icon}>\n {children}\n </NavSection>\n ) : (\n <NavGroup key={keyOf(item)} label={item.label} icon={item.icon}>\n {children}\n </NavGroup>\n );\n}\n\n/** 数据驱动的侧边导航:菜单树 → NavList、NavSection、NavGroup、NavItem */\nexport const NavMenu = _component(\n ({ items, topLevel = 'section', ...rest }: NavMenuProps) =>\n () => <NavList {...rest}>{items.map((item) => renderNode(item, 0, topLevel))}</NavList>,\n);\n"],"mappings":";;;;;;;AA0CA,SAAA,QAAA,GAAA;CAAA,OAAA,OAAA,MAAA,cAAA,OAAA,UAAA,SAAA,KAAA,CAAA,MAAA,qBAAA,CAAAA,QAAA,CAAA;AAAA;;AASA,IAAM,WAAW,SACf,KAAK,UAAU,SAAS,KAAK,SAAS,KAAK,OAAO,IAAI,KAAK,SAAS,KAAA;AAEtE,IAAM,SAAS,SAAsB,KAAK,OAAO,KAAK,QAAQ,KAAK;AAEnE,SAAS,WAAW,MAA+B;CACjD,OAAAC,YAAA,SAAA;EAAA,OAES,MAAM,IAAI;EAAC,QACV,KAAK;EAAI,QACT,KAAK;EAAI,SACR,KAAK;EAAK,YACP,KAAK;EAAQ,UACf,KAAK;CAAM,GAAA,EAAA,eAAA,CAElB,KAAK,KAAK,EAAA,CAAA;AAGjB;AAEA,SAAS,WACP,MACA,OACA,UACY;CACZ,IAAI,CAAC,QAAQ,IAAI,GAAG,OAAO;CAC3B,IAAI,CAAC,KAAK,UAAU,QAAQ,OAAO,WAAW,IAAI;CAClD,MAAM,WAAW,KAAK,SAAS,KAAK,UAAU,WAAW,OAAO,QAAQ,GAAG,QAAQ,CAAC;CACpF,OAAO,UAAU,KAAK,aAAa,YAASA,YAAA,YAAA;EAAA,OACzB,MAAM,IAAI;EAAC,SAAS,KAAK;EAAK,QAAQ,KAAK;CAAI,GAAA,QAC7D,QAAQ,IAAR,WAAQ,EAAA,eAAA,CAAR,QAAQ,EAAA,CAAA,IAAAA,YAAA,UAAA;EAAA,OAGI,MAAM,IAAI;EAAC,SAAS,KAAK;EAAK,QAAQ,KAAK;CAAI,GAAA,QAC3D,QAAQ,IAAR,WAAQ,EAAA,eAAA,CAAR,QAAQ,EAAA,CAAA;AAGf;;AAGA,IAAa,UAAU,0BACrB,QAAA,SAAA;CAAA,MAAA,QAAAC,aAAA,QAAA,OAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,YAAqB,SAAS;CAAA,MAAK,OAAIC,UAAA,QAAA,MAAA,IAAA;CAAA,aACrCF,YAAA,SAAAG,cAAmB,MAAI,EAAA,OAAA,UAAA,CAAA,GAAA;EAAA,eAAA,CAAG,MAAA,MAAM,KAAK,SAAS,WAAW,MAAM,GAAC,SAAA,KAAU,CAAC,CAAC;EAAA,SAAA;CAAA,CAAA;AAAW,GAAA;CAAA,MAAA;CAAA,OAAA,CAAA,SAAA,UAAA;AAAA,CAC3F"}
|
|
@@ -3,8 +3,8 @@ import { useLang } from "../config/context.js";
|
|
|
3
3
|
import { mergeAttrs, mergePartProps } from "../utils/props.js";
|
|
4
4
|
import { fontSizeStyles } from "../utils/style/typography.js";
|
|
5
5
|
import { NumberField } from "../input/NumberField.js";
|
|
6
|
-
import { createVNode,
|
|
7
|
-
import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
6
|
+
import { createVNode, ref, watch } from "vue";
|
|
7
|
+
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
8
8
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
9
9
|
//#region src/navigation/PageJump.tsx
|
|
10
10
|
/** 未声明的属性落到外层 div 上 */
|
|
@@ -44,7 +44,7 @@ var PageJump = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
44
44
|
sx: pageJumpStyles.text,
|
|
45
45
|
"aria-hidden": true
|
|
46
46
|
}, propsBefore.value), [lang.pageJumpBefore]),
|
|
47
|
-
createVNode(NumberField,
|
|
47
|
+
createVNode(NumberField, mergeJsxProps(mergePartProps({
|
|
48
48
|
"aria-label": lang.pageJumpLabel,
|
|
49
49
|
min: 1,
|
|
50
50
|
max: Math.max(1, pageCount.value),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageJump.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/navigation/PageJump.tsx"],"sourcesContent":["/**\n * 跳页:分页的配套组件,“跳至 [ ] 页”,回车或失焦后跳过去(夹在 1–pageCount),输入框随后清空。\n *\n * <PageJump _page={page} pageCount={32} />\n *\n * 基于 NumberField:未声明的属性落到外层 div 上;输入框用 propsInput。读屏念输入框的名称(语言包的“跳到第几页”),\n * 前后的“跳至”“页”只是视觉上的提示。部件:Root(div)、Before、Input(NumberField)、After。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { watch } from 'vue';\nimport { useLang } from '../config/context';\nimport { NumberField, type NumberFieldProps } from '../input/NumberField';\nimport { clamp } from '../utils/data/number';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface PageJumpProps extends PartProps<'div'> {\n /** 当前页:父级写 _page={page},跳页时写回 */\n _page?: number;\n /** 总页数:输入的页码夹在 1–pageCount */\n pageCount: number;\n /** 字号档位,默认 sm(同 Pagination) */\n size?: TextSize;\n /** 输入框前文字的部件属性 */\n propsBefore?: PartProps<'span'>;\n /** 输入框(NumberField)的部件属性 */\n propsInput?: Partial<NumberFieldProps>;\n /** 输入框后文字的部件属性 */\n propsAfter?: PartProps<'span'>;\n}\n\n/** PageJump 的样式:root、input、text */\nexport const pageJumpStyles = css.create({\n root: { display: 'inline-flex', alignItems: 'center', gap: '_sm' },\n input: { width: '4.5em' },\n text: { color: '_textMuted', whiteSpace: 'nowrap' },\n});\n\n/** 跳页:输入页码后跳过去 */\nexport const PageJump = _component(\n ({\n _page: page = _bindable(1),\n pageCount,\n size = 'sm',\n propsBefore,\n propsInput,\n propsAfter,\n ...rest\n }: PageJumpProps) => {\n const lang = useLang();\n // 输入框只在跳之前暂存页码,跳完清空\n let draft = _state<number | null>(null);\n watch(\n () => draft,\n (target) => {\n if (target == null) return;\n const next = clamp(Math.round(target), 1, Math.max(1, pageCount));\n if (next !== page) page = next;\n draft = null;\n },\n );\n\n return () => (\n <div {...mergeAttrs<'div'>({ sx: [pageJumpStyles.root, fontSizeStyles[size]] }, rest)}>\n {lang.pageJumpBefore && (\n <span\n {...mergeAttrs<'span'>({ sx: pageJumpStyles.text, 'aria-hidden': true }, propsBefore)}\n >\n {lang.pageJumpBefore}\n </span>\n )}\n <NumberField\n {...mergePartProps<NumberFieldProps>(\n {\n 'aria-label': lang.pageJumpLabel,\n min: 1,\n max: Math.max(1, pageCount),\n stepper: false,\n propsRoot: { sx: pageJumpStyles.input },\n },\n propsInput,\n )}\n _value={draft}\n />\n {lang.pageJumpAfter && (\n <span\n {...mergeAttrs<'span'>({ sx: pageJumpStyles.text, 'aria-hidden': true }, propsAfter)}\n >\n {lang.pageJumpAfter}\n </span>\n )}\n </div>\n );\n },\n);\n"],"mappings":";;;;;;;;;;;AAkCA,IAAa,iBAAiB,IAAI,OAAO;CACvC,MAAM;EAAE,SAAS;EAAe,YAAY;EAAU,KAAK;CAAM;CACjE,OAAO,EAAE,OAAO,QAAQ;CACxB,MAAM;EAAE,OAAO;EAAc,YAAY;CAAS;AACpD,CAAC;;AAGD,IAAa,WAAW,0BACtB,QAAA,SAQqB;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,OAAAA,SAAA,QAAA,eAPK,GAAC,KAAA,IAAA;CAAA,MAAA,YAAAC,aAAA,QAAA,WAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,QAElB,IAAI;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAIR,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,OAAO,QAAQ;CAErB,IAAI,QAAKC,IAAyB,IAAI;CACtC,YACE,MAAA,QACC,WAAW;EACV,IAAI,UAAU,MAAM;EACpB,MAAM,OAAO,MAAM,KAAK,MAAM,MAAM,GAAG,GAAG,KAAK,IAAI,GAAC,UAAA,KAAW,CAAC;EAChE,IAAI,SAAI,KAAA,OAAW,KAAA,QAAO;EAC1B,MAAA,QAAQ;CACV,CACF;CAEA,aAAOC,YAAA,OACI,WAAkB,EAAE,IAAI,CAAC,eAAe,MAAM,eAAc,KAAA,MAAM,EAAE,GAAG,IAAI,GAAC;EAClF,KAAK,kBAAcA,YAAA,QAEZ,WAAmB;GAAE,IAAI,eAAe;GAAM,eAAe;EAAK,GAAC,YAAA,KAAa,GAAC,CAEpF,KAAK,cAAc,CAAA;EAEvBA,YAAA,aAAAC,
|
|
1
|
+
{"version":3,"file":"PageJump.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/navigation/PageJump.tsx"],"sourcesContent":["/**\n * 跳页:分页的配套组件,“跳至 [ ] 页”,回车或失焦后跳过去(夹在 1–pageCount),输入框随后清空。\n *\n * <PageJump _page={page} pageCount={32} />\n *\n * 基于 NumberField:未声明的属性落到外层 div 上;输入框用 propsInput。读屏念输入框的名称(语言包的“跳到第几页”),\n * 前后的“跳至”“页”只是视觉上的提示。部件:Root(div)、Before、Input(NumberField)、After。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { watch } from 'vue';\nimport { useLang } from '../config/context';\nimport { NumberField, type NumberFieldProps } from '../input/NumberField';\nimport { clamp } from '../utils/data/number';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\n\n/** 未声明的属性落到外层 div 上 */\nexport interface PageJumpProps extends PartProps<'div'> {\n /** 当前页:父级写 _page={page},跳页时写回 */\n _page?: number;\n /** 总页数:输入的页码夹在 1–pageCount */\n pageCount: number;\n /** 字号档位,默认 sm(同 Pagination) */\n size?: TextSize;\n /** 输入框前文字的部件属性 */\n propsBefore?: PartProps<'span'>;\n /** 输入框(NumberField)的部件属性 */\n propsInput?: Partial<NumberFieldProps>;\n /** 输入框后文字的部件属性 */\n propsAfter?: PartProps<'span'>;\n}\n\n/** PageJump 的样式:root、input、text */\nexport const pageJumpStyles = css.create({\n root: { display: 'inline-flex', alignItems: 'center', gap: '_sm' },\n input: { width: '4.5em' },\n text: { color: '_textMuted', whiteSpace: 'nowrap' },\n});\n\n/** 跳页:输入页码后跳过去 */\nexport const PageJump = _component(\n ({\n _page: page = _bindable(1),\n pageCount,\n size = 'sm',\n propsBefore,\n propsInput,\n propsAfter,\n ...rest\n }: PageJumpProps) => {\n const lang = useLang();\n // 输入框只在跳之前暂存页码,跳完清空\n let draft = _state<number | null>(null);\n watch(\n () => draft,\n (target) => {\n if (target == null) return;\n const next = clamp(Math.round(target), 1, Math.max(1, pageCount));\n if (next !== page) page = next;\n draft = null;\n },\n );\n\n return () => (\n <div {...mergeAttrs<'div'>({ sx: [pageJumpStyles.root, fontSizeStyles[size]] }, rest)}>\n {lang.pageJumpBefore && (\n <span\n {...mergeAttrs<'span'>({ sx: pageJumpStyles.text, 'aria-hidden': true }, propsBefore)}\n >\n {lang.pageJumpBefore}\n </span>\n )}\n <NumberField\n {...mergePartProps<NumberFieldProps>(\n {\n 'aria-label': lang.pageJumpLabel,\n min: 1,\n max: Math.max(1, pageCount),\n stepper: false,\n propsRoot: { sx: pageJumpStyles.input },\n },\n propsInput,\n )}\n _value={draft}\n />\n {lang.pageJumpAfter && (\n <span\n {...mergeAttrs<'span'>({ sx: pageJumpStyles.text, 'aria-hidden': true }, propsAfter)}\n >\n {lang.pageJumpAfter}\n </span>\n )}\n </div>\n );\n },\n);\n"],"mappings":";;;;;;;;;;;AAkCA,IAAa,iBAAiB,IAAI,OAAO;CACvC,MAAM;EAAE,SAAS;EAAe,YAAY;EAAU,KAAK;CAAM;CACjE,OAAO,EAAE,OAAO,QAAQ;CACxB,MAAM;EAAE,OAAO;EAAc,YAAY;CAAS;AACpD,CAAC;;AAGD,IAAa,WAAW,0BACtB,QAAA,SAQqB;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,OAAAA,SAAA,QAAA,eAPK,GAAC,KAAA,IAAA;CAAA,MAAA,YAAAC,aAAA,QAAA,WAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,QAElB,IAAI;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAIR,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,OAAO,QAAQ;CAErB,IAAI,QAAKC,IAAyB,IAAI;CACtC,YACE,MAAA,QACC,WAAW;EACV,IAAI,UAAU,MAAM;EACpB,MAAM,OAAO,MAAM,KAAK,MAAM,MAAM,GAAG,GAAG,KAAK,IAAI,GAAC,UAAA,KAAW,CAAC;EAChE,IAAI,SAAI,KAAA,OAAW,KAAA,QAAO;EAC1B,MAAA,QAAQ;CACV,CACF;CAEA,aAAOC,YAAA,OACI,WAAkB,EAAE,IAAI,CAAC,eAAe,MAAM,eAAc,KAAA,MAAM,EAAE,GAAG,IAAI,GAAC;EAClF,KAAK,kBAAcA,YAAA,QAEZ,WAAmB;GAAE,IAAI,eAAe;GAAM,eAAe;EAAK,GAAC,YAAA,KAAa,GAAC,CAEpF,KAAK,cAAc,CAAA;EAEvBA,YAAA,aAAAC,cAEK,eACF;GACE,cAAc,KAAK;GACnB,KAAK;GACL,KAAK,KAAK,IAAI,GAAC,UAAA,KAAW;GAC1B,SAAS;GACT,WAAW,EAAE,IAAI,eAAe,MAAM;EACxC,GAAC,WAAA,KAEH,GAAC;GAAA,UAAA,MAAA;GAAA,mBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,MAAA,QAAA;EAAA,CAAA,GAAA,IAAA;EAGF,KAAK,iBAAaD,YAAA,QAEX,WAAmB;GAAE,IAAI,eAAe;GAAM,eAAe;EAAK,GAAC,WAAA,KAAY,GAAC,CAEnF,KAAK,aAAa,CAAA;CAEtB,CAAA;AAGP,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|