@zerodep-dev/vue-tsx-pro-ui 0.2.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/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/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/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.js +7 -7
- 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/index.d.ts +11 -6
- package/dist/index.js +10 -5
- 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 +4 -4
- 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 +3 -3
- 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 +4 -4
- 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 +4 -4
- 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 +6 -6
- package/dist/input/TreeSelect.js.map +1 -1
- package/dist/input/Upload.js +8 -8
- package/dist/input/Upload.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 +7 -1
- package/dist/patterns/QueryTable.js +116 -81
- 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 +37 -1
- package/dist/patterns/messages.js +38 -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/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/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/http.d.ts +12 -0
- package/dist/utils/request/http.js +6 -2
- package/dist/utils/request/http.js.map +1 -1
- package/dist/utils/request/use-request.js +4 -2
- package/dist/utils/request/use-request.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { effectScope, reactive, watch } from "vue";
|
|
2
|
+
//#region src/config/layout/preference.ts
|
|
3
|
+
/**
|
|
4
|
+
* 布局偏好:用户选的侧栏形式(固定 / 抽屉)、抽屉从哪一边滑出、抽屉开不开与尺寸,记在本地存储里,
|
|
5
|
+
* 下次打开、其他标签页都沿用。和 createThemePreference 对应:主题管颜色,布局偏好管结构。
|
|
6
|
+
* 交给 AppShell 的 layout,配合 LayoutSwitcher 让用户自己选:
|
|
7
|
+
*
|
|
8
|
+
* const layout = createLayoutPreference({ defaults: { mode: 'overlay' } });
|
|
9
|
+
* <AppShell layout={layout} sidebar={…} header={<LayoutSwitcher layout={layout} />}>…</AppShell>
|
|
10
|
+
*
|
|
11
|
+
* 各项都是可读可写的属性(读时跟踪、写时存盘),也能不经 AppShell 直接用:layout.side = 'end'。
|
|
12
|
+
* 存的值不合法(改过键、版本升级)时用默认值,不会报错;存储不可用(隐私模式)时只在内存里。
|
|
13
|
+
*/
|
|
14
|
+
/** 可选的侧栏形式,LayoutSwitcher 据此列出选项 */
|
|
15
|
+
var LAYOUT_MODES = ["docked", "overlay"];
|
|
16
|
+
/** 可选的抽屉方向,LayoutSwitcher 据此列出选项 */
|
|
17
|
+
var LAYOUT_SIDES = [
|
|
18
|
+
"start",
|
|
19
|
+
"end",
|
|
20
|
+
"top",
|
|
21
|
+
"bottom"
|
|
22
|
+
];
|
|
23
|
+
/** 默认的抽屉宽度(px):左右两侧 */
|
|
24
|
+
var DEFAULT_LAYOUT_WIDTH = 256;
|
|
25
|
+
/** 默认的抽屉高度(px):上下两侧 */
|
|
26
|
+
var DEFAULT_LAYOUT_HEIGHT = 320;
|
|
27
|
+
/** 记住选择的默认 localStorage 键 */
|
|
28
|
+
var DEFAULT_LAYOUT_STORAGE_KEY = "vue-tsx-pro-layout";
|
|
29
|
+
var isMode = (value) => LAYOUT_MODES.includes(value);
|
|
30
|
+
var isSide = (value) => LAYOUT_SIDES.includes(value);
|
|
31
|
+
var isSize = (value) => typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
32
|
+
/** 读存下来的内容,只留合法的项 */
|
|
33
|
+
function parse(text) {
|
|
34
|
+
if (!text) return {};
|
|
35
|
+
let value;
|
|
36
|
+
try {
|
|
37
|
+
value = JSON.parse(text);
|
|
38
|
+
} catch {
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
if (typeof value !== "object" || value === null) return {};
|
|
42
|
+
const stored = value;
|
|
43
|
+
const result = {};
|
|
44
|
+
if (isMode(stored.mode)) result.mode = stored.mode;
|
|
45
|
+
if (isSide(stored.side)) result.side = stored.side;
|
|
46
|
+
if (typeof stored.open === "boolean") result.open = stored.open;
|
|
47
|
+
if (isSize(stored.width)) result.width = stored.width;
|
|
48
|
+
if (isSize(stored.height)) result.height = stored.height;
|
|
49
|
+
if (typeof stored.collapsed === "boolean") result.collapsed = stored.collapsed;
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
/** 创建布局偏好;在应用的生命周期里一直有效(监听其他标签页的改动不撤销) */
|
|
53
|
+
function createLayoutPreference(options = {}) {
|
|
54
|
+
const storageKey = options.storageKey === void 0 ? DEFAULT_LAYOUT_STORAGE_KEY : options.storageKey;
|
|
55
|
+
const defaults = {
|
|
56
|
+
mode: "docked",
|
|
57
|
+
side: "start",
|
|
58
|
+
open: false,
|
|
59
|
+
width: 256,
|
|
60
|
+
height: 320,
|
|
61
|
+
collapsed: false,
|
|
62
|
+
...options.defaults
|
|
63
|
+
};
|
|
64
|
+
const read = () => ({
|
|
65
|
+
...defaults,
|
|
66
|
+
...storageKey ? parse(safeStorage()?.getItem(storageKey) ?? null) : {}
|
|
67
|
+
});
|
|
68
|
+
const state = reactive(read());
|
|
69
|
+
let remote = false;
|
|
70
|
+
if (storageKey && typeof window !== "undefined") window.addEventListener("storage", (event) => {
|
|
71
|
+
if (event.key !== storageKey) return;
|
|
72
|
+
remote = true;
|
|
73
|
+
Object.assign(state, read());
|
|
74
|
+
});
|
|
75
|
+
effectScope(true).run(() => {
|
|
76
|
+
watch(() => ({ ...state }), (value) => {
|
|
77
|
+
if (remote) {
|
|
78
|
+
remote = false;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (storageKey) safeStorage()?.setItem(storageKey, JSON.stringify(value));
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
const preference = { reset() {
|
|
85
|
+
Object.assign(state, defaults);
|
|
86
|
+
if (storageKey) safeStorage()?.removeItem(storageKey);
|
|
87
|
+
} };
|
|
88
|
+
for (const key of Object.keys(defaults)) Object.defineProperty(preference, key, {
|
|
89
|
+
enumerable: true,
|
|
90
|
+
get: () => state[key],
|
|
91
|
+
set: (value) => {
|
|
92
|
+
state[key] = value;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return preference;
|
|
96
|
+
}
|
|
97
|
+
/** 隐私模式、禁用存储时 localStorage 会抛错:当作没有存储 */
|
|
98
|
+
function safeStorage() {
|
|
99
|
+
try {
|
|
100
|
+
return globalThis.localStorage;
|
|
101
|
+
} catch {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { DEFAULT_LAYOUT_HEIGHT, DEFAULT_LAYOUT_STORAGE_KEY, DEFAULT_LAYOUT_WIDTH, LAYOUT_MODES, LAYOUT_SIDES, createLayoutPreference };
|
|
107
|
+
|
|
108
|
+
//# sourceMappingURL=preference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preference.js","names":[],"sources":["../../../src/config/layout/preference.ts"],"sourcesContent":["/**\n * 布局偏好:用户选的侧栏形式(固定 / 抽屉)、抽屉从哪一边滑出、抽屉开不开与尺寸,记在本地存储里,\n * 下次打开、其他标签页都沿用。和 createThemePreference 对应:主题管颜色,布局偏好管结构。\n * 交给 AppShell 的 layout,配合 LayoutSwitcher 让用户自己选:\n *\n * const layout = createLayoutPreference({ defaults: { mode: 'overlay' } });\n * <AppShell layout={layout} sidebar={…} header={<LayoutSwitcher layout={layout} />}>…</AppShell>\n *\n * 各项都是可读可写的属性(读时跟踪、写时存盘),也能不经 AppShell 直接用:layout.side = 'end'。\n * 存的值不合法(改过键、版本升级)时用默认值,不会报错;存储不可用(隐私模式)时只在内存里。\n */\nimport { effectScope, reactive, watch } from 'vue';\n\n/** 侧栏的形式 */\nexport type LayoutMode = 'docked' | 'overlay';\n\n/** 抽屉式侧栏从哪一边滑出:start / end 随排版方向(从右到左时互换),top / bottom 是上下 */\nexport type LayoutSide = 'start' | 'end' | 'top' | 'bottom';\n\n/** 可选的侧栏形式,LayoutSwitcher 据此列出选项 */\nexport const LAYOUT_MODES: readonly LayoutMode[] = ['docked', 'overlay'];\n/** 可选的抽屉方向,LayoutSwitcher 据此列出选项 */\nexport const LAYOUT_SIDES: readonly LayoutSide[] = ['start', 'end', 'top', 'bottom'];\n\n/** 默认的抽屉宽度(px):左右两侧 */\nexport const DEFAULT_LAYOUT_WIDTH = 256;\n/** 默认的抽屉高度(px):上下两侧 */\nexport const DEFAULT_LAYOUT_HEIGHT = 320;\n\n/** createLayoutPreference 记住的内容 */\nexport interface LayoutState {\n /** 侧栏的形式,默认 docked */\n mode: LayoutMode;\n /** 抽屉从哪一边滑出(只在 overlay 时有效),默认 start */\n side: LayoutSide;\n /** 抽屉开着 */\n open: boolean;\n /** 左右两侧抽屉的宽度(px) */\n width: number;\n /** 上下两侧抽屉的高度(px) */\n height: number;\n /** docked 侧栏收起成了图标栏 */\n collapsed: boolean;\n}\n\n/** createLayoutPreference 的选项 */\nexport interface LayoutPreferenceOptions {\n /** 没记过(或记的值不合法)时各项的值 */\n defaults?: Partial<LayoutState>;\n /** 记住选择的 localStorage 键,默认 'vue-tsx-pro-layout';false 不记 */\n storageKey?: string | false;\n}\n\n/** 布局偏好:各项可读可写,写了就存盘、其他标签页跟着变 */\nexport interface LayoutPreference extends LayoutState {\n /** 全部恢复成默认值(并清掉记住的内容) */\n reset(): void;\n}\n\n/** 记住选择的默认 localStorage 键 */\nexport const DEFAULT_LAYOUT_STORAGE_KEY = 'vue-tsx-pro-layout';\n\nconst isMode = (value: unknown): value is LayoutMode => LAYOUT_MODES.includes(value as LayoutMode);\nconst isSide = (value: unknown): value is LayoutSide => LAYOUT_SIDES.includes(value as LayoutSide);\nconst isSize = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value) && value > 0;\n\n/** 读存下来的内容,只留合法的项 */\nfunction parse(text: string | null): Partial<LayoutState> {\n if (!text) return {};\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n return {};\n }\n if (typeof value !== 'object' || value === null) return {};\n const stored = value as Record<string, unknown>;\n const result: Partial<LayoutState> = {};\n if (isMode(stored.mode)) result.mode = stored.mode;\n if (isSide(stored.side)) result.side = stored.side;\n if (typeof stored.open === 'boolean') result.open = stored.open;\n if (isSize(stored.width)) result.width = stored.width;\n if (isSize(stored.height)) result.height = stored.height;\n if (typeof stored.collapsed === 'boolean') result.collapsed = stored.collapsed;\n return result;\n}\n\n/** 创建布局偏好;在应用的生命周期里一直有效(监听其他标签页的改动不撤销) */\nexport function createLayoutPreference(options: LayoutPreferenceOptions = {}): LayoutPreference {\n const storageKey =\n options.storageKey === undefined ? DEFAULT_LAYOUT_STORAGE_KEY : options.storageKey;\n const defaults: LayoutState = {\n mode: 'docked',\n side: 'start',\n open: false,\n width: DEFAULT_LAYOUT_WIDTH,\n height: DEFAULT_LAYOUT_HEIGHT,\n collapsed: false,\n ...options.defaults,\n };\n const read = (): LayoutState => ({\n ...defaults,\n ...(storageKey ? parse(safeStorage()?.getItem(storageKey) ?? null) : {}),\n });\n\n const state = reactive<LayoutState>(read());\n let remote = false;\n\n // 其他标签页改了:跟着变(这时不再写回去,避免来回触发)\n if (storageKey && typeof window !== 'undefined') {\n window.addEventListener('storage', (event) => {\n if (event.key !== storageKey) return;\n remote = true;\n Object.assign(state, read());\n });\n }\n\n // 监听放在自己的作用域里:不属于哪个组件\n effectScope(true).run(() => {\n watch(\n () => ({ ...state }),\n (value) => {\n if (remote) {\n remote = false;\n return;\n }\n if (storageKey) safeStorage()?.setItem(storageKey, JSON.stringify(value));\n },\n );\n });\n\n // 对外是带读写的属性(state 本身不暴露:reset 不该混进要存的内容里)\n const preference = {\n reset() {\n Object.assign(state, defaults);\n if (storageKey) safeStorage()?.removeItem(storageKey);\n },\n } as LayoutPreference;\n for (const key of Object.keys(defaults) as (keyof LayoutState)[]) {\n Object.defineProperty(preference, key, {\n enumerable: true,\n get: () => state[key],\n set: (value: never) => {\n state[key] = value;\n },\n });\n }\n return preference;\n}\n\n/** 隐私模式、禁用存储时 localStorage 会抛错:当作没有存储 */\nfunction safeStorage(): Storage | undefined {\n try {\n return globalThis.localStorage;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAoBA,IAAa,eAAsC,CAAC,UAAU,SAAS;;AAEvE,IAAa,eAAsC;CAAC;CAAS;CAAO;CAAO;AAAQ;;AAGnF,IAAa,uBAAuB;;AAEpC,IAAa,wBAAwB;;AAiCrC,IAAa,6BAA6B;AAE1C,IAAM,UAAU,UAAwC,aAAa,SAAS,KAAmB;AACjG,IAAM,UAAU,UAAwC,aAAa,SAAS,KAAmB;AACjG,IAAM,UAAU,UACd,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,QAAQ;;AAGjE,SAAS,MAAM,MAA2C;CACxD,IAAI,CAAC,MAAM,OAAO,CAAC;CACnB,IAAI;CACJ,IAAI;EACF,QAAQ,KAAK,MAAM,IAAI;CACzB,QAAQ;EACN,OAAO,CAAC;CACV;CACA,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO,CAAC;CACzD,MAAM,SAAS;CACf,MAAM,SAA+B,CAAC;CACtC,IAAI,OAAO,OAAO,IAAI,GAAG,OAAO,OAAO,OAAO;CAC9C,IAAI,OAAO,OAAO,IAAI,GAAG,OAAO,OAAO,OAAO;CAC9C,IAAI,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,OAAO;CAC3D,IAAI,OAAO,OAAO,KAAK,GAAG,OAAO,QAAQ,OAAO;CAChD,IAAI,OAAO,OAAO,MAAM,GAAG,OAAO,SAAS,OAAO;CAClD,IAAI,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY,OAAO;CACrE,OAAO;AACT;;AAGA,SAAgB,uBAAuB,UAAmC,CAAC,GAAqB;CAC9F,MAAM,aACJ,QAAQ,eAAe,KAAA,IAAY,6BAA6B,QAAQ;CAC1E,MAAM,WAAwB;EAC5B,MAAM;EACN,MAAM;EACN,MAAM;EACN,OAAA;EACA,QAAA;EACA,WAAW;EACX,GAAG,QAAQ;CACb;CACA,MAAM,cAA2B;EAC/B,GAAG;EACH,GAAI,aAAa,MAAM,YAAY,CAAC,EAAE,QAAQ,UAAU,KAAK,IAAI,IAAI,CAAC;CACxE;CAEA,MAAM,QAAQ,SAAsB,KAAK,CAAC;CAC1C,IAAI,SAAS;CAGb,IAAI,cAAc,OAAO,WAAW,aAClC,OAAO,iBAAiB,YAAY,UAAU;EAC5C,IAAI,MAAM,QAAQ,YAAY;EAC9B,SAAS;EACT,OAAO,OAAO,OAAO,KAAK,CAAC;CAC7B,CAAC;CAIH,YAAY,IAAI,CAAC,CAAC,UAAU;EAC1B,aACS,EAAE,GAAG,MAAM,KACjB,UAAU;GACT,IAAI,QAAQ;IACV,SAAS;IACT;GACF;GACA,IAAI,YAAY,YAAY,CAAC,EAAE,QAAQ,YAAY,KAAK,UAAU,KAAK,CAAC;EAC1E,CACF;CACF,CAAC;CAGD,MAAM,aAAa,EACjB,QAAQ;EACN,OAAO,OAAO,OAAO,QAAQ;EAC7B,IAAI,YAAY,YAAY,CAAC,EAAE,WAAW,UAAU;CACtD,EACF;CACA,KAAK,MAAM,OAAO,OAAO,KAAK,QAAQ,GACpC,OAAO,eAAe,YAAY,KAAK;EACrC,YAAY;EACZ,WAAW,MAAM;EACjB,MAAM,UAAiB;GACrB,MAAM,OAAO;EACf;CACF,CAAC;CAEH,OAAO;AACT;;AAGA,SAAS,cAAmC;CAC1C,IAAI;EACF,OAAO,WAAW;CACpB,QAAQ;EACN;CACF;AACF"}
|
package/dist/date/Calendar.js
CHANGED
|
@@ -2,8 +2,8 @@ import { isSameDate } from "../utils/data/date.js";
|
|
|
2
2
|
import { useCalendarState } from "./calendar-state.js";
|
|
3
3
|
import { toDateLimits, useDateLocale, writeDateLike } from "./date-locale.js";
|
|
4
4
|
import { CalendarView } from "./CalendarView.js";
|
|
5
|
-
import { computed, createVNode
|
|
6
|
-
import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
5
|
+
import { computed, createVNode } from "vue";
|
|
6
|
+
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
7
7
|
//#region src/date/Calendar.tsx
|
|
8
8
|
/** Calendar 共有的属性;未声明的属性落到根元素上 */
|
|
9
9
|
/** 单选:value 是一个日期 */
|
|
@@ -52,7 +52,7 @@ var Calendar = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
52
52
|
readonly: () => readonly.value || disabled.value,
|
|
53
53
|
defaultFocused: () => locale.fromValue(defaultFocused.value)
|
|
54
54
|
});
|
|
55
|
-
return () => createVNode(CalendarView,
|
|
55
|
+
return () => createVNode(CalendarView, mergeJsxProps(rest, {
|
|
56
56
|
"calendar": calendar,
|
|
57
57
|
"firstDayOfWeek": firstDayOfWeek.value,
|
|
58
58
|
"disabled": disabled.value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Calendar.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/date/Calendar.tsx"],"sourcesContent":["/**\n * 日历(WAI-ARIA 的日期网格):选一天或多天,可以并排几个月、显示周数、自定义日期格、切到月份与年份视图。\n * 参考 React Aria Calendar、Mantine DatePicker(inline)。\n *\n * <Calendar _value={date} min=\"2026-01-01\" aria-label=\"出发日期\" />\n * <Calendar selectionMode=\"multiple\" _value={days} visibleMonths={2} />\n * <Calendar _value={day}>{(date, cell) => <><span>{…}</span><small>¥399</small></>}</Calendar>\n *\n * 值是 ISO 日期字符串('2026-10-20',与原生 input type=\"date\"、URL 参数、zod 的 z.iso.date() 一致),\n * 也可以是 @internationalized/date 的 DateValue;写回时保持传入的类型(CalendarDateTime 选了另一天,时间不变)。\n * 月份名、星期名、读屏念的完整日期都由 Intl 按当前语言生成,一周从哪天开始按语言(可用 firstDayOfWeek 覆盖)。\n * 选一个区间用 RangeCalendar;选月份、年份用 granularity=\"month\" / \"year\"(DatePicker 的同名 granularity 就是这样做的)。\n *\n * 键盘:←→ 一天、↑↓ 一周,Page Up / Down 一个月、加 Shift 一年,Home / End 到这周两端,Enter / 空格选中。\n * 部件见 CalendarView。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport type { CalendarDate } from '@internationalized/date';\nimport { isSameDate, type DateUnit } from '../utils/data/date';\nimport { useCalendarState } from './calendar-state';\nimport { CalendarView, type CalendarViewProps } from './CalendarView';\nimport {\n toDateLimits,\n useDateLocale,\n writeDateLike,\n type DateInput,\n type DateLimitProps,\n type DateValueTypes,\n} from './date-locale';\n\n/** Calendar 共有的属性;未声明的属性落到根元素上 */\nexport interface CalendarBaseProps<V extends DateInput>\n extends Omit<CalendarViewProps, 'calendar'>, DateLimitProps {\n /** 并排显示几个月,默认 1 */\n visibleMonths?: number;\n /** 选择的粒度:day(默认)、month(选月份)、year(选年份) */\n granularity?: DateUnit;\n /** 没有已选日期时一开始显示哪天所在的月,默认今天 */\n defaultFocused?: DateInput;\n /** 值为空、推不出类型时写回哪一种,默认 iso(字符串);绑定的是 CalendarDate 且一开始为空时写 dateValue */\n valueType?: keyof DateValueTypes;\n /** 只读:能翻页、移动焦点,不能改选择 */\n readonly?: boolean;\n /** 点选了一天(再点已选的那天也会调用):日期选择器据此关闭弹层 */\n onPick?: (date: V) => void;\n}\n\n/** 单选:value 是一个日期 */\nexport interface SingleCalendarProps<V extends DateInput> {\n /** 选择方式,默认 single */\n selectionMode?: 'single';\n /** 选中的日期(ISO 字符串或 DateValue,写回时保持同一种类型):父级写 _value={x};没有时 null */\n _value?: V | null;\n}\n\n/** 多选:value 是日期的数组 */\nexport interface MultipleCalendarProps<V extends DateInput> {\n /** 选择方式 */\n selectionMode: 'multiple';\n /** 选中的日期(ISO 字符串或 DateValue):父级写 _value={list} */\n _value?: V[];\n}\n\n/** 单选或多选一天(多天) */\nexport type CalendarProps<V extends DateInput = string> = CalendarBaseProps<V> &\n (SingleCalendarProps<V> | MultipleCalendarProps<V>);\n\n/** 日历:选一天或多天 */\nexport const Calendar = _component(\n <V extends DateInput>({\n selectionMode = 'single',\n _value: value = _bindable<V | V[] | null | undefined>(undefined),\n min,\n max,\n isDateUnavailable,\n visibleMonths = 1,\n granularity = 'day',\n defaultFocused,\n valueType,\n firstDayOfWeek,\n readonly = false,\n disabled = false,\n onPick,\n ...rest\n }: CalendarProps<V>) => {\n const locale = useDateLocale(() => ({ firstDayOfWeek }));\n const values = (): readonly V[] =>\n value == null ? [] : Array.isArray(value) ? value : [value];\n const selected = _derived(\n values()\n .map((item) => locale.fromValue(item))\n .filter((date): date is CalendarDate => date != null),\n );\n // 值清空后再选:仍按清空前的类型写回\n let lastLike: V | undefined;\n const limits = _derived(toDateLimits(locale, { min, max, isDateUnavailable }));\n const calendar = useCalendarState({\n mode: () => selectionMode,\n selected: () => selected,\n onChange: (dates) => {\n const current = values();\n lastLike = current[0] ?? lastLike;\n // 多选时没变的那几天原样保留(DateValue 的时间、时区不丢)\n const picked = dates.map(\n (date) =>\n current.find((item) => isSameDate(locale.fromValue(item), date, granularity)) ??\n (writeDateLike(date, lastLike, valueType) as V),\n );\n value = selectionMode === 'multiple' ? picked : (picked[0] ?? null);\n if (selectionMode === 'single' && picked[0] != null) onPick?.(picked[0]);\n },\n today: () => locale.today(),\n limits: () => limits,\n week: () => locale.week,\n unit: () => granularity,\n visibleMonths: () => visibleMonths,\n readonly: () => readonly || disabled,\n defaultFocused: () => locale.fromValue(defaultFocused),\n });\n return () => (\n <CalendarView\n {...rest}\n calendar={calendar}\n firstDayOfWeek={firstDayOfWeek}\n disabled={disabled}\n data-invalid={calendar.invalid || undefined}\n />\n );\n },\n);\n"],"mappings":";;;;;;;;;;;;AAoEA,IAAa,WAAW,0BACtB,QAAA,SAewB;CAAA,MAAA,gBAAAA,aAAA,QAAA,iBAdN,QAAQ;CAAA,MAAA,QAAAC,SAAA,QAAA,gBAC8B,KAAA,GAAS,KAAA,IAAA;CAAA,MAAA,MAAAD,aAAA,QAAA,KAAA;CAAA,MAAA,MAAAA,aAAA,QAAA,KAAA;CAAA,MAAA,oBAAAA,aAAA,QAAA,mBAAA;CAAA,MAAA,gBAAAA,aAAA,QAAA,iBAI/C,CAAC;CAAA,MAAA,cAAAA,aAAA,QAAA,eACH,KAAK;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,YAIR,KAAK;CAAA,MAAA,WAAAA,aAAA,QAAA,YACL,KAAK;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAEb,OAAIE,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,SAAS,qBAAqB,EAAE,gBAAc,eAAA,MAAC,EAAE;CACvD,MAAM,eACJ,MAAA,SAAS,OAAO,CAAA,IAAK,MAAM,QAAO,MAAA,KAAM,IAAC,MAAA,QAAW,CAAA,MAAA,KAAA;CACtD,MAAM,WAAQC,eACZ,OAAO,CAAC,CACL,KAAK,SAAS,OAAO,UAAU,IAAI,CAAC,CAAC,CACrC,QAAQ,SAA+B,QAAQ,IAAI,CAAC;CAGzD,IAAI;CACJ,MAAM,SAAMA,eAAY,aAAa,QAAQ;EAAE,KAAG,IAAA;EAAE,KAAG,IAAA;EAAE,mBAAiB,kBAAA;CAAC,CAAC,CAAC;CAC7E,MAAM,WAAW,iBAAiB;EAChC,YAAM,cAAA;EACN,gBAAU,SAAA;EACV,WAAW,UAAU;GACnB,MAAM,UAAU,OAAO;GACvB,WAAW,QAAQ,MAAM;GAEzB,MAAM,SAAS,MAAM,KAClB,SACC,QAAQ,MAAM,SAAS,WAAW,OAAO,UAAU,IAAI,GAAG,MAAI,YAAA,KAAa,CAAC,KAC3E,cAAc,MAAM,UAAQ,UAAA,KAAW,CAC5C;GACA,MAAA,QAAQ,cAAA,UAAkB,aAAa,SAAU,OAAO,MAAM;GAC9D,IAAI,cAAA,UAAkB,YAAY,OAAO,MAAM,MAAM,OAAA,QAAS,OAAO,EAAE;EACzE;EACA,aAAa,OAAO,MAAM;EAC1B,cAAQ,OAAA;EACR,YAAY,OAAO;EACnB,YAAM,YAAA;EACN,qBAAe,cAAA;EACf,gBAAgB,SAAA,SAAA,SAAA;EAChB,sBAAsB,OAAO,UAAS,eAAA,KAAe;CACvD,CAAC;CACD,aAAOC,YAAA,cAAAC,
|
|
1
|
+
{"version":3,"file":"Calendar.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/date/Calendar.tsx"],"sourcesContent":["/**\n * 日历(WAI-ARIA 的日期网格):选一天或多天,可以并排几个月、显示周数、自定义日期格、切到月份与年份视图。\n * 参考 React Aria Calendar、Mantine DatePicker(inline)。\n *\n * <Calendar _value={date} min=\"2026-01-01\" aria-label=\"出发日期\" />\n * <Calendar selectionMode=\"multiple\" _value={days} visibleMonths={2} />\n * <Calendar _value={day}>{(date, cell) => <><span>{…}</span><small>¥399</small></>}</Calendar>\n *\n * 值是 ISO 日期字符串('2026-10-20',与原生 input type=\"date\"、URL 参数、zod 的 z.iso.date() 一致),\n * 也可以是 @internationalized/date 的 DateValue;写回时保持传入的类型(CalendarDateTime 选了另一天,时间不变)。\n * 月份名、星期名、读屏念的完整日期都由 Intl 按当前语言生成,一周从哪天开始按语言(可用 firstDayOfWeek 覆盖)。\n * 选一个区间用 RangeCalendar;选月份、年份用 granularity=\"month\" / \"year\"(DatePicker 的同名 granularity 就是这样做的)。\n *\n * 键盘:←→ 一天、↑↓ 一周,Page Up / Down 一个月、加 Shift 一年,Home / End 到这周两端,Enter / 空格选中。\n * 部件见 CalendarView。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport type { CalendarDate } from '@internationalized/date';\nimport { isSameDate, type DateUnit } from '../utils/data/date';\nimport { useCalendarState } from './calendar-state';\nimport { CalendarView, type CalendarViewProps } from './CalendarView';\nimport {\n toDateLimits,\n useDateLocale,\n writeDateLike,\n type DateInput,\n type DateLimitProps,\n type DateValueTypes,\n} from './date-locale';\n\n/** Calendar 共有的属性;未声明的属性落到根元素上 */\nexport interface CalendarBaseProps<V extends DateInput>\n extends Omit<CalendarViewProps, 'calendar'>, DateLimitProps {\n /** 并排显示几个月,默认 1 */\n visibleMonths?: number;\n /** 选择的粒度:day(默认)、month(选月份)、year(选年份) */\n granularity?: DateUnit;\n /** 没有已选日期时一开始显示哪天所在的月,默认今天 */\n defaultFocused?: DateInput;\n /** 值为空、推不出类型时写回哪一种,默认 iso(字符串);绑定的是 CalendarDate 且一开始为空时写 dateValue */\n valueType?: keyof DateValueTypes;\n /** 只读:能翻页、移动焦点,不能改选择 */\n readonly?: boolean;\n /** 点选了一天(再点已选的那天也会调用):日期选择器据此关闭弹层 */\n onPick?: (date: V) => void;\n}\n\n/** 单选:value 是一个日期 */\nexport interface SingleCalendarProps<V extends DateInput> {\n /** 选择方式,默认 single */\n selectionMode?: 'single';\n /** 选中的日期(ISO 字符串或 DateValue,写回时保持同一种类型):父级写 _value={x};没有时 null */\n _value?: V | null;\n}\n\n/** 多选:value 是日期的数组 */\nexport interface MultipleCalendarProps<V extends DateInput> {\n /** 选择方式 */\n selectionMode: 'multiple';\n /** 选中的日期(ISO 字符串或 DateValue):父级写 _value={list} */\n _value?: V[];\n}\n\n/** 单选或多选一天(多天) */\nexport type CalendarProps<V extends DateInput = string> = CalendarBaseProps<V> &\n (SingleCalendarProps<V> | MultipleCalendarProps<V>);\n\n/** 日历:选一天或多天 */\nexport const Calendar = _component(\n <V extends DateInput>({\n selectionMode = 'single',\n _value: value = _bindable<V | V[] | null | undefined>(undefined),\n min,\n max,\n isDateUnavailable,\n visibleMonths = 1,\n granularity = 'day',\n defaultFocused,\n valueType,\n firstDayOfWeek,\n readonly = false,\n disabled = false,\n onPick,\n ...rest\n }: CalendarProps<V>) => {\n const locale = useDateLocale(() => ({ firstDayOfWeek }));\n const values = (): readonly V[] =>\n value == null ? [] : Array.isArray(value) ? value : [value];\n const selected = _derived(\n values()\n .map((item) => locale.fromValue(item))\n .filter((date): date is CalendarDate => date != null),\n );\n // 值清空后再选:仍按清空前的类型写回\n let lastLike: V | undefined;\n const limits = _derived(toDateLimits(locale, { min, max, isDateUnavailable }));\n const calendar = useCalendarState({\n mode: () => selectionMode,\n selected: () => selected,\n onChange: (dates) => {\n const current = values();\n lastLike = current[0] ?? lastLike;\n // 多选时没变的那几天原样保留(DateValue 的时间、时区不丢)\n const picked = dates.map(\n (date) =>\n current.find((item) => isSameDate(locale.fromValue(item), date, granularity)) ??\n (writeDateLike(date, lastLike, valueType) as V),\n );\n value = selectionMode === 'multiple' ? picked : (picked[0] ?? null);\n if (selectionMode === 'single' && picked[0] != null) onPick?.(picked[0]);\n },\n today: () => locale.today(),\n limits: () => limits,\n week: () => locale.week,\n unit: () => granularity,\n visibleMonths: () => visibleMonths,\n readonly: () => readonly || disabled,\n defaultFocused: () => locale.fromValue(defaultFocused),\n });\n return () => (\n <CalendarView\n {...rest}\n calendar={calendar}\n firstDayOfWeek={firstDayOfWeek}\n disabled={disabled}\n data-invalid={calendar.invalid || undefined}\n />\n );\n },\n);\n"],"mappings":";;;;;;;;;;;;AAoEA,IAAa,WAAW,0BACtB,QAAA,SAewB;CAAA,MAAA,gBAAAA,aAAA,QAAA,iBAdN,QAAQ;CAAA,MAAA,QAAAC,SAAA,QAAA,gBAC8B,KAAA,GAAS,KAAA,IAAA;CAAA,MAAA,MAAAD,aAAA,QAAA,KAAA;CAAA,MAAA,MAAAA,aAAA,QAAA,KAAA;CAAA,MAAA,oBAAAA,aAAA,QAAA,mBAAA;CAAA,MAAA,gBAAAA,aAAA,QAAA,iBAI/C,CAAC;CAAA,MAAA,cAAAA,aAAA,QAAA,eACH,KAAK;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,YAIR,KAAK;CAAA,MAAA,WAAAA,aAAA,QAAA,YACL,KAAK;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAEb,OAAIE,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,SAAS,qBAAqB,EAAE,gBAAc,eAAA,MAAC,EAAE;CACvD,MAAM,eACJ,MAAA,SAAS,OAAO,CAAA,IAAK,MAAM,QAAO,MAAA,KAAM,IAAC,MAAA,QAAW,CAAA,MAAA,KAAA;CACtD,MAAM,WAAQC,eACZ,OAAO,CAAC,CACL,KAAK,SAAS,OAAO,UAAU,IAAI,CAAC,CAAC,CACrC,QAAQ,SAA+B,QAAQ,IAAI,CAAC;CAGzD,IAAI;CACJ,MAAM,SAAMA,eAAY,aAAa,QAAQ;EAAE,KAAG,IAAA;EAAE,KAAG,IAAA;EAAE,mBAAiB,kBAAA;CAAC,CAAC,CAAC;CAC7E,MAAM,WAAW,iBAAiB;EAChC,YAAM,cAAA;EACN,gBAAU,SAAA;EACV,WAAW,UAAU;GACnB,MAAM,UAAU,OAAO;GACvB,WAAW,QAAQ,MAAM;GAEzB,MAAM,SAAS,MAAM,KAClB,SACC,QAAQ,MAAM,SAAS,WAAW,OAAO,UAAU,IAAI,GAAG,MAAI,YAAA,KAAa,CAAC,KAC3E,cAAc,MAAM,UAAQ,UAAA,KAAW,CAC5C;GACA,MAAA,QAAQ,cAAA,UAAkB,aAAa,SAAU,OAAO,MAAM;GAC9D,IAAI,cAAA,UAAkB,YAAY,OAAO,MAAM,MAAM,OAAA,QAAS,OAAO,EAAE;EACzE;EACA,aAAa,OAAO,MAAM;EAC1B,cAAQ,OAAA;EACR,YAAY,OAAO;EACnB,YAAM,YAAA;EACN,qBAAe,cAAA;EACf,gBAAgB,SAAA,SAAA,SAAA;EAChB,sBAAsB,OAAO,UAAS,eAAA,KAAe;CACvD,CAAC;CACD,aAAOC,YAAA,cAAAC,cAEC,MAAI;EAAA,YACE;EAAQ,kBAAA,eAAA;EAAA,YAAA,SAAA;EAAA,gBAGJ,SAAS,WAAW,KAAA;CAAS,CAAA,GAAA,IAAA;AAGjD,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
|
@@ -13,8 +13,8 @@ import { isSameDate, monthGrid, weekdayNames } from "../utils/data/date.js";
|
|
|
13
13
|
import { useFormat } from "../config/lang/format.js";
|
|
14
14
|
import { handleCalendarKeydown, useCalendarState } from "./calendar-state.js";
|
|
15
15
|
import { toDateLimits, useDateLocale } from "./date-locale.js";
|
|
16
|
-
import { computed, createVNode, isVNode,
|
|
17
|
-
import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
16
|
+
import { computed, createVNode, isVNode, nextTick, shallowRef, useId, watch } from "vue";
|
|
17
|
+
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
18
18
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
19
19
|
import { ChevronLeft, ChevronRight } from "@lucide/icons";
|
|
20
20
|
import { isWeekend } from "@internationalized/date";
|
|
@@ -269,7 +269,7 @@ var CalendarBoard = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
269
269
|
const shown = list.slice(0, Math.max(0, maxEvents.value));
|
|
270
270
|
const own = typeof propsCell.value === "function" ? propsCell.value(iso) : propsCell.value;
|
|
271
271
|
const label = format.date(day, { dateStyle: "full" });
|
|
272
|
-
return createVNode("td",
|
|
272
|
+
return createVNode("td", mergeJsxProps({ "key": iso }, mergeAttrs({ sx: [
|
|
273
273
|
calendarBoardStyles.cell,
|
|
274
274
|
dayState.weekend && calendarBoardStyles.weekend,
|
|
275
275
|
state.outside && calendarBoardStyles.outside,
|
|
@@ -286,7 +286,7 @@ var CalendarBoard = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
286
286
|
"data-today": state.today || void 0,
|
|
287
287
|
"data-outside": state.outside || void 0
|
|
288
288
|
}), [
|
|
289
|
-
createVNode("div", css.attrs(calendarBoardStyles.dayHead), [createVNode("button",
|
|
289
|
+
createVNode("div", css.attrs(calendarBoardStyles.dayHead), [createVNode("button", mergeJsxProps({
|
|
290
290
|
"type": "button",
|
|
291
291
|
"tabindex": state.focused && !state.outside ? 0 : -1,
|
|
292
292
|
"aria-label": [state.today ? lang.calendarToday(label) : label, list.length > 0 ? lang.calendarBoardCount(list.length) : null].filter(Boolean).join(","),
|
|
@@ -302,7 +302,7 @@ var CalendarBoard = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
302
302
|
if (!state.focused) calendar.focus(day);
|
|
303
303
|
}
|
|
304
304
|
}), [locale.dayNumber(day)]), getDayNote.value && createVNode("span", css.attrs(calendarBoardStyles.note), [getDayNote.value(iso)])]),
|
|
305
|
-
shown.length > 0 && createVNode("ul", css.attrs(calendarBoardStyles.events), [shown.map((event, index) => createVNode("li", { "key": getEventKey.value?.(event) ?? index }, [renderEvent.value ? renderEvent.value(event, iso) : createVNode("span", css.attrs(calendarBoardStyles.event, statusToneSx("soft", getEventTone.value?.(event) ?? "accent")), [getEventLabel.value?.(event) ?? ""])])), list.length > shown.length && createVNode("li", null, [createVNode("button",
|
|
305
|
+
shown.length > 0 && createVNode("ul", css.attrs(calendarBoardStyles.events), [shown.map((event, index) => createVNode("li", { "key": getEventKey.value?.(event) ?? index }, [renderEvent.value ? renderEvent.value(event, iso) : createVNode("span", css.attrs(calendarBoardStyles.event, statusToneSx("soft", getEventTone.value?.(event) ?? "accent")), [getEventLabel.value?.(event) ?? ""])])), list.length > shown.length && createVNode("li", null, [createVNode("button", mergeJsxProps({ "type": "button" }, css.attrs(buttonBaseStyles.root, interactionTransitions.colors, calendarBoardStyles.more, focusRingStyles.tight), { "onClick": (event) => {
|
|
306
306
|
event.stopPropagation();
|
|
307
307
|
calendar.activate(day);
|
|
308
308
|
} }), [lang.calendarBoardMore(list.length - shown.length)])])]),
|
|
@@ -328,9 +328,9 @@ var CalendarBoard = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
328
328
|
role: "group"
|
|
329
329
|
}), [
|
|
330
330
|
createVNode("div", css.attrs(calendarBoardStyles.header), [
|
|
331
|
-
createVNode("span",
|
|
331
|
+
createVNode("span", mergeJsxProps({ "id": titleId }, css.attrs(calendarBoardStyles.title)), [title]),
|
|
332
332
|
toolbar.value,
|
|
333
|
-
createVNode(Button,
|
|
333
|
+
createVNode(Button, mergeJsxProps(mergePartProps({
|
|
334
334
|
size: "sm",
|
|
335
335
|
variant: "soft",
|
|
336
336
|
tone: "neutral"
|
|
@@ -358,12 +358,12 @@ var CalendarBoard = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
358
358
|
"onClick": _cache[3] || (_cache[3] = () => calendar.turnPage(1))
|
|
359
359
|
}, null)
|
|
360
360
|
]),
|
|
361
|
-
createVNode("table",
|
|
361
|
+
createVNode("table", mergeJsxProps(css.attrs(calendarBoardStyles.grid), {
|
|
362
362
|
"role": "grid",
|
|
363
363
|
"aria-labelledby": titleId,
|
|
364
364
|
"onKeydown": onKeydown,
|
|
365
365
|
"onPointerleave": _cache[4] || (_cache[4] = () => calendar.hover(null))
|
|
366
|
-
}), [createVNode("thead", null, [createVNode("tr", null, [names.map((name) => createVNode("th",
|
|
366
|
+
}), [createVNode("thead", null, [createVNode("tr", null, [names.map((name) => createVNode("th", mergeJsxProps({
|
|
367
367
|
"key": name,
|
|
368
368
|
"scope": "col"
|
|
369
369
|
}, css.attrs(calendarBoardStyles.weekday)), [name]))])]), createVNode("tbody", null, [weeks.map((week) => createVNode("tr", { "key": week[0].toString() }, [week.map((day) => renderCell(day, page))]))])]),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CalendarBoard.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/date/CalendarBoard.tsx"],"sourcesContent":["/**\n * 整页的月历(日历看板):一个月铺满一页,每天一个大格子,格子里放日程、排班、节假日这类按天的内容。\n * 参考 Ant Design Calendar 的 fullscreen、Google 日历的月视图。要在输入框里选日期用 DatePicker,小日历用 Calendar。\n *\n * <CalendarBoard\n * events={meetings}\n * getEventDate={(meeting) => meeting.date}\n * getEventLabel={(meeting) => meeting.title}\n * _value={day}\n * aria-label=\"会议日程\"\n * />\n *\n * - 数据按天放进格子:getEventDate 是哪一天(带时间的取日期),getEventEnd 给了时跨天的每一天都有它;\n * 每天最多显示 maxEvents 条,其余收成“还有 N 项”(点了选中那一天,由页面在旁边列出全部)。\n * renderEvent 自定义一条的显示(默认是带色调的一行文字),renderDay 往格子里加别的内容(排班、价格),\n * getDayNote 是日期旁边的小字(节假日、“休”“班”、农历)。\n * - 键盘与 Calendar 一致(同一个 useCalendarState):每天的日期数字是一个按钮,焦点在当前日期上,\n * ←→ 一天、↑↓ 一周、Page Up / Down 一个月、Home / End 到这周两端,Enter / 空格选中;读屏念完整日期与有几项日程。\n * 格子里的日程可以是链接、按钮,Tab 照常进去。\n * - 页头:标题(翻页时播报)、toolbar(筛选、视图切换)、“今天”、上个月 / 下个月;month 可以双向绑定(翻页写回)。\n *\n * 部件:Root(div,role=\"group\")、Header、Title、Today、Previous、Next、Grid(table)、Weekday、Cell(td)、\n * DayButton(日期数字)、Note、Events(ul)、Event、More。\n */\nimport { ChevronLeft, ChevronRight } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { isWeekend, type CalendarDate } from '@internationalized/date';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick, useId, watch, type VNodeChild } from 'vue';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { buttonBaseStyles } from '../base/button-core';\nimport { IconButton } from '../base/IconButton';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFormat } from '../config/lang/format';\nimport { t } from '../config/theme/tokens';\nimport { isSameDate, monthGrid, weekdayNames } from '../utils/data/date';\nimport { isRtl } from '../utils/dom/direction';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { statusToneSx, type StatusTone } from '../utils/style/tone-styles';\nimport { interactionTransitions } from '../utils/style/transitions';\nimport { handleCalendarKeydown, useCalendarState } from './calendar-state';\nimport { toDateLimits, useDateLocale, type DateLimitProps } from './date-locale';\n\n/** 一天的状态:renderDay、getDayNote 之外的自定义内容用 */\nexport interface CalendarBoardDayState {\n /** 今天 */\n today: boolean;\n /** 补齐的上个月、下个月的日子 */\n outside: boolean;\n /** 选中的那一天 */\n selected: boolean;\n /** 周六、周日(按语言) */\n weekend: boolean;\n /** 不可选(范围外、不可选的日期) */\n disabled: boolean;\n}\n\n/** 未声明的属性落到根元素上;aria-label 是整个月历的名称 */\nexport interface CalendarBoardProps<T = unknown> extends PartProps<'div', 'role'>, DateLimitProps {\n /** 选中的那一天(ISO 日期):父级写 _value={day};没有时 null */\n _value?: string | null;\n /** 显示哪个月('YYYY-MM'):父级可写 _month={m},翻页时写回;不写时从选中的那天(或今天)开始 */\n _month?: string;\n /** 一周的第一天,0 是周日;不写时按语言 */\n firstDayOfWeek?: number;\n /** 按天放的数据:日程、排班、提醒 */\n events?: readonly T[];\n /** 数据在哪一天(ISO 日期;带时间的取日期部分) */\n getEventDate?: (event: T) => string;\n /** 跨天的数据在哪一天结束(含);不写时只在 getEventDate 那一天 */\n getEventEnd?: (event: T) => string;\n /** 数据的 key;不写时用它在 events 里的位置 */\n getEventKey?: (event: T) => string;\n /** 默认显示的文字 */\n getEventLabel?: (event: T) => string;\n /** 默认显示的色调,默认 accent */\n getEventTone?: (event: T) => StatusTone;\n /** 自定义一条数据的显示 */\n renderEvent?: (event: T, date: string) => VNodeChild;\n /** 每天最多显示几条,其余收成“还有 N 项”,默认 3 */\n maxEvents?: number;\n /** 日期旁边的小字(节假日、“休”“班”、农历) */\n getDayNote?: (date: string) => VNodeChild;\n /** 往格子里加别的内容(排班、价格),放在日程下面 */\n renderDay?: (date: string, state: CalendarBoardDayState) => VNodeChild;\n /** 页头右边的内容(筛选、视图切换) */\n toolbar?: VNodeChild;\n /** 只读:能翻页、移动焦点,不能选 */\n readonly?: boolean;\n /** “今天”按钮的部件属性 */\n propsToday?: Partial<ButtonProps>;\n /** 每格(td)的部件属性,可以按日期给 */\n propsCell?: PartProps<'td', 'role' | 'aria-selected'> | ((date: string) => PartProps<'td'>);\n}\n\n/** CalendarBoard 的样式 */\nexport const calendarBoardStyles = css.create({\n root: { display: 'flex', flexDirection: 'column', gap: '_sm', minWidth: 0 },\n header: { display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '_sm' },\n title: { fontSize: '_lg', fontWeight: '_semibold', marginInlineEnd: 'auto' },\n grid: {\n width: '_full',\n tableLayout: 'fixed',\n borderCollapse: 'collapse',\n borderSpacing: 0,\n },\n weekday: {\n paddingBlock: '_xs',\n paddingInline: '_sm',\n color: '_textMuted',\n fontWeight: '_normal',\n fontSize: '_sm',\n textAlign: 'start',\n },\n cell: {\n height: '7em',\n padding: '_xs',\n verticalAlign: 'top',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n cursor: 'pointer',\n transition: `background-color ${t.durations.sm} ${t.easings.standard}`,\n backgroundColor: { default: 'transparent', ':hover': '_fillHover' },\n },\n weekend: { backgroundColor: { default: '_surfaceMuted', ':hover': '_fillHover' } },\n outside: { color: '_textMuted' },\n selected: {\n backgroundColor: { default: '_accentSoft', ':hover': '_accentSoftHover' },\n boxShadow: `inset 0 0 0 ${t.borderWidths.sm} ${t.colors.accentBorder}`,\n },\n disabled: { cursor: 'not-allowed', opacity: '_disabled' },\n // 只读:格子不像能点\n readonly: { cursor: 'default' },\n dayHead: { display: 'flex', alignItems: 'center', gap: '_xs', minWidth: 0 },\n // 日期数字:可聚焦的按钮,焦点环画在它上面\n day: {\n display: 'inline-grid',\n placeItems: 'center',\n flexShrink: 0,\n minWidth: '1.75em',\n height: '1.75em',\n paddingInline: '_xs',\n borderRadius: '_full',\n fontVariantNumeric: 'tabular-nums',\n fontWeight: '_medium',\n },\n today: { backgroundColor: '_accent', color: '_accentContrast' },\n note: {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n fontSize: '_xs',\n color: '_textMuted',\n },\n events: {\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n marginBlock: '_xs',\n marginInline: 0,\n padding: 0,\n listStyle: 'none',\n },\n event: {\n display: 'block',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n paddingInline: '_xs',\n borderRadius: '_sm',\n fontSize: '_xs',\n lineHeight: '1.6',\n },\n more: {\n paddingInline: '_xs',\n borderRadius: '_sm',\n fontSize: '_xs',\n color: '_textMuted',\n backgroundColor: { default: 'transparent', ':hover': '_fillHover' },\n },\n});\n\n/** 整页的月历:每天一个大格子,放日程、排班、节假日 */\nexport const CalendarBoard = _component(\n <T,>({\n _value: value = _bindable<string | null>(null),\n _month: month = _bindable<string | undefined>(undefined),\n firstDayOfWeek,\n min,\n max,\n isDateUnavailable,\n events = [],\n getEventDate,\n getEventEnd,\n getEventKey,\n getEventLabel,\n getEventTone,\n renderEvent,\n maxEvents = 3,\n getDayNote,\n renderDay,\n toolbar,\n readonly = false,\n propsToday,\n propsCell,\n ...rest\n }: CalendarBoardProps<T>) => {\n const lang = useLang();\n const format = useFormat();\n const locale = useDateLocale(() => ({ firstDayOfWeek }));\n const titleId = useId();\n let root = _state.raw<HTMLElement | null>(null);\n const limits = _derived(toDateLimits(locale, { min, max, isDateUnavailable }));\n const selected = _derived.by(() => {\n const day = locale.fromValue(value);\n return day ? [day] : [];\n });\n const calendar = useCalendarState({\n mode: () => 'single',\n selected: () => selected,\n onChange: ([day]) => {\n value = locale.toIso(day!);\n },\n today: () => locale.today(),\n limits: () => limits,\n week: () => locale.week,\n readonly: () => readonly,\n defaultFocused: () => (month ? locale.fromValue(`${month}-01`) : null),\n });\n\n // 翻页写回 month;父级改了 month 时翻过去\n watch(\n () => calendar.page.toString().slice(0, 7),\n (page) => {\n if (month !== undefined && month !== page) month = page;\n },\n );\n watch(\n () => month,\n (next) => {\n const target = next ? locale.fromValue(`${next}-01`) : null;\n if (target && !isSameDate(target, calendar.page, 'month')) calendar.focus(target);\n },\n );\n\n /** 按天分好的数据:ISO 日期 → 那天的数据(跨天的每一天都有) */\n const byDay = _derived.by(() => {\n const map = new Map<string, T[]>();\n if (!getEventDate) return map;\n for (const event of events) {\n const first = locale.fromValue(getEventDate(event).slice(0, 10));\n if (!first) continue;\n const last = getEventEnd ? locale.fromValue(getEventEnd(event).slice(0, 10)) : null;\n // 跨天的最多铺 366 天,数据错了(结束早于开始、跨好几年)也不会卡住\n for (let day = first, count = 0; count < 366; day = day.add({ days: 1 }), count++) {\n const key = locale.toIso(day);\n map.set(key, [...(map.get(key) ?? []), event]);\n if (!last || day.compare(last) >= 0) break;\n }\n }\n return map;\n });\n\n function onKeydown(event: KeyboardEvent) {\n // 格子里的日程(链接、按钮)自己处理按键\n if (!(event.target as Element).matches('[data-day]')) return;\n if (!handleCalendarKeydown(calendar, event, !!root && isRtl(root))) return;\n event.preventDefault();\n void nextTick(() => root?.querySelector<HTMLElement>('[data-day][data-focused]')?.focus());\n }\n\n /** 点格子的空白处:选中那一天(点里面的链接、按钮时照常) */\n function onCellClick(event: MouseEvent, day: CalendarDate) {\n if ((event.target as Element).closest('a, button, input, [role=\"button\"]')) return;\n calendar.activate(day);\n }\n\n function renderCell(day: CalendarDate, page: CalendarDate) {\n const iso = locale.toIso(day);\n const state = calendar.cell(day, page);\n const dayState: CalendarBoardDayState = {\n today: state.today,\n outside: state.outside,\n selected: state.selected,\n weekend: isWeekend(day, locale.locale),\n disabled: state.disabled,\n };\n const list = byDay.get(iso) ?? [];\n const shown = list.slice(0, Math.max(0, maxEvents));\n const own = typeof propsCell === 'function' ? propsCell(iso) : propsCell;\n const label = format.date(day, { dateStyle: 'full' });\n return (\n <td\n key={iso}\n {...mergeAttrs<'td'>(\n {\n sx: [\n calendarBoardStyles.cell,\n dayState.weekend && calendarBoardStyles.weekend,\n state.outside && calendarBoardStyles.outside,\n state.selected && calendarBoardStyles.selected,\n state.disabled && calendarBoardStyles.disabled,\n readonly && calendarBoardStyles.readonly,\n ],\n },\n own,\n {\n role: 'gridcell',\n 'aria-selected': state.selected,\n onClick: (event: MouseEvent) => onCellClick(event, day),\n onPointerenter: () => calendar.hover(day),\n },\n )}\n data-date={iso}\n data-today={state.today || undefined}\n data-outside={state.outside || undefined}\n >\n <div {...css.attrs(calendarBoardStyles.dayHead)}>\n <button\n type=\"button\"\n tabindex={state.focused && !state.outside ? 0 : -1}\n aria-label={[\n state.today ? lang.calendarToday(label) : label,\n list.length > 0 ? lang.calendarBoardCount(list.length) : null,\n ]\n .filter(Boolean)\n .join(',')}\n aria-disabled={state.disabled || undefined}\n {...css.attrs(\n buttonBaseStyles.root,\n interactionTransitions.colors,\n calendarBoardStyles.day,\n focusRingStyles.tight,\n state.today && calendarBoardStyles.today,\n )}\n data-day=\"\"\n data-focused={(state.focused && !state.outside) || undefined}\n onClick={(event: MouseEvent) => {\n event.stopPropagation();\n if (!state.disabled) calendar.activate(day);\n }}\n onFocus={() => {\n if (!state.focused) calendar.focus(day);\n }}\n >\n {locale.dayNumber(day)}\n </button>\n {getDayNote && <span {...css.attrs(calendarBoardStyles.note)}>{getDayNote(iso)}</span>}\n </div>\n {shown.length > 0 && (\n <ul {...css.attrs(calendarBoardStyles.events)}>\n {shown.map((event, index) => (\n <li key={getEventKey?.(event) ?? index}>\n {renderEvent ? (\n renderEvent(event, iso)\n ) : (\n <span\n {...css.attrs(\n calendarBoardStyles.event,\n statusToneSx('soft', getEventTone?.(event) ?? 'accent'),\n )}\n >\n {getEventLabel?.(event) ?? ''}\n </span>\n )}\n </li>\n ))}\n {list.length > shown.length && (\n <li>\n <button\n type=\"button\"\n {...css.attrs(\n buttonBaseStyles.root,\n interactionTransitions.colors,\n calendarBoardStyles.more,\n focusRingStyles.tight,\n )}\n onClick={(event: MouseEvent) => {\n event.stopPropagation();\n calendar.activate(day);\n }}\n >\n {lang.calendarBoardMore(list.length - shown.length)}\n </button>\n </li>\n )}\n </ul>\n )}\n {renderDay?.(iso, dayState)}\n </td>\n );\n }\n\n return () => {\n const page = calendar.page;\n const title = format.date(page, { year: 'numeric', month: 'long' });\n const weeks = monthGrid(page, { ...locale.week, fixedWeeks: false });\n const names = weekdayNames(locale.locale, {\n firstDayOfWeek: locale.week.firstDayOfWeek,\n format: 'short',\n });\n return (\n <div\n {...mergeAttrs<'div'>({ sx: calendarBoardStyles.root }, rest, {\n ref: _toRef(root),\n role: 'group',\n })}\n >\n <div {...css.attrs(calendarBoardStyles.header)}>\n <span id={titleId} {...css.attrs(calendarBoardStyles.title)}>\n {title}\n </span>\n {toolbar}\n <Button\n {...mergePartProps<ButtonProps>(\n { size: 'sm', variant: 'soft', tone: 'neutral' },\n propsToday,\n {\n onClick: () => {\n calendar.focus(locale.today());\n void nextTick(() =>\n root?.querySelector<HTMLElement>('[data-day][data-focused]')?.focus(),\n );\n },\n },\n )}\n >\n {lang.dateRangePreset.today}\n </Button>\n <IconButton\n icon={ChevronLeft}\n aria-label={lang.calendarPreviousMonth}\n propsIcon={{ flipInRtl: true }}\n size=\"sm\"\n disabled={!calendar.canTurnPage(-1)}\n onClick={() => calendar.turnPage(-1)}\n />\n <IconButton\n icon={ChevronRight}\n aria-label={lang.calendarNextMonth}\n propsIcon={{ flipInRtl: true }}\n size=\"sm\"\n disabled={!calendar.canTurnPage(1)}\n onClick={() => calendar.turnPage(1)}\n />\n </div>\n <table\n {...css.attrs(calendarBoardStyles.grid)}\n role=\"grid\"\n aria-labelledby={titleId}\n onKeydown={onKeydown}\n onPointerleave={() => calendar.hover(null)}\n >\n <thead>\n <tr>\n {names.map((name) => (\n <th key={name} scope=\"col\" {...css.attrs(calendarBoardStyles.weekday)}>\n {name}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {weeks.map((week) => (\n <tr key={week[0]!.toString()}>{week.map((day) => renderCell(day, page))}</tr>\n ))}\n </tbody>\n </table>\n {/* 翻页时播报新的月份 */}\n <VisuallyHidden aria-live=\"polite\">{title}</VisuallyHidden>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CalendarBoard.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/date/CalendarBoard.tsx"],"sourcesContent":["/**\n * 整页的月历(日历看板):一个月铺满一页,每天一个大格子,格子里放日程、排班、节假日这类按天的内容。\n * 参考 Ant Design Calendar 的 fullscreen、Google 日历的月视图。要在输入框里选日期用 DatePicker,小日历用 Calendar。\n *\n * <CalendarBoard\n * events={meetings}\n * getEventDate={(meeting) => meeting.date}\n * getEventLabel={(meeting) => meeting.title}\n * _value={day}\n * aria-label=\"会议日程\"\n * />\n *\n * - 数据按天放进格子:getEventDate 是哪一天(带时间的取日期),getEventEnd 给了时跨天的每一天都有它;\n * 每天最多显示 maxEvents 条,其余收成“还有 N 项”(点了选中那一天,由页面在旁边列出全部)。\n * renderEvent 自定义一条的显示(默认是带色调的一行文字),renderDay 往格子里加别的内容(排班、价格),\n * getDayNote 是日期旁边的小字(节假日、“休”“班”、农历)。\n * - 键盘与 Calendar 一致(同一个 useCalendarState):每天的日期数字是一个按钮,焦点在当前日期上,\n * ←→ 一天、↑↓ 一周、Page Up / Down 一个月、Home / End 到这周两端,Enter / 空格选中;读屏念完整日期与有几项日程。\n * 格子里的日程可以是链接、按钮,Tab 照常进去。\n * - 页头:标题(翻页时播报)、toolbar(筛选、视图切换)、“今天”、上个月 / 下个月;month 可以双向绑定(翻页写回)。\n *\n * 部件:Root(div,role=\"group\")、Header、Title、Today、Previous、Next、Grid(table)、Weekday、Cell(td)、\n * DayButton(日期数字)、Note、Events(ul)、Event、More。\n */\nimport { ChevronLeft, ChevronRight } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { isWeekend, type CalendarDate } from '@internationalized/date';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick, useId, watch, type VNodeChild } from 'vue';\nimport { Button, type ButtonProps } from '../base/Button';\nimport { buttonBaseStyles } from '../base/button-core';\nimport { IconButton } from '../base/IconButton';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFormat } from '../config/lang/format';\nimport { t } from '../config/theme/tokens';\nimport { isSameDate, monthGrid, weekdayNames } from '../utils/data/date';\nimport { isRtl } from '../utils/dom/direction';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { statusToneSx, type StatusTone } from '../utils/style/tone-styles';\nimport { interactionTransitions } from '../utils/style/transitions';\nimport { handleCalendarKeydown, useCalendarState } from './calendar-state';\nimport { toDateLimits, useDateLocale, type DateLimitProps } from './date-locale';\n\n/** 一天的状态:renderDay、getDayNote 之外的自定义内容用 */\nexport interface CalendarBoardDayState {\n /** 今天 */\n today: boolean;\n /** 补齐的上个月、下个月的日子 */\n outside: boolean;\n /** 选中的那一天 */\n selected: boolean;\n /** 周六、周日(按语言) */\n weekend: boolean;\n /** 不可选(范围外、不可选的日期) */\n disabled: boolean;\n}\n\n/** 未声明的属性落到根元素上;aria-label 是整个月历的名称 */\nexport interface CalendarBoardProps<T = unknown> extends PartProps<'div', 'role'>, DateLimitProps {\n /** 选中的那一天(ISO 日期):父级写 _value={day};没有时 null */\n _value?: string | null;\n /** 显示哪个月('YYYY-MM'):父级可写 _month={m},翻页时写回;不写时从选中的那天(或今天)开始 */\n _month?: string;\n /** 一周的第一天,0 是周日;不写时按语言 */\n firstDayOfWeek?: number;\n /** 按天放的数据:日程、排班、提醒 */\n events?: readonly T[];\n /** 数据在哪一天(ISO 日期;带时间的取日期部分) */\n getEventDate?: (event: T) => string;\n /** 跨天的数据在哪一天结束(含);不写时只在 getEventDate 那一天 */\n getEventEnd?: (event: T) => string;\n /** 数据的 key;不写时用它在 events 里的位置 */\n getEventKey?: (event: T) => string;\n /** 默认显示的文字 */\n getEventLabel?: (event: T) => string;\n /** 默认显示的色调,默认 accent */\n getEventTone?: (event: T) => StatusTone;\n /** 自定义一条数据的显示 */\n renderEvent?: (event: T, date: string) => VNodeChild;\n /** 每天最多显示几条,其余收成“还有 N 项”,默认 3 */\n maxEvents?: number;\n /** 日期旁边的小字(节假日、“休”“班”、农历) */\n getDayNote?: (date: string) => VNodeChild;\n /** 往格子里加别的内容(排班、价格),放在日程下面 */\n renderDay?: (date: string, state: CalendarBoardDayState) => VNodeChild;\n /** 页头右边的内容(筛选、视图切换) */\n toolbar?: VNodeChild;\n /** 只读:能翻页、移动焦点,不能选 */\n readonly?: boolean;\n /** “今天”按钮的部件属性 */\n propsToday?: Partial<ButtonProps>;\n /** 每格(td)的部件属性,可以按日期给 */\n propsCell?: PartProps<'td', 'role' | 'aria-selected'> | ((date: string) => PartProps<'td'>);\n}\n\n/** CalendarBoard 的样式 */\nexport const calendarBoardStyles = css.create({\n root: { display: 'flex', flexDirection: 'column', gap: '_sm', minWidth: 0 },\n header: { display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '_sm' },\n title: { fontSize: '_lg', fontWeight: '_semibold', marginInlineEnd: 'auto' },\n grid: {\n width: '_full',\n tableLayout: 'fixed',\n borderCollapse: 'collapse',\n borderSpacing: 0,\n },\n weekday: {\n paddingBlock: '_xs',\n paddingInline: '_sm',\n color: '_textMuted',\n fontWeight: '_normal',\n fontSize: '_sm',\n textAlign: 'start',\n },\n cell: {\n height: '7em',\n padding: '_xs',\n verticalAlign: 'top',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n cursor: 'pointer',\n transition: `background-color ${t.durations.sm} ${t.easings.standard}`,\n backgroundColor: { default: 'transparent', ':hover': '_fillHover' },\n },\n weekend: { backgroundColor: { default: '_surfaceMuted', ':hover': '_fillHover' } },\n outside: { color: '_textMuted' },\n selected: {\n backgroundColor: { default: '_accentSoft', ':hover': '_accentSoftHover' },\n boxShadow: `inset 0 0 0 ${t.borderWidths.sm} ${t.colors.accentBorder}`,\n },\n disabled: { cursor: 'not-allowed', opacity: '_disabled' },\n // 只读:格子不像能点\n readonly: { cursor: 'default' },\n dayHead: { display: 'flex', alignItems: 'center', gap: '_xs', minWidth: 0 },\n // 日期数字:可聚焦的按钮,焦点环画在它上面\n day: {\n display: 'inline-grid',\n placeItems: 'center',\n flexShrink: 0,\n minWidth: '1.75em',\n height: '1.75em',\n paddingInline: '_xs',\n borderRadius: '_full',\n fontVariantNumeric: 'tabular-nums',\n fontWeight: '_medium',\n },\n today: { backgroundColor: '_accent', color: '_accentContrast' },\n note: {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n fontSize: '_xs',\n color: '_textMuted',\n },\n events: {\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n marginBlock: '_xs',\n marginInline: 0,\n padding: 0,\n listStyle: 'none',\n },\n event: {\n display: 'block',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n paddingInline: '_xs',\n borderRadius: '_sm',\n fontSize: '_xs',\n lineHeight: '1.6',\n },\n more: {\n paddingInline: '_xs',\n borderRadius: '_sm',\n fontSize: '_xs',\n color: '_textMuted',\n backgroundColor: { default: 'transparent', ':hover': '_fillHover' },\n },\n});\n\n/** 整页的月历:每天一个大格子,放日程、排班、节假日 */\nexport const CalendarBoard = _component(\n <T,>({\n _value: value = _bindable<string | null>(null),\n _month: month = _bindable<string | undefined>(undefined),\n firstDayOfWeek,\n min,\n max,\n isDateUnavailable,\n events = [],\n getEventDate,\n getEventEnd,\n getEventKey,\n getEventLabel,\n getEventTone,\n renderEvent,\n maxEvents = 3,\n getDayNote,\n renderDay,\n toolbar,\n readonly = false,\n propsToday,\n propsCell,\n ...rest\n }: CalendarBoardProps<T>) => {\n const lang = useLang();\n const format = useFormat();\n const locale = useDateLocale(() => ({ firstDayOfWeek }));\n const titleId = useId();\n let root = _state.raw<HTMLElement | null>(null);\n const limits = _derived(toDateLimits(locale, { min, max, isDateUnavailable }));\n const selected = _derived.by(() => {\n const day = locale.fromValue(value);\n return day ? [day] : [];\n });\n const calendar = useCalendarState({\n mode: () => 'single',\n selected: () => selected,\n onChange: ([day]) => {\n value = locale.toIso(day!);\n },\n today: () => locale.today(),\n limits: () => limits,\n week: () => locale.week,\n readonly: () => readonly,\n defaultFocused: () => (month ? locale.fromValue(`${month}-01`) : null),\n });\n\n // 翻页写回 month;父级改了 month 时翻过去\n watch(\n () => calendar.page.toString().slice(0, 7),\n (page) => {\n if (month !== undefined && month !== page) month = page;\n },\n );\n watch(\n () => month,\n (next) => {\n const target = next ? locale.fromValue(`${next}-01`) : null;\n if (target && !isSameDate(target, calendar.page, 'month')) calendar.focus(target);\n },\n );\n\n /** 按天分好的数据:ISO 日期 → 那天的数据(跨天的每一天都有) */\n const byDay = _derived.by(() => {\n const map = new Map<string, T[]>();\n if (!getEventDate) return map;\n for (const event of events) {\n const first = locale.fromValue(getEventDate(event).slice(0, 10));\n if (!first) continue;\n const last = getEventEnd ? locale.fromValue(getEventEnd(event).slice(0, 10)) : null;\n // 跨天的最多铺 366 天,数据错了(结束早于开始、跨好几年)也不会卡住\n for (let day = first, count = 0; count < 366; day = day.add({ days: 1 }), count++) {\n const key = locale.toIso(day);\n map.set(key, [...(map.get(key) ?? []), event]);\n if (!last || day.compare(last) >= 0) break;\n }\n }\n return map;\n });\n\n function onKeydown(event: KeyboardEvent) {\n // 格子里的日程(链接、按钮)自己处理按键\n if (!(event.target as Element).matches('[data-day]')) return;\n if (!handleCalendarKeydown(calendar, event, !!root && isRtl(root))) return;\n event.preventDefault();\n void nextTick(() => root?.querySelector<HTMLElement>('[data-day][data-focused]')?.focus());\n }\n\n /** 点格子的空白处:选中那一天(点里面的链接、按钮时照常) */\n function onCellClick(event: MouseEvent, day: CalendarDate) {\n if ((event.target as Element).closest('a, button, input, [role=\"button\"]')) return;\n calendar.activate(day);\n }\n\n function renderCell(day: CalendarDate, page: CalendarDate) {\n const iso = locale.toIso(day);\n const state = calendar.cell(day, page);\n const dayState: CalendarBoardDayState = {\n today: state.today,\n outside: state.outside,\n selected: state.selected,\n weekend: isWeekend(day, locale.locale),\n disabled: state.disabled,\n };\n const list = byDay.get(iso) ?? [];\n const shown = list.slice(0, Math.max(0, maxEvents));\n const own = typeof propsCell === 'function' ? propsCell(iso) : propsCell;\n const label = format.date(day, { dateStyle: 'full' });\n return (\n <td\n key={iso}\n {...mergeAttrs<'td'>(\n {\n sx: [\n calendarBoardStyles.cell,\n dayState.weekend && calendarBoardStyles.weekend,\n state.outside && calendarBoardStyles.outside,\n state.selected && calendarBoardStyles.selected,\n state.disabled && calendarBoardStyles.disabled,\n readonly && calendarBoardStyles.readonly,\n ],\n },\n own,\n {\n role: 'gridcell',\n 'aria-selected': state.selected,\n onClick: (event: MouseEvent) => onCellClick(event, day),\n onPointerenter: () => calendar.hover(day),\n },\n )}\n data-date={iso}\n data-today={state.today || undefined}\n data-outside={state.outside || undefined}\n >\n <div {...css.attrs(calendarBoardStyles.dayHead)}>\n <button\n type=\"button\"\n tabindex={state.focused && !state.outside ? 0 : -1}\n aria-label={[\n state.today ? lang.calendarToday(label) : label,\n list.length > 0 ? lang.calendarBoardCount(list.length) : null,\n ]\n .filter(Boolean)\n .join(',')}\n aria-disabled={state.disabled || undefined}\n {...css.attrs(\n buttonBaseStyles.root,\n interactionTransitions.colors,\n calendarBoardStyles.day,\n focusRingStyles.tight,\n state.today && calendarBoardStyles.today,\n )}\n data-day=\"\"\n data-focused={(state.focused && !state.outside) || undefined}\n onClick={(event: MouseEvent) => {\n event.stopPropagation();\n if (!state.disabled) calendar.activate(day);\n }}\n onFocus={() => {\n if (!state.focused) calendar.focus(day);\n }}\n >\n {locale.dayNumber(day)}\n </button>\n {getDayNote && <span {...css.attrs(calendarBoardStyles.note)}>{getDayNote(iso)}</span>}\n </div>\n {shown.length > 0 && (\n <ul {...css.attrs(calendarBoardStyles.events)}>\n {shown.map((event, index) => (\n <li key={getEventKey?.(event) ?? index}>\n {renderEvent ? (\n renderEvent(event, iso)\n ) : (\n <span\n {...css.attrs(\n calendarBoardStyles.event,\n statusToneSx('soft', getEventTone?.(event) ?? 'accent'),\n )}\n >\n {getEventLabel?.(event) ?? ''}\n </span>\n )}\n </li>\n ))}\n {list.length > shown.length && (\n <li>\n <button\n type=\"button\"\n {...css.attrs(\n buttonBaseStyles.root,\n interactionTransitions.colors,\n calendarBoardStyles.more,\n focusRingStyles.tight,\n )}\n onClick={(event: MouseEvent) => {\n event.stopPropagation();\n calendar.activate(day);\n }}\n >\n {lang.calendarBoardMore(list.length - shown.length)}\n </button>\n </li>\n )}\n </ul>\n )}\n {renderDay?.(iso, dayState)}\n </td>\n );\n }\n\n return () => {\n const page = calendar.page;\n const title = format.date(page, { year: 'numeric', month: 'long' });\n const weeks = monthGrid(page, { ...locale.week, fixedWeeks: false });\n const names = weekdayNames(locale.locale, {\n firstDayOfWeek: locale.week.firstDayOfWeek,\n format: 'short',\n });\n return (\n <div\n {...mergeAttrs<'div'>({ sx: calendarBoardStyles.root }, rest, {\n ref: _toRef(root),\n role: 'group',\n })}\n >\n <div {...css.attrs(calendarBoardStyles.header)}>\n <span id={titleId} {...css.attrs(calendarBoardStyles.title)}>\n {title}\n </span>\n {toolbar}\n <Button\n {...mergePartProps<ButtonProps>(\n { size: 'sm', variant: 'soft', tone: 'neutral' },\n propsToday,\n {\n onClick: () => {\n calendar.focus(locale.today());\n void nextTick(() =>\n root?.querySelector<HTMLElement>('[data-day][data-focused]')?.focus(),\n );\n },\n },\n )}\n >\n {lang.dateRangePreset.today}\n </Button>\n <IconButton\n icon={ChevronLeft}\n aria-label={lang.calendarPreviousMonth}\n propsIcon={{ flipInRtl: true }}\n size=\"sm\"\n disabled={!calendar.canTurnPage(-1)}\n onClick={() => calendar.turnPage(-1)}\n />\n <IconButton\n icon={ChevronRight}\n aria-label={lang.calendarNextMonth}\n propsIcon={{ flipInRtl: true }}\n size=\"sm\"\n disabled={!calendar.canTurnPage(1)}\n onClick={() => calendar.turnPage(1)}\n />\n </div>\n <table\n {...css.attrs(calendarBoardStyles.grid)}\n role=\"grid\"\n aria-labelledby={titleId}\n onKeydown={onKeydown}\n onPointerleave={() => calendar.hover(null)}\n >\n <thead>\n <tr>\n {names.map((name) => (\n <th key={name} scope=\"col\" {...css.attrs(calendarBoardStyles.weekday)}>\n {name}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {weeks.map((week) => (\n <tr key={week[0]!.toString()}>{week.map((day) => renderCell(day, page))}</tr>\n ))}\n </tbody>\n </table>\n {/* 翻页时播报新的月份 */}\n <VisuallyHidden aria-live=\"polite\">{title}</VisuallyHidden>\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
@@ -12,8 +12,8 @@ import { monthGrid, monthsOfYear, weekOfYear, weekdayNames, yearsOfDecade } from
|
|
|
12
12
|
import { useFormat } from "../config/lang/format.js";
|
|
13
13
|
import { handleCalendarKeydown } from "./calendar-state.js";
|
|
14
14
|
import { useDateLocale } from "./date-locale.js";
|
|
15
|
-
import { createVNode, isVNode,
|
|
16
|
-
import { _component, childrenProp, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
15
|
+
import { createVNode, isVNode, nextTick, shallowRef, useId } from "vue";
|
|
16
|
+
import { _component, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
17
17
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
18
18
|
import { ChevronLeft, ChevronRight } from "@lucide/icons";
|
|
19
19
|
//#region src/date/CalendarView.tsx
|
|
@@ -253,7 +253,7 @@ var CalendarView = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
253
253
|
const range = calendar.value.mode === "range";
|
|
254
254
|
const ends = range && (state.rangeStart || state.rangeEnd);
|
|
255
255
|
const marked = range ? ends : state.selected;
|
|
256
|
-
return createVNode("td",
|
|
256
|
+
return createVNode("td", mergeJsxProps({ "key": iso }, mergeAttrs({ sx: [
|
|
257
257
|
calendarStyles.cell,
|
|
258
258
|
state.inRange && calendarStyles.inRange,
|
|
259
259
|
state.rangeStart && calendarStyles.rangeStart,
|
|
@@ -320,14 +320,14 @@ var CalendarView = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
320
320
|
firstDayOfWeek: locale.week.firstDayOfWeek,
|
|
321
321
|
format: "long"
|
|
322
322
|
});
|
|
323
|
-
return createVNode("table", gridAttrs(title(month)), [createVNode("thead", { "aria-hidden": "true" }, [createVNode("tr", null, [showWeekNumbers.value && createVNode("th", mergeAttrs({ sx: calendarStyles.weekNumber }, propsWeekNumber.value, { scope: "col" }), [lang.calendarWeek]), names.map((name, index) => createVNode("th",
|
|
323
|
+
return createVNode("table", gridAttrs(title(month)), [createVNode("thead", { "aria-hidden": "true" }, [createVNode("tr", null, [showWeekNumbers.value && createVNode("th", mergeAttrs({ sx: calendarStyles.weekNumber }, propsWeekNumber.value, { scope: "col" }), [lang.calendarWeek]), names.map((name, index) => createVNode("th", mergeJsxProps({ "key": index }, mergeAttrs({
|
|
324
324
|
sx: calendarStyles.weekday,
|
|
325
325
|
title: longNames[index]
|
|
326
326
|
}, propsWeekday.value, { scope: "col" })), [name]))])]), createVNode("tbody", null, [weeks.map((week) => createVNode("tr", { "key": week[0].toString() }, [showWeekNumbers.value && createVNode("th", mergeAttrs({ sx: calendarStyles.weekNumber }, propsWeekNumber.value, {
|
|
327
327
|
"aria-label": lang.calendarWeekNumber(weekOfYear(week[0], locale.week)),
|
|
328
328
|
scope: "row"
|
|
329
329
|
}), [weekOfYear(week[0], locale.week)]), week.map((date) => {
|
|
330
|
-
if (date.month !== month.month && !single) return createVNode("td",
|
|
330
|
+
if (date.month !== month.month && !single) return createVNode("td", mergeJsxProps({ "key": date.toString() }, css.attrs(calendarStyles.cell)), null);
|
|
331
331
|
return cell(date, month, format.date(date, { dateStyle: "full" }), children.value ? children.value(locale.toIso(date), calendar.value.cell(date, month)) : locale.dayNumber(date), children.value ? "custom" : "day");
|
|
332
332
|
})]))])]);
|
|
333
333
|
}
|
|
@@ -363,7 +363,7 @@ var CalendarView = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
363
363
|
onClick: () => calendar.value.turnPage(1)
|
|
364
364
|
}), null);
|
|
365
365
|
const spacer = createVNode("span", css.attrs(calendarStyles.spacer), null);
|
|
366
|
-
return createVNode("div",
|
|
366
|
+
return createVNode("div", mergeJsxProps(mergeAttrs({ sx: [calendarStyles.root, size.value && fontSizeStyles[size.value]] }, rest, {
|
|
367
367
|
ref: root,
|
|
368
368
|
role: "group"
|
|
369
369
|
}), {
|
|
@@ -372,7 +372,7 @@ var CalendarView = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
372
372
|
}), [
|
|
373
373
|
createVNode("div", mergeAttrs({ sx: calendarStyles.months }, propsMonths.value), [months.map((month, index) => {
|
|
374
374
|
const label = title(month);
|
|
375
|
-
return createVNode("div",
|
|
375
|
+
return createVNode("div", mergeJsxProps({ "key": month.toString() }, css.attrs(calendarStyles.month)), [createVNode("div", mergeAttrs({ sx: calendarStyles.header }, propsHeader.value), [
|
|
376
376
|
index === 0 ? previous : spacer,
|
|
377
377
|
coarser && !disabled.value ? createVNode("button", mergeAttrs({ sx: [
|
|
378
378
|
buttonBaseStyles.root,
|