@zerodep-dev/vue-tsx-pro-ui 0.3.1 → 0.3.2
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/Blockquote.d.ts +1 -1
- package/dist/base/Blockquote.js +1 -1
- package/dist/base/Blockquote.js.map +1 -1
- package/dist/base/ButtonGroup.d.ts +1 -1
- package/dist/base/ButtonGroup.js +1 -1
- package/dist/base/ButtonGroup.js.map +1 -1
- package/dist/base/Code.d.ts +1 -1
- package/dist/base/Code.js +1 -1
- package/dist/base/Code.js.map +1 -1
- package/dist/base/CodeBlock.d.ts +1 -1
- package/dist/base/CodeBlock.js +1 -1
- package/dist/base/CodeBlock.js.map +1 -1
- package/dist/base/CopyButton.d.ts +1 -1
- package/dist/base/CopyButton.js +1 -1
- package/dist/base/CopyButton.js.map +1 -1
- package/dist/base/Heading.d.ts +1 -1
- package/dist/base/Heading.js +1 -1
- package/dist/base/Heading.js.map +1 -1
- package/dist/base/Icon.d.ts +1 -1
- package/dist/base/Icon.js +1 -1
- package/dist/base/Icon.js.map +1 -1
- package/dist/base/Indicator.d.ts +1 -1
- package/dist/base/Indicator.js +1 -1
- package/dist/base/Indicator.js.map +1 -1
- package/dist/base/Kbd.d.ts +1 -1
- package/dist/base/Kbd.js +1 -1
- package/dist/base/Kbd.js.map +1 -1
- package/dist/base/Link.d.ts +1 -1
- package/dist/base/Link.js +1 -1
- package/dist/base/Link.js.map +1 -1
- package/dist/base/List.d.ts +1 -1
- package/dist/base/List.js +1 -1
- package/dist/base/List.js.map +1 -1
- package/dist/base/Mark.d.ts +1 -1
- package/dist/base/Mark.js +1 -1
- package/dist/base/Mark.js.map +1 -1
- package/dist/base/Spinner.d.ts +1 -1
- package/dist/base/Spinner.js +1 -1
- package/dist/base/Spinner.js.map +1 -1
- package/dist/base/StatusDot.d.ts +1 -1
- package/dist/base/StatusDot.js +1 -1
- package/dist/base/StatusDot.js.map +1 -1
- package/dist/base/Tag.d.ts +1 -1
- package/dist/base/Tag.js +1 -1
- package/dist/base/Tag.js.map +1 -1
- package/dist/base/Text.d.ts +1 -1
- package/dist/base/Text.js +1 -1
- package/dist/base/Text.js.map +1 -1
- package/dist/base/VisuallyHidden.d.ts +1 -1
- package/dist/base/VisuallyHidden.js +1 -1
- package/dist/base/VisuallyHidden.js.map +1 -1
- package/dist/base/badge-styles.d.ts +1 -1
- package/dist/base/badge-styles.js +1 -1
- package/dist/base/badge-styles.js.map +1 -1
- package/dist/base/button-core.d.ts +1 -1
- package/dist/base/button-core.js +1 -1
- package/dist/base/button-core.js.map +1 -1
- package/dist/charts/ChordChart.d.ts +1 -1
- package/dist/charts/ChordChart.js +1 -1
- package/dist/charts/ChordChart.js.map +1 -1
- package/dist/charts/DonutChart.d.ts +1 -1
- package/dist/charts/DonutChart.js +1 -1
- package/dist/charts/DonutChart.js.map +1 -1
- package/dist/charts/FunnelChart.d.ts +1 -1
- package/dist/charts/FunnelChart.js +1 -1
- package/dist/charts/FunnelChart.js.map +1 -1
- package/dist/charts/GraphChart.d.ts +1 -1
- package/dist/charts/GraphChart.js +1 -1
- package/dist/charts/GraphChart.js.map +1 -1
- package/dist/charts/MapChart.d.ts +1 -1
- package/dist/charts/MapChart.js +1 -1
- package/dist/charts/MapChart.js.map +1 -1
- package/dist/charts/RadarChart.d.ts +1 -1
- package/dist/charts/RadarChart.js +1 -1
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/SankeyChart.d.ts +1 -1
- package/dist/charts/SankeyChart.js +1 -1
- package/dist/charts/SankeyChart.js.map +1 -1
- package/dist/charts/TreemapChart.d.ts +1 -1
- package/dist/charts/TreemapChart.js +1 -1
- package/dist/charts/TreemapChart.js.map +1 -1
- package/dist/charts/XYChart.d.ts +1 -1
- package/dist/charts/XYChart.js +1 -1
- package/dist/charts/XYChart.js.map +1 -1
- package/dist/charts/frame.d.ts +1 -1
- package/dist/charts/frame.js +1 -1
- package/dist/charts/frame.js.map +1 -1
- package/dist/code-editor/CodeEditor.js +1 -1
- package/dist/code-editor/CodeEditor.js.map +1 -1
- package/dist/config/Provider.d.ts +1 -1
- package/dist/config/Provider.js +1 -1
- package/dist/config/Provider.js.map +1 -1
- package/dist/config/createUi.d.ts +1 -1
- package/dist/config/createUi.js +1 -1
- package/dist/config/createUi.js.map +1 -1
- package/dist/config/theme/coffee.d.ts +1 -1
- package/dist/config/theme/coffee.js +1 -1
- package/dist/config/theme/coffee.js.map +1 -1
- package/dist/config/theme/cyberpunk.d.ts +1 -1
- package/dist/config/theme/cyberpunk.js +1 -1
- package/dist/config/theme/cyberpunk.js.map +1 -1
- package/dist/config/theme/dark.d.ts +1 -1
- package/dist/config/theme/dark.js +1 -1
- package/dist/config/theme/dark.js.map +1 -1
- package/dist/config/theme/festive.d.ts +1 -1
- package/dist/config/theme/festive.js +1 -1
- package/dist/config/theme/festive.js.map +1 -1
- package/dist/config/theme/forest.d.ts +1 -1
- package/dist/config/theme/forest.js +1 -1
- package/dist/config/theme/forest.js.map +1 -1
- package/dist/config/theme/high-contrast.d.ts +1 -1
- package/dist/config/theme/high-contrast.js +1 -1
- package/dist/config/theme/high-contrast.js.map +1 -1
- package/dist/config/theme/lemon.d.ts +1 -1
- package/dist/config/theme/lemon.js +1 -1
- package/dist/config/theme/lemon.js.map +1 -1
- package/dist/config/theme/light.d.ts +1 -1
- package/dist/config/theme/light.js +1 -1
- package/dist/config/theme/light.js.map +1 -1
- package/dist/config/theme/midnight.d.ts +1 -1
- package/dist/config/theme/midnight.js +1 -1
- package/dist/config/theme/midnight.js.map +1 -1
- package/dist/config/theme/ocean.d.ts +1 -1
- package/dist/config/theme/ocean.js +1 -1
- package/dist/config/theme/ocean.js.map +1 -1
- package/dist/config/theme/paper.d.ts +1 -1
- package/dist/config/theme/paper.js +1 -1
- package/dist/config/theme/paper.js.map +1 -1
- package/dist/config/theme/sakura.d.ts +1 -1
- package/dist/config/theme/sakura.js +1 -1
- package/dist/config/theme/sakura.js.map +1 -1
- package/dist/config/theme/theme.js +1 -1
- package/dist/config/theme/theme.js.map +1 -1
- package/dist/config/theme/tokens.d.ts +1 -1
- package/dist/config/theme/tokens.js +1 -1
- package/dist/config/theme/tokens.js.map +1 -1
- package/dist/date/CalendarBoard.d.ts +1 -1
- package/dist/date/CalendarBoard.js +1 -1
- package/dist/date/CalendarBoard.js.map +1 -1
- package/dist/date/CalendarView.d.ts +1 -1
- package/dist/date/CalendarView.js +1 -1
- package/dist/date/CalendarView.js.map +1 -1
- package/dist/date/Countdown.d.ts +1 -1
- package/dist/date/Countdown.js +1 -1
- package/dist/date/Countdown.js.map +1 -1
- package/dist/date/DatePicker.d.ts +1 -1
- package/dist/date/DatePicker.js +1 -1
- package/dist/date/DatePicker.js.map +1 -1
- package/dist/date/DateRangePicker.d.ts +1 -1
- package/dist/date/DateRangePicker.js +1 -1
- package/dist/date/DateRangePicker.js.map +1 -1
- package/dist/date/DateSegmentGroup.d.ts +1 -1
- package/dist/date/DateSegmentGroup.js +1 -1
- package/dist/date/DateSegmentGroup.js.map +1 -1
- package/dist/date/QuarterCalendar.js +1 -1
- package/dist/date/QuarterCalendar.js.map +1 -1
- package/dist/date/SegmentedField.d.ts +1 -1
- package/dist/date/SegmentedField.js +1 -1
- package/dist/date/SegmentedField.js.map +1 -1
- package/dist/date/TimePicker.d.ts +1 -1
- package/dist/date/TimePicker.js +1 -1
- package/dist/date/TimePicker.js.map +1 -1
- package/dist/date/picker-popover.d.ts +1 -1
- package/dist/date/picker-popover.js +1 -1
- package/dist/date/picker-popover.js.map +1 -1
- package/dist/diagram/Diagram.d.ts +1 -1
- package/dist/diagram/Diagram.js +1 -1
- package/dist/diagram/Diagram.js.map +1 -1
- package/dist/diagram/DiagramControls.d.ts +1 -1
- package/dist/diagram/DiagramControls.js +1 -1
- package/dist/diagram/DiagramControls.js.map +1 -1
- package/dist/diagram/DiagramLanes.d.ts +1 -1
- package/dist/diagram/DiagramLanes.js +1 -1
- package/dist/diagram/DiagramLanes.js.map +1 -1
- package/dist/diagram/DiagramMinimap.d.ts +1 -1
- package/dist/diagram/DiagramMinimap.js +1 -1
- package/dist/diagram/DiagramMinimap.js.map +1 -1
- package/dist/diagram/DiagramNode.d.ts +1 -1
- package/dist/diagram/DiagramNode.js +1 -1
- package/dist/diagram/DiagramNode.js.map +1 -1
- package/dist/display/Accordion.d.ts +1 -1
- package/dist/display/Accordion.js +1 -1
- package/dist/display/Accordion.js.map +1 -1
- package/dist/display/AnimatedNumber.d.ts +1 -1
- package/dist/display/AnimatedNumber.js +1 -1
- package/dist/display/AnimatedNumber.js.map +1 -1
- package/dist/display/Avatar.d.ts +1 -1
- package/dist/display/Avatar.js +1 -1
- package/dist/display/Avatar.js.map +1 -1
- package/dist/display/AvatarGroup.d.ts +1 -1
- package/dist/display/AvatarGroup.js +1 -1
- package/dist/display/AvatarGroup.js.map +1 -1
- package/dist/display/Card.d.ts +1 -1
- package/dist/display/Card.js +1 -1
- package/dist/display/Card.js.map +1 -1
- package/dist/display/Checklist.d.ts +1 -1
- package/dist/display/Checklist.js +1 -1
- package/dist/display/Checklist.js.map +1 -1
- package/dist/display/Collapse.d.ts +1 -1
- package/dist/display/Collapse.js +1 -1
- package/dist/display/Collapse.js.map +1 -1
- package/dist/display/Descriptions.d.ts +1 -1
- package/dist/display/Descriptions.js +1 -1
- package/dist/display/Descriptions.js.map +1 -1
- package/dist/display/Ellipsis.d.ts +1 -1
- package/dist/display/Ellipsis.js +1 -1
- package/dist/display/Ellipsis.js.map +1 -1
- package/dist/display/FieldCompare.d.ts +1 -1
- package/dist/display/FieldCompare.js +1 -1
- package/dist/display/FieldCompare.js.map +1 -1
- package/dist/display/Gauge.d.ts +1 -1
- package/dist/display/Gauge.js +1 -1
- package/dist/display/Gauge.js.map +1 -1
- package/dist/display/Image.d.ts +1 -1
- package/dist/display/Image.js +1 -1
- package/dist/display/Image.js.map +1 -1
- package/dist/display/ItemList.d.ts +1 -1
- package/dist/display/ItemList.js +1 -1
- package/dist/display/ItemList.js.map +1 -1
- package/dist/display/Marquee.d.ts +1 -1
- package/dist/display/Marquee.js +1 -1
- package/dist/display/Marquee.js.map +1 -1
- package/dist/display/ProportionBar.d.ts +1 -1
- package/dist/display/ProportionBar.js +1 -1
- package/dist/display/ProportionBar.js.map +1 -1
- package/dist/display/Sortable.d.ts +1 -1
- package/dist/display/Sortable.js +1 -1
- package/dist/display/Sortable.js.map +1 -1
- package/dist/display/Sparkline.d.ts +1 -1
- package/dist/display/Sparkline.js +1 -1
- package/dist/display/Sparkline.js.map +1 -1
- package/dist/display/Stat.d.ts +1 -1
- package/dist/display/Stat.js +1 -1
- package/dist/display/Stat.js.map +1 -1
- package/dist/display/Timeline.d.ts +1 -1
- package/dist/display/Timeline.js +1 -1
- package/dist/display/Timeline.js.map +1 -1
- package/dist/display/Tree.d.ts +1 -1
- package/dist/display/Tree.js +1 -1
- package/dist/display/Tree.js.map +1 -1
- package/dist/display/VirtualList.d.ts +1 -1
- package/dist/display/VirtualList.js +1 -1
- package/dist/display/VirtualList.js.map +1 -1
- package/dist/display/Watermark.d.ts +1 -1
- package/dist/display/Watermark.js +1 -1
- package/dist/display/Watermark.js.map +1 -1
- package/dist/docs-kit/CodeGroup.d.ts +1 -1
- package/dist/docs-kit/CodeGroup.js +1 -1
- package/dist/docs-kit/CodeGroup.js.map +1 -1
- package/dist/docs-kit/CodePreview.d.ts +1 -1
- package/dist/docs-kit/CodePreview.js +1 -1
- package/dist/docs-kit/CodePreview.js.map +1 -1
- package/dist/docs-kit/ColorSwatch.d.ts +1 -1
- package/dist/docs-kit/ColorSwatch.js +1 -1
- package/dist/docs-kit/ColorSwatch.js.map +1 -1
- package/dist/docs-kit/PropsTable.d.ts +1 -1
- package/dist/docs-kit/PropsTable.js +1 -1
- package/dist/docs-kit/PropsTable.js.map +1 -1
- package/dist/feedback/Alert.d.ts +1 -1
- package/dist/feedback/Alert.js +1 -1
- package/dist/feedback/Alert.js.map +1 -1
- package/dist/feedback/Banner.d.ts +1 -1
- package/dist/feedback/Banner.js +1 -1
- package/dist/feedback/Banner.js.map +1 -1
- package/dist/feedback/Empty.d.ts +1 -1
- package/dist/feedback/Empty.js +1 -1
- package/dist/feedback/Empty.js.map +1 -1
- package/dist/feedback/LoadingBar.d.ts +1 -1
- package/dist/feedback/LoadingBar.js +1 -1
- package/dist/feedback/LoadingBar.js.map +1 -1
- package/dist/feedback/LoadingOverlay.d.ts +1 -1
- package/dist/feedback/LoadingOverlay.js +1 -1
- package/dist/feedback/LoadingOverlay.js.map +1 -1
- package/dist/feedback/Progress.d.ts +1 -1
- package/dist/feedback/Progress.js +1 -1
- package/dist/feedback/Progress.js.map +1 -1
- package/dist/feedback/Result.d.ts +1 -1
- package/dist/feedback/Result.js +1 -1
- package/dist/feedback/Result.js.map +1 -1
- package/dist/feedback/Skeleton.d.ts +1 -1
- package/dist/feedback/Skeleton.js +1 -1
- package/dist/feedback/Skeleton.js.map +1 -1
- package/dist/feedback/SkeletonText.d.ts +1 -1
- package/dist/feedback/SkeletonText.js +1 -1
- package/dist/feedback/SkeletonText.js.map +1 -1
- package/dist/feedback/Toast.d.ts +1 -1
- package/dist/feedback/Toast.js +1 -1
- package/dist/feedback/Toast.js.map +1 -1
- package/dist/form/Field.d.ts +1 -1
- package/dist/form/Field.js +1 -1
- package/dist/form/Field.js.map +1 -1
- package/dist/form/FormErrorSummary.d.ts +1 -1
- package/dist/form/FormErrorSummary.js +1 -1
- package/dist/form/FormErrorSummary.js.map +1 -1
- package/dist/form/FormSection.d.ts +1 -1
- package/dist/form/FormSection.js +1 -1
- package/dist/form/FormSection.js.map +1 -1
- package/dist/form/schemas.d.ts +1 -1
- package/dist/form/schemas.js +1 -1
- package/dist/form/schemas.js.map +1 -1
- package/dist/input/Cascader.d.ts +1 -1
- package/dist/input/Cascader.js +1 -1
- package/dist/input/Cascader.js.map +1 -1
- package/dist/input/CharacterCount.d.ts +1 -1
- package/dist/input/CharacterCount.js +1 -1
- package/dist/input/CharacterCount.js.map +1 -1
- package/dist/input/Checkbox.d.ts +1 -1
- package/dist/input/Checkbox.js +1 -1
- package/dist/input/Checkbox.js.map +1 -1
- package/dist/input/ColorField.d.ts +1 -1
- package/dist/input/ColorField.js +1 -1
- package/dist/input/ColorField.js.map +1 -1
- package/dist/input/Combobox.d.ts +1 -1
- package/dist/input/Combobox.js +1 -1
- package/dist/input/Combobox.js.map +1 -1
- package/dist/input/ConditionBuilder.d.ts +1 -1
- package/dist/input/ConditionBuilder.js +1 -1
- package/dist/input/ConditionBuilder.js.map +1 -1
- package/dist/input/ControlGroup.d.ts +1 -1
- package/dist/input/ControlGroup.js +1 -1
- package/dist/input/ControlGroup.js.map +1 -1
- package/dist/input/FileDrop.d.ts +1 -1
- package/dist/input/FileDrop.js +1 -1
- package/dist/input/FileDrop.js.map +1 -1
- package/dist/input/ListPopover.d.ts +1 -1
- package/dist/input/ListPopover.js +1 -1
- package/dist/input/ListPopover.js.map +1 -1
- package/dist/input/Listbox.d.ts +1 -1
- package/dist/input/Listbox.js +1 -1
- package/dist/input/Listbox.js.map +1 -1
- package/dist/input/Mentions.d.ts +1 -1
- package/dist/input/Mentions.js +1 -1
- package/dist/input/Mentions.js.map +1 -1
- package/dist/input/NumberRangeField.d.ts +1 -1
- package/dist/input/NumberRangeField.js +1 -1
- package/dist/input/NumberRangeField.js.map +1 -1
- package/dist/input/OtpField.d.ts +1 -1
- package/dist/input/OtpField.js +1 -1
- package/dist/input/OtpField.js.map +1 -1
- package/dist/input/PeoplePicker.js +1 -1
- package/dist/input/PeoplePicker.js.map +1 -1
- package/dist/input/PeoplePickerPanel.d.ts +1 -1
- package/dist/input/PeoplePickerPanel.js +1 -1
- package/dist/input/PeoplePickerPanel.js.map +1 -1
- package/dist/input/Radio.d.ts +1 -1
- package/dist/input/Radio.js +1 -1
- package/dist/input/Radio.js.map +1 -1
- package/dist/input/Rating.d.ts +1 -1
- package/dist/input/Rating.js +1 -1
- package/dist/input/Rating.js.map +1 -1
- package/dist/input/Select.d.ts +1 -1
- package/dist/input/Select.js +1 -1
- package/dist/input/Select.js.map +1 -1
- package/dist/input/SelectedTags.d.ts +1 -1
- package/dist/input/SelectedTags.js +1 -1
- package/dist/input/SelectedTags.js.map +1 -1
- package/dist/input/Slider.d.ts +1 -1
- package/dist/input/Slider.js +1 -1
- package/dist/input/Slider.js.map +1 -1
- package/dist/input/Switch.d.ts +1 -1
- package/dist/input/Switch.js +1 -1
- package/dist/input/Switch.js.map +1 -1
- package/dist/input/TagsInput.d.ts +1 -1
- package/dist/input/TagsInput.js +1 -1
- package/dist/input/TagsInput.js.map +1 -1
- package/dist/input/Textarea.d.ts +1 -1
- package/dist/input/Textarea.js +1 -1
- package/dist/input/Textarea.js.map +1 -1
- package/dist/input/ToggleGroup.d.ts +1 -1
- package/dist/input/ToggleGroup.js +1 -1
- package/dist/input/ToggleGroup.js.map +1 -1
- package/dist/input/Transfer.d.ts +1 -1
- package/dist/input/Transfer.js +1 -1
- package/dist/input/Transfer.js.map +1 -1
- package/dist/input/TreeSelect.d.ts +1 -1
- package/dist/input/TreeSelect.js +1 -1
- package/dist/input/TreeSelect.js.map +1 -1
- package/dist/input/Upload.d.ts +1 -1
- package/dist/input/Upload.js +1 -1
- package/dist/input/Upload.js.map +1 -1
- package/dist/input/choice-styles.d.ts +1 -1
- package/dist/input/choice-styles.js +1 -1
- package/dist/input/choice-styles.js.map +1 -1
- package/dist/input/control.d.ts +1 -1
- package/dist/input/control.js +1 -1
- package/dist/input/control.js.map +1 -1
- package/dist/layout/Affix.d.ts +1 -1
- package/dist/layout/Affix.js +1 -1
- package/dist/layout/Affix.js.map +1 -1
- package/dist/layout/AsideLayout.d.ts +1 -1
- package/dist/layout/AsideLayout.js +1 -1
- package/dist/layout/AsideLayout.js.map +1 -1
- package/dist/layout/BackTop.d.ts +1 -1
- package/dist/layout/BackTop.js +1 -1
- package/dist/layout/BackTop.js.map +1 -1
- package/dist/layout/Container.d.ts +1 -1
- package/dist/layout/Container.js +1 -1
- package/dist/layout/Container.js.map +1 -1
- package/dist/layout/Flex.d.ts +1 -1
- package/dist/layout/Flex.js +1 -1
- package/dist/layout/Flex.js.map +1 -1
- package/dist/layout/Grid.d.ts +1 -1
- package/dist/layout/Grid.js +1 -1
- package/dist/layout/Grid.js.map +1 -1
- package/dist/layout/PageScrollbar.d.ts +1 -1
- package/dist/layout/PageScrollbar.js +1 -1
- package/dist/layout/PageScrollbar.js.map +1 -1
- package/dist/layout/Prose.d.ts +1 -1
- package/dist/layout/Prose.js +1 -1
- package/dist/layout/Prose.js.map +1 -1
- package/dist/layout/ResizeHandle.d.ts +1 -1
- package/dist/layout/ResizeHandle.js +1 -1
- package/dist/layout/ResizeHandle.js.map +1 -1
- package/dist/layout/ScrollArea.d.ts +1 -1
- package/dist/layout/ScrollArea.js +1 -1
- package/dist/layout/ScrollArea.js.map +1 -1
- package/dist/layout/Separator.d.ts +1 -1
- package/dist/layout/Separator.js +1 -1
- package/dist/layout/Separator.js.map +1 -1
- package/dist/layout/Splitter.d.ts +1 -1
- package/dist/layout/Splitter.js +1 -1
- package/dist/layout/Splitter.js.map +1 -1
- package/dist/layout/ViewportFill.d.ts +1 -1
- package/dist/layout/ViewportFill.js +1 -1
- package/dist/layout/ViewportFill.js.map +1 -1
- package/dist/navigation/Breadcrumbs.d.ts +1 -1
- package/dist/navigation/Breadcrumbs.js +1 -1
- package/dist/navigation/Breadcrumbs.js.map +1 -1
- package/dist/navigation/NavBar.d.ts +1 -1
- package/dist/navigation/NavBar.js +1 -1
- package/dist/navigation/NavBar.js.map +1 -1
- package/dist/navigation/NavList.d.ts +1 -1
- package/dist/navigation/NavList.js +1 -1
- package/dist/navigation/NavList.js.map +1 -1
- package/dist/navigation/PageJump.d.ts +1 -1
- package/dist/navigation/PageJump.js +1 -1
- package/dist/navigation/PageJump.js.map +1 -1
- package/dist/navigation/PageSizeSelect.d.ts +1 -1
- package/dist/navigation/PageSizeSelect.js +1 -1
- package/dist/navigation/PageSizeSelect.js.map +1 -1
- package/dist/navigation/Pager.d.ts +1 -1
- package/dist/navigation/Pager.js +1 -1
- package/dist/navigation/Pager.js.map +1 -1
- package/dist/navigation/Pagination.d.ts +1 -1
- package/dist/navigation/Pagination.js +1 -1
- package/dist/navigation/Pagination.js.map +1 -1
- package/dist/navigation/PaginationBar.d.ts +1 -1
- package/dist/navigation/PaginationBar.js +1 -1
- package/dist/navigation/PaginationBar.js.map +1 -1
- package/dist/navigation/SkipLink.d.ts +1 -1
- package/dist/navigation/SkipLink.js +1 -1
- package/dist/navigation/SkipLink.js.map +1 -1
- package/dist/navigation/Steps.d.ts +1 -1
- package/dist/navigation/Steps.js +1 -1
- package/dist/navigation/Steps.js.map +1 -1
- package/dist/navigation/TableOfContents.d.ts +1 -1
- package/dist/navigation/TableOfContents.js +1 -1
- package/dist/navigation/TableOfContents.js.map +1 -1
- package/dist/navigation/Tabs.d.ts +1 -1
- package/dist/navigation/Tabs.js +1 -1
- package/dist/navigation/Tabs.js.map +1 -1
- package/dist/navigation/Toolbar.d.ts +1 -1
- package/dist/navigation/Toolbar.js +1 -1
- package/dist/navigation/Toolbar.js.map +1 -1
- package/dist/overlay/CommandPalette.d.ts +1 -1
- package/dist/overlay/CommandPalette.js +1 -1
- package/dist/overlay/CommandPalette.js.map +1 -1
- package/dist/overlay/Dialog.d.ts +1 -1
- package/dist/overlay/Dialog.js +1 -1
- package/dist/overlay/Dialog.js.map +1 -1
- package/dist/overlay/Drawer.d.ts +1 -1
- package/dist/overlay/Drawer.js +1 -1
- package/dist/overlay/Drawer.js.map +1 -1
- package/dist/overlay/HoverCard.d.ts +1 -1
- package/dist/overlay/HoverCard.js +1 -1
- package/dist/overlay/HoverCard.js.map +1 -1
- package/dist/overlay/Lightbox.d.ts +1 -1
- package/dist/overlay/Lightbox.js +1 -1
- package/dist/overlay/Lightbox.js.map +1 -1
- package/dist/overlay/Menu.d.ts +1 -1
- package/dist/overlay/Menu.js +1 -1
- package/dist/overlay/Menu.js.map +1 -1
- package/dist/overlay/Popconfirm.d.ts +1 -1
- package/dist/overlay/Popconfirm.js +1 -1
- package/dist/overlay/Popconfirm.js.map +1 -1
- package/dist/overlay/Popover.d.ts +1 -1
- package/dist/overlay/Popover.js +1 -1
- package/dist/overlay/Popover.js.map +1 -1
- package/dist/overlay/Tooltip.d.ts +1 -1
- package/dist/overlay/Tooltip.js +1 -1
- package/dist/overlay/Tooltip.js.map +1 -1
- package/dist/overlay/Tour.d.ts +1 -1
- package/dist/overlay/Tour.js +1 -1
- package/dist/overlay/Tour.js.map +1 -1
- package/dist/patterns/ActionBar.d.ts +1 -1
- package/dist/patterns/ActionBar.js +1 -1
- package/dist/patterns/ActionBar.js.map +1 -1
- package/dist/patterns/AppShell.d.ts +1 -1
- package/dist/patterns/AppShell.js +1 -1
- package/dist/patterns/AppShell.js.map +1 -1
- package/dist/patterns/AuthLayout.d.ts +2 -2
- package/dist/patterns/AuthLayout.js +2 -2
- package/dist/patterns/AuthLayout.js.map +1 -1
- package/dist/patterns/CommentThread.d.ts +1 -1
- package/dist/patterns/CommentThread.js +1 -1
- package/dist/patterns/CommentThread.js.map +1 -1
- package/dist/patterns/DataImport.d.ts +1 -1
- package/dist/patterns/DataImport.js +1 -1
- package/dist/patterns/DataImport.js.map +1 -1
- package/dist/patterns/FilterBar.d.ts +1 -1
- package/dist/patterns/FilterBar.js +1 -1
- package/dist/patterns/FilterBar.js.map +1 -1
- package/dist/patterns/KanbanBoard.d.ts +1 -1
- package/dist/patterns/KanbanBoard.js +1 -1
- package/dist/patterns/KanbanBoard.js.map +1 -1
- package/dist/patterns/NotificationCenter.d.ts +1 -1
- package/dist/patterns/NotificationCenter.js +1 -1
- package/dist/patterns/NotificationCenter.js.map +1 -1
- package/dist/patterns/QueryTable.d.ts +1 -1
- package/dist/patterns/QueryTable.js +1 -1
- package/dist/patterns/QueryTable.js.map +1 -1
- package/dist/patterns/SlideCaptcha.d.ts +1 -1
- package/dist/patterns/SlideCaptcha.js +1 -1
- package/dist/patterns/SlideCaptcha.js.map +1 -1
- package/dist/patterns/StepsForm.d.ts +1 -1
- package/dist/patterns/StepsForm.js +1 -1
- package/dist/patterns/StepsForm.js.map +1 -1
- package/dist/table/ColumnHeaderActions.d.ts +1 -1
- package/dist/table/ColumnHeaderActions.js +1 -1
- package/dist/table/ColumnHeaderActions.js.map +1 -1
- package/dist/table/ColumnSettings.d.ts +1 -1
- package/dist/table/ColumnSettings.js +1 -1
- package/dist/table/ColumnSettings.js.map +1 -1
- package/dist/table/ColumnTable.d.ts +1 -1
- package/dist/table/ColumnTable.js +1 -1
- package/dist/table/ColumnTable.js.map +1 -1
- package/dist/table/DataTableView.d.ts +1 -1
- package/dist/table/DataTableView.js +1 -1
- package/dist/table/DataTableView.js.map +1 -1
- package/dist/table/PivotTable.d.ts +1 -1
- package/dist/table/PivotTable.js +1 -1
- package/dist/table/PivotTable.js.map +1 -1
- package/dist/table/SelectionBar.d.ts +1 -1
- package/dist/table/SelectionBar.js +1 -1
- package/dist/table/SelectionBar.js.map +1 -1
- package/dist/table/Table.d.ts +1 -1
- package/dist/table/Table.js +1 -1
- package/dist/table/Table.js.map +1 -1
- package/dist/table/TreeDataTable.d.ts +1 -1
- package/dist/table/TreeDataTable.js +1 -1
- package/dist/table/TreeDataTable.js.map +1 -1
- package/dist/table/table-styles.d.ts +1 -1
- package/dist/table/table-styles.js +1 -1
- package/dist/table/table-styles.js.map +1 -1
- package/dist/theme-customize/ThemeCustomizer.d.ts +1 -1
- package/dist/theme-customize/ThemeCustomizer.js +1 -1
- package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
- package/dist/theme-customize/ThemeThumbnail.d.ts +1 -1
- package/dist/theme-customize/ThemeThumbnail.js +1 -1
- package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
- package/dist/theme-customize/design-tokens.js +1 -1
- package/dist/theme-customize/design-tokens.js.map +1 -1
- package/dist/three/core/EffectSurface.d.ts +1 -1
- package/dist/three/core/EffectSurface.js +1 -1
- package/dist/three/core/EffectSurface.js.map +1 -1
- package/dist/three/core/ThreeCanvas.d.ts +1 -1
- package/dist/three/core/ThreeCanvas.js +1 -1
- package/dist/three/core/ThreeCanvas.js.map +1 -1
- package/dist/three/effects/Confetti.d.ts +1 -1
- package/dist/three/effects/Confetti.js +1 -1
- package/dist/three/effects/Confetti.js.map +1 -1
- package/dist/three/globe/Globe.d.ts +1 -1
- package/dist/three/globe/Globe.js +1 -1
- package/dist/three/globe/Globe.js.map +1 -1
- package/dist/three/model/ModelViewer.d.ts +1 -1
- package/dist/three/model/ModelViewer.js +1 -1
- package/dist/three/model/ModelViewer.js.map +1 -1
- package/dist/utils/dom/floating.d.ts +1 -1
- package/dist/utils/dom/floating.js +1 -1
- package/dist/utils/dom/floating.js.map +1 -1
- package/dist/utils/dom/ripple.d.ts +1 -1
- package/dist/utils/dom/ripple.js +1 -1
- package/dist/utils/dom/ripple.js.map +1 -1
- package/dist/utils/props.js +1 -1
- package/dist/utils/props.js.map +1 -1
- package/dist/utils/style/attached.d.ts +1 -1
- package/dist/utils/style/attached.js +1 -1
- package/dist/utils/style/attached.js.map +1 -1
- package/dist/utils/style/item-styles.d.ts +1 -1
- package/dist/utils/style/item-styles.js +1 -1
- package/dist/utils/style/item-styles.js.map +1 -1
- package/dist/utils/style/markers.d.ts +1 -1
- package/dist/utils/style/markers.js +1 -1
- package/dist/utils/style/markers.js.map +1 -1
- package/dist/utils/style/shimmer.d.ts +1 -1
- package/dist/utils/style/shimmer.js +1 -1
- package/dist/utils/style/shimmer.js.map +1 -1
- package/dist/utils/style/styles.d.ts +1 -1
- package/dist/utils/style/styles.js +1 -1
- package/dist/utils/style/styles.js.map +1 -1
- package/dist/utils/style/swatch-styles.d.ts +1 -1
- package/dist/utils/style/swatch-styles.js +1 -1
- package/dist/utils/style/swatch-styles.js.map +1 -1
- package/dist/utils/style/tone-styles.d.ts +1 -1
- package/dist/utils/style/tone-styles.js +1 -1
- package/dist/utils/style/tone-styles.js.map +1 -1
- package/dist/utils/style/transitions.d.ts +1 -1
- package/dist/utils/style/transitions.js +1 -1
- package/dist/utils/style/transitions.js.map +1 -1
- package/dist/utils/style/typography.d.ts +1 -1
- package/dist/utils/style/typography.js +1 -1
- package/dist/utils/style/typography.js.map +1 -1
- package/dist/utils/style/vars.d.ts +1 -1
- package/dist/utils/style/vars.js +1 -1
- package/dist/utils/style/vars.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapChart.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps","_createTextVNode","_vue_ref"],"sources":["../../src/charts/MapChart.tsx"],"sourcesContent":["/**\n * 地图:按区域着色(分省的销售额、各国的采购额),标出地点(工厂、供应商)与它们之间的流向。\n * 地理数据是 TopoJSON:Unovis 自带中国省份、世界、美国等(`@unovis/ts/maps`),也可以用自己的。\n *\n * import { ChinaTopoJSON } from '@unovis/ts/maps';\n * <MapChart\n * aria-label=\"各省销售额\"\n * topology={ChinaTopoJSON}\n * feature=\"provinces\"\n * areas={[{ id: 'CN-JS', label: '江苏', value: 623 }, …]} // id 是地图要素的 id\n * points={[{ id: 'sh', label: '上海组装', longitude: 121.47, latitude: 31.23, value: 860 }]}\n * links={[{ from: 'xa', to: 'sh', value: 120 }]}\n * bins={5}\n * areaLabels\n * />\n *\n * 投影:默认按地理数据的范围选——一个国家、一个地区用以它为中心的等积圆锥投影(中国地图常用的 Albers,正着、不歪),\n * 跨了大半个地球时用 Natural Earth;也可以指定 mercator、equalEarth、orthographic(地球仪)或自己的 d3 投影。\n *\n * 着色:sequential(默认)按数值深浅;diverging 以 midpoint 为界两头两种颜色(同比的涨跌);\n * bins 分成几档(分级着色,图例是几个色块),不写时连续着色(图例是色带);区域写了 color 时按它(分类着色)。\n * 没有数据的区域是底色。地点:value 决定大小(面积按比例),color、shape 决定颜色与形状;名字自动避让\n * (换方位、挤时往外退并画引线,数值大的先放,放不下的悬停看;压住名字、地点的区域名藏起来);\n * links 是地点之间的流向,粗细按 value,flow 时有流动的粒子。\n * zoomable 时可以拖动、按住 Ctrl 滚轮缩放,右上角有放大、缩小、复位的按钮。悬停看名称与数值;读屏的数据表列出各区域、地点与流向。\n */\nimport {\n MapProjection,\n TopoJSONMap,\n type MapGraphData,\n type TopoJSONMapConfigInterface,\n} from '@unovis/ts';\nimport { Maximize, Minus, Plus } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { presimplify, simplify } from 'topojson-simplify';\nimport type { VNodeChild } from 'vue';\nimport { IconButton } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { colors } from '../config/theme/tokens';\nimport { Skeleton } from '../feedback/Skeleton';\nimport { toNumber, type NumericValue } from '../utils/data/numeric';\nimport { useEventListener } from '../utils/dom/event-listener';\nimport type { PartProps } from '../utils/props';\nimport { chartTooltip, ChartFrame, type ChartFrameParts } from './frame';\nimport { placeLabels, rectsOverlap, type LabelRect } from './label-layout';\nimport { resolveColor, type ChartColor } from './series';\nimport { useSingleChart, type SingleChart } from './single';\n\n/** 一个区域的数据 */\nexport interface MapArea {\n /** 地图要素的 id(Unovis 的中国省份是 'CN-JS' 这样的写法) */\n id: string;\n /** 显示的名称:提示框、区域名、数据表 */\n label: string;\n /** 数值:决定颜色 */\n value?: NumericValue;\n /** 指定颜色:不按数值着色(分类着色,如所属大区) */\n color?: ChartColor;\n}\n\n/** 一个地点 */\nexport interface MapPoint {\n /** 标识:流向的 from、to 指向它 */\n id: string;\n /** 名称:写在点下方 */\n label: string;\n /** 经度 */\n longitude: number;\n /** 纬度 */\n latitude: number;\n /** 数值:决定点的大小(面积按比例),也显示在提示框 */\n value?: NumericValue;\n /** 颜色,默认 danger */\n color?: ChartColor;\n /** 形状,默认 circle */\n shape?: 'circle' | 'square' | 'triangle';\n}\n\n/** 两个地点之间的流向 */\nexport interface MapLink {\n /** 起点(地点的 id) */\n from: string;\n /** 终点(地点的 id) */\n to: string;\n /** 数值:决定线的粗细,也显示在数据表 */\n value?: NumericValue;\n /** 颜色,默认次要色 */\n color?: ChartColor;\n}\n\n/** 投影的预设 */\nexport interface MapProjections {\n /** 等积圆锥(Albers):以数据为中心,一个国家、一个地区用它(中国地图常用),正着、面积不失真 */\n conic: unknown;\n /** 墨卡托:网页地图常见,高纬度会放大 */\n mercator: unknown;\n /** Natural Earth:世界地图,形状与面积都比较自然 */\n naturalEarth: unknown;\n /** Equal Earth:世界地图,面积准确 */\n equalEarth: unknown;\n /** 正射(地球仪):以数据为中心看半个地球 */\n orthographic: unknown;\n}\n\n/** d3 的投影(TopoJSONMap 的 projection) */\nexport type MapGeoProjection = NonNullable<TopoJSONMapConfigInterface<MapArea>['projection']>;\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface MapChartProps extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 地理数据(TopoJSON),如 `@unovis/ts/maps` 的 ChinaTopoJSON、WorldMapTopoJSON */\n topology: NonNullable<TopoJSONMapConfigInterface<MapArea>['topojson']>;\n /** 画哪一组要素(TopoJSON 的 objects 里的名字),如中国省份是 'provinces'、世界是 'countries' */\n feature: string;\n /** 投影:预设的名字,或 d3 的投影;不写时按数据的范围选 conic 或 naturalEarth */\n projection?: keyof MapProjections | MapGeoProjection;\n /** 投影的中心 [经度, 纬度]:中央经线(世界地图写 [150, 0] 以太平洋为中心),orthographic 还用纬度;不写时取地理数据范围的中心 */\n center?: readonly [number, number];\n /** 各区域的数值 */\n areas?: readonly MapArea[];\n /** 地点 */\n points?: readonly MapPoint[];\n /** 地点之间的流向 */\n links?: readonly MapLink[];\n /** 着色方式:sequential 按数值深浅(默认),diverging 以 midpoint 为界两头两种颜色 */\n scheme?: 'sequential' | 'diverging';\n /** sequential 的基色,默认 accent */\n color?: ChartColor;\n /** diverging 的两头 [低, 高],默认 ['danger', 'success'] */\n divergingColors?: readonly [ChartColor, ChartColor];\n /** diverging 的分界,默认 0 */\n midpoint?: number;\n /** 分成几档(分级着色);不写时连续着色 */\n bins?: number;\n /** 在区域上写名字(区域够大时) */\n areaLabels?: boolean;\n /** 流向上有流动的粒子 */\n flow?: boolean;\n /** 数值的格式 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方,提示框与数据表的数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 400\n */\n height?: number | string;\n /** 可以拖动、滚轮缩放,右上角有放大、缩小、复位的按钮;默认关(不抢页面的滚动) */\n zoomable?: boolean;\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n /** 悬停时的提示框,默认 true */\n tooltip?: boolean;\n /** 点了一个有数据的区域 */\n onAreaClick?: (area: MapArea) => void;\n /** 点了一个地点 */\n onPointClick?: (point: MapPoint) => void;\n}\n\n/** MapChart 的样式 */\nexport const mapChartStyles = css.create({\n // 地图跟随主题:底色、边界是表面色,文字是正文色\n root: {\n '--vis-map-feature-color': colors.fill,\n '--vis-map-boundary-color': colors.surface,\n '--vis-map-point-label-text-color-dark': colors.text,\n '--vis-map-point-label-text-color-light': colors.text,\n '--vis-map-area-label-text-color': colors.text,\n '--vis-map-area-label-font-size': '10px',\n '--vis-map-area-label-font-weight': '400',\n '--vis-map-point-default-stroke-color': colors.surface,\n '--vis-map-point-default-stroke-width': '1.5px',\n },\n skeleton: { display: 'block', width: '100%', height: '100%' },\n // 地点的标签:描一圈表面色的边,压在区域、连线上也看得清;字号、描边宽度随缩放在行内设置\n pointLabels: {\n fontWeight: 600,\n fill: colors.text,\n stroke: colors.surface,\n paintOrder: 'stroke',\n strokeLinejoin: 'round',\n pointerEvents: 'none',\n },\n leader: { stroke: colors.textMuted },\n // 缩放按钮:在标题行的结束边(导出菜单前面)\n zoom: { display: 'inline-flex', alignItems: 'center', gap: '2px', marginInlineStart: 'auto' },\n wheelHint: { marginInlineEnd: '_sm', color: '_textMuted', fontSize: '_xs' },\n // 图例:连续是色带,分档是一排色块\n legend: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n columnGap: '_md',\n rowGap: '_xs',\n fontSize: '_xs',\n color: '_textMuted',\n paddingInline: '_sm',\n },\n ramp: { flexGrow: 1, maxWidth: '16rem', height: '0.5rem', borderRadius: '_full' },\n rampColors: (gradient: string) => ({ backgroundImage: gradient }),\n bin: { display: 'inline-flex', alignItems: 'center', gap: '0.375em', whiteSpace: 'nowrap' },\n swatch: { width: '0.875rem', height: '0.625rem', borderRadius: '2px' },\n swatchColor: (color: string) => ({ backgroundColor: color }),\n});\n\n/** 地点的标签四周留的空(屏幕像素) */\nconst labelPadding = 3;\n\n/** 新建一个 SVG 元素 */\nconst svgElement = <K extends keyof SVGElementTagNameMap>(name: K) =>\n document.createElementNS('http://www.w3.org/2000/svg', name);\n\n/** 混色:基色占 percent,其余透明(落在底色上) */\nconst tint = (color: string, percent: number) =>\n `color-mix(in srgb, ${color} ${Math.round(percent)}%, transparent)`;\n\ntype MapTopology = MapChartProps['topology'];\n\n/** 算好了各点权重的地理数据:同一份 TopoJSON 只算一次 */\nconst presimplified = new WeakMap<MapTopology, MapTopology>();\n/**\n * 简化过的地理数据放进这个类的实例:Unovis 的 setConfig 深拷贝配置,但跳过类的实例,\n * 每次更新就不必把整份 TopoJSON 再拷一遍\n */\nclass SharedTopology {}\n\n/** 简化过的地理数据:TopoJSON → 档位 → 结果 */\nconst simplified = new WeakMap<MapTopology, Map<number, MapTopology>>();\n\n/**\n * 简化地理数据:去掉与前后两点围成的三角形面积不到 minArea(坐标单位的平方,经纬度是平方度)的点\n * (Visvalingam,topojson-simplify)。相邻区域共用的边界一起简化,不会出现缝隙;各段弧的两端总保留。\n * minArea 按 2 的整数次幂分档缓存:绘图区大小变一点不重算。\n */\nexport function simplifyTopology(topology: MapTopology, minArea: number): MapTopology {\n if (!(minArea > 0) || !Number.isFinite(minArea)) return topology;\n const level = 2 ** Math.floor(Math.log2(minArea));\n let byLevel = simplified.get(topology);\n if (!byLevel) simplified.set(topology, (byLevel = new Map()));\n let result = byLevel.get(level);\n if (!result) {\n // topojson-simplify 的类型里要素属性不能是 null(GeoJSON 允许):边界上转一下\n type Input = Parameters<typeof presimplify>[0];\n let weighted = presimplified.get(topology);\n if (!weighted)\n presimplified.set(topology, (weighted = presimplify(topology as Input) as MapTopology));\n result = Object.assign(new SharedTopology(), simplify(weighted as Input, level)) as MapTopology;\n byLevel.set(level, result);\n }\n return result;\n}\n\n/** TopoJSON 的经纬度范围 [西, 南, 东, 北]:有 bbox 用它,否则解出各段弧的坐标(量化的弧是逐点的差值) */\nexport function topologyBounds(\n topology: MapChartProps['topology'],\n): [number, number, number, number] {\n if (topology.bbox) {\n const [west, south, east, north] = topology.bbox;\n return [west, south, east, north];\n }\n const quantized = topology.transform;\n const [scaleX, scaleY] = quantized?.scale ?? [1, 1];\n const [translateX, translateY] = quantized?.translate ?? [0, 0];\n let [west, south, east, north] = [Infinity, Infinity, -Infinity, -Infinity];\n for (const arc of topology.arcs) {\n let x = 0;\n let y = 0;\n for (const position of arc) {\n x = quantized ? x + position[0]! : position[0]!;\n y = quantized ? y + position[1]! : position[1]!;\n const longitude = x * scaleX + translateX;\n const latitude = y * scaleY + translateY;\n west = Math.min(west, longitude);\n east = Math.max(east, longitude);\n south = Math.min(south, latitude);\n north = Math.max(north, latitude);\n }\n }\n return [west, south, east, north];\n}\n\n/** 地图 */\nexport const MapChart = _component(\n ({\n topology,\n feature,\n projection,\n center,\n areas = [],\n points = [],\n links = [],\n scheme = 'sequential',\n color = 'accent',\n divergingColors = ['danger', 'success'],\n midpoint = 0,\n bins,\n areaLabels = false,\n flow = false,\n valueFormat,\n unit,\n height = 400,\n zoomable = false,\n loading = false,\n empty,\n tooltip = true,\n onAreaClick,\n onPointClick,\n sx,\n ...rest\n }: MapChartProps) => {\n const lang = useLang();\n const format = useFormat();\n const bounds = _derived(topologyBounds(topology));\n const numbers = _derived(\n areas.flatMap((area) => (area.value === undefined ? [] : [toNumber(area.value)])),\n );\n const extent = _derived<[number, number] | null>(\n numbers.length ? [Math.min(...numbers), Math.max(...numbers)] : null,\n );\n const largest = (values: readonly { value?: NumericValue }[]) =>\n Math.max(0, ...values.map((item) => (item.value === undefined ? 0 : toNumber(item.value))));\n const valueText = (value: NumericValue | undefined) =>\n value === undefined\n ? lang.emptyValue\n : format.number(value, unit ? { ...valueFormat, suffix: unit } : valueFormat);\n const numberText = (value: number) => format.number(value, valueFormat);\n\n /** 数值 → 颜色:sequential 从 12% 到 100%;diverging 两头各自从分界往外加深;bins 时按档取 */\n function colorOf(value: number): string {\n const [low, high] = extent ?? [0, 0];\n if (scheme === 'diverging') {\n const [lowColor, highColor] = divergingColors.map((item) => resolveColor(item, 0));\n const reach = Math.max(midpoint - low, high - midpoint) || 1;\n let ratio = Math.min(Math.abs(value - midpoint) / reach, 1);\n if (bins) ratio = Math.max(Math.ceil(ratio * bins), 1) / bins;\n return tint(value < midpoint ? lowColor! : highColor!, 12 + ratio * 88);\n }\n let ratio = high === low ? 1 : (value - low) / (high - low);\n if (bins) ratio = Math.min(Math.floor(ratio * bins), bins - 1) / Math.max(bins - 1, 1);\n return tint(resolveColor(color, 0), 12 + ratio * 88);\n }\n const areaColor = (area: MapArea) =>\n area.color\n ? resolveColor(area.color, 0)\n : area.value === undefined\n ? undefined\n : colorOf(toNumber(area.value));\n\n /** 投影:预设按中心旋转;不写时按范围选 */\n function createProjection(): MapGeoProjection {\n if (projection && typeof projection !== 'string') return projection;\n const [west, south, east, north] = bounds;\n const [longitude, latitude] = center ?? [(west + east) / 2, (south + north) / 2];\n const kind = projection ?? (east - west > 180 ? 'naturalEarth' : 'conic');\n if (kind === 'conic')\n // 标准纬线取范围的 1/6 与 5/6 处(中国约是 25°、47°),中央经线是中心\n return MapProjection.ConicEqualArea()\n .rotate([-longitude, 0])\n .parallels([south + (north - south) / 6, north - (north - south) / 6]);\n if (kind === 'orthographic')\n return MapProjection.Orthographic().rotate([-longitude, -latitude]);\n const create =\n kind === 'mercator'\n ? MapProjection.Mercator\n : kind === 'equalEarth'\n ? MapProjection.EqualEarth\n : MapProjection.NaturalEarth1;\n return create().rotate([-longitude, 0]);\n }\n\n // Unovis 只在第一次画时按绘图区适配投影(之后变了大小也会),换上的新投影只沿用旧的比例与平移,地图会画歪、画小;\n // 所以投影的输入(预设、中心、范围、自己的投影)变了就换一个新的 TopoJSONMap,第一次画时由它自己适配\n let mapKey: unknown[] = [];\n let generation = 0;\n let mapProjection: MapGeoProjection | undefined;\n function updateProjection() {\n const key = [projection, center?.[0], center?.[1], ...bounds];\n if (key.some((item, index) => item !== mapKey[index])) {\n if (mapKey.length) {\n map?.destroy();\n generation += 1;\n }\n mapKey = key;\n mapProjection = createProjection();\n }\n }\n\n // Unovis 每次绘制都把整份 TopoJSON 投影成路径:自带的中国省份有 3.5 万个点,画在几百像素里大多看不出来。\n // 按绘图区里一像素对应的经纬度简化(三角形不到一平方像素的点去掉),绘制快一个数量级;\n // 能缩放时留到放大一倍也看不出折角\n function drawnTopology(): MapTopology {\n const width = plot?.clientWidth ?? 0;\n const height = plot?.clientHeight ?? 0;\n if (!width || !height) return topology;\n const [west, south, east, north] = bounds;\n const degreesPerPixel =\n Math.max((east - west) / width, (north - south) / height) / (zoomable ? 2 : 1);\n return simplifyTopology(topology, degreesPerPixel ** 2);\n }\n\n const pointOf = (id: string) => points.find((point) => point.id === id);\n /** Unovis 画连线时给的是 { source, target }(克隆过的地点),不是原来的流向:按两端的 id 找回 */\n const linkOf = (drawn: MapLink) => {\n const { source, target } = drawn as unknown as { source: MapPoint; target: MapPoint };\n return links.find((link) => link.from === source.id && link.to === target.id);\n };\n let map: TopoJSONMap<MapArea, MapPoint, MapLink> | undefined;\n let plot = _state.raw<HTMLElement | null>(null);\n\n const pointMax = _derived(largest(points));\n // 面积按数值比例:半径 3–8 px\n const radiusOf = (point: MapPoint) =>\n point.value === undefined || pointMax === 0\n ? 4\n : 3 + Math.sqrt(toNumber(point.value) / pointMax) * 5;\n\n let labelFrame = 0;\n /** 画完、缩放之后,下一帧重排地点的标签 */\n function scheduleLabels() {\n cancelAnimationFrame(labelFrame);\n labelFrame = requestAnimationFrame(layoutLabels);\n }\n _effect(() => () => cancelAnimationFrame(labelFrame));\n\n /**\n * 地点的标签:Unovis 的标签相撞时只会藏起来,这里用 placeLabels 挪到放得下的方位(挤时画引线),\n * 画在地点那一组里(跟着缩放、拖动);压在标签、地点上的区域名藏起来。\n * 按屏幕像素算:地点那一组的坐标乘缩放级别\n */\n function layoutLabels() {\n const root = map?.g.node();\n const group = root?.querySelector<SVGGElement>(`.${TopoJSONMap.selectors.points}`);\n const svg = group?.ownerSVGElement;\n if (!root || !group || !svg || !mapProjection) return;\n const projectionAt = mapProjection;\n const zoom = Number(svg.style.getPropertyValue('--vis-map-current-zoom-level')) || 1;\n const layer =\n group.querySelector<SVGGElement>(':scope > [data-point-labels]') ?? svgElement('g');\n layer.setAttribute('data-point-labels', '');\n layer.setAttribute('class', css.attrs(mapChartStyles.pointLabels).class ?? '');\n layer.style.fontSize = `${11 / zoom}px`;\n layer.style.strokeWidth = `${3 / zoom}px`;\n // 放在最后:之后加入的地点不会盖住标签\n group.append(layer);\n\n const items = points.flatMap((point) => {\n const position = projectionAt([point.longitude, point.latitude]);\n if (!position || !point.label) return [];\n const text = svgElement('text');\n text.textContent = point.label;\n text.setAttribute('text-anchor', 'middle');\n return [{ point, text, x: position[0] * zoom, y: position[1] * zoom }];\n });\n layer.replaceChildren(...items.map((item) => item.text));\n // 在原点量字形的框:中文字体的行高、基线的位置各浏览器不同,摆放时按量到的上沿对齐\n const glyphs = items.map((item) => item.text.getBBox());\n const anchors = items.map((item, index) => {\n const box = glyphs[index]!;\n return {\n x: item.x,\n y: item.y,\n radius: radiusOf(item.point),\n // 四周留出描边(1.5 px)与一点空隙;Firefox 量到的框比字形的墨迹窄一点\n width: box.width * zoom + labelPadding * 2,\n height: box.height * zoom + labelPadding * 2,\n priority: item.point.value === undefined ? 0 : toNumber(item.point.value),\n };\n });\n\n const areaTexts = [\n ...root.querySelectorAll<SVGTextElement>(`text.${TopoJSONMap.selectors.areaLabel}`),\n ].filter((text) => text.getAttribute('visibility') !== 'hidden');\n const areaBoxes = areaTexts.map((text): LabelRect => {\n text.style.display = '';\n const { e, f } = text.transform.baseVal.consolidate()?.matrix ?? { e: 0, f: 0 };\n const box = text.getBBox();\n return {\n x: (e + box.x) * zoom,\n y: (f + box.y) * zoom,\n width: box.width * zoom,\n height: box.height * zoom,\n };\n });\n // 没放大时整张图在绘图区里:标签也不出界;放大后本来就只看得到一部分\n const bounds =\n zoom === 1 ? { x: 0, y: 0, width: svg.clientWidth, height: svg.clientHeight } : undefined;\n const placements = placeLabels(anchors, { bounds, soft: areaBoxes });\n\n const taken: LabelRect[] = anchors.map((anchor) => ({\n x: anchor.x - anchor.radius,\n y: anchor.y - anchor.radius,\n width: anchor.radius * 2,\n height: anchor.radius * 2,\n }));\n placements.forEach((placement, index) => {\n const { text } = items[index]!;\n if (!placement) {\n text.remove();\n return;\n }\n const { box, leader } = placement;\n taken.push(box);\n text.setAttribute('x', String((box.x + box.width / 2) / zoom));\n text.setAttribute('y', String((box.y + labelPadding) / zoom - glyphs[index]!.y));\n if (leader) layer.insertBefore(leaderLine(anchors[index]!, box, zoom), text);\n });\n areaTexts.forEach((text, index) => {\n if (taken.some((rect) => rectsOverlap(rect, areaBoxes[index]!)))\n text.style.display = 'none';\n });\n }\n\n /** 引线:从标记的边到标签矩形上离标记最近的点 */\n function leaderLine(\n anchor: { x: number; y: number; radius: number },\n box: LabelRect,\n zoom: number,\n ) {\n const toX = Math.min(Math.max(anchor.x, box.x), box.x + box.width);\n const toY = Math.min(Math.max(anchor.y, box.y), box.y + box.height);\n const length = Math.hypot(toX - anchor.x, toY - anchor.y) || 1;\n const line = svgElement('line');\n line.setAttribute('class', css.attrs(mapChartStyles.leader).class ?? '');\n line.setAttribute(\n 'x1',\n String((anchor.x + ((toX - anchor.x) / length) * anchor.radius) / zoom),\n );\n line.setAttribute(\n 'y1',\n String((anchor.y + ((toY - anchor.y) / length) * anchor.radius) / zoom),\n );\n line.setAttribute('x2', String(toX / zoom));\n line.setAttribute('y2', String(toY / zoom));\n line.style.strokeWidth = `${1 / zoom}px`;\n return line;\n }\n const chart: SingleChart = useSingleChart<MapGraphData<MapArea, MapPoint, MapLink>>(() => ({\n element: plot,\n ready: !loading,\n tooltip,\n build: (instance) => {\n const linkMax = largest(links);\n updateProjection();\n map = instance(`map-${generation}`, () => {\n const created = new TopoJSONMap<MapArea, MapPoint, MapLink>();\n // 热力模式的滤镜是写死的 id=\"heatmapFilter\",一页多张地图时 id 重复;不用热力模式,去掉\n created.g.select('filter#heatmapFilter').remove();\n // 缩放时 Unovis 把缩放级别写到 svg 的 style 上:跟着重排标签(拖动只是平移,标签随地点那一组走)\n const observer = new MutationObserver(scheduleLabels);\n queueMicrotask(() => {\n const svg = created.g.node()?.parentElement;\n if (svg) observer.observe(svg, { attributes: true, attributeFilter: ['style'] });\n });\n const destroy = created.destroy.bind(created);\n created.destroy = () => {\n observer.disconnect();\n destroy();\n };\n return created;\n });\n map.setConfig({\n topojson: drawnTopology(),\n mapFeatureName: feature,\n projection: mapProjection,\n disableZoom: !zoomable,\n areaId: (area) => area.id,\n areaColor,\n areaLabel: areaLabels ? (area) => area.label : undefined,\n areaCursor: onAreaClick ? () => 'pointer' : undefined,\n pointId: (point) => point.id,\n longitude: (point) => point.longitude,\n latitude: (point) => point.latitude,\n pointColor: (point) => resolveColor(point.color ?? 'danger', 0),\n pointRadius: radiusOf,\n pointShape: (point) => point.shape ?? 'circle',\n pointCursor: onPointClick ? () => 'pointer' : undefined,\n // 名字由 layoutLabels 自己画(pointLabel 写在点里面,pointBottomLabel 相撞时只会藏起来)\n pointLabel: () => '',\n pointBottomLabel: () => '',\n // 两端给 id:Unovis 克隆了地点,按对象找不到\n linkSource: (link) => link.from,\n linkTarget: (link) => link.to,\n linkColor: (drawn) => resolveColor(linkOf(drawn)?.color ?? 'neutral', 0),\n linkWidth: (drawn) => {\n const value = linkOf(drawn)?.value;\n return value === undefined || linkMax === 0 ? 1.5 : 1 + (toNumber(value) / linkMax) * 4;\n },\n enableFlowAnimation: flow,\n // 流动的粒子按原来的流向画,两端的经纬度直接给;起点已经有地点的标记,不再加一个\n sourceLongitude: (link) => pointOf(link.from)?.longitude,\n sourceLatitude: (link) => pointOf(link.from)?.latitude,\n targetLongitude: (link) => pointOf(link.to)?.longitude,\n targetLatitude: (link) => pointOf(link.to)?.latitude,\n sourcePointRadius: 0,\n flowParticleColor: (link) => resolveColor(link.color ?? 'accent', 0),\n flowParticleRadius: 2,\n // 每经度 0.15 个粒子:默认的 0.6 太密,连成一条线盖住了连线\n flowParticleDensity: 0.15,\n events: {\n [TopoJSONMap.selectors.feature]: {\n click: (shape: { data?: MapArea }) => {\n if (shape.data) onAreaClick?.(shape.data);\n },\n },\n [TopoJSONMap.selectors.point]: {\n click: (point: MapPoint) => onPointClick?.(point),\n },\n },\n });\n return {\n component: map,\n onRender: scheduleLabels,\n data: {\n areas: [...areas],\n points: [...points],\n links: links.filter((link) => pointOf(link.from) && pointOf(link.to)),\n },\n triggers: {\n [TopoJSONMap.selectors.feature]: (shape: { data?: MapArea }) =>\n shape.data\n ? chart.tooltip(\n chartTooltip(shape.data.label, [\n {\n label: lang.chartValue,\n color: areaColor(shape.data) ?? 'transparent',\n value: valueText(shape.data.value),\n },\n ]),\n )\n : undefined,\n [TopoJSONMap.selectors.point]: (point: MapPoint) =>\n chart.tooltip(\n chartTooltip(point.label, [\n {\n label: lang.chartValue,\n color: resolveColor(point.color ?? 'danger', 0),\n value: valueText(point.value),\n },\n ]),\n ),\n },\n };\n },\n }));\n\n /** 图例:分档时每档一个色块与范围,连续时一条色带两端写最小最大 */\n function legend() {\n if (!extent || areas.every((area) => area.color)) return null;\n const [low, high] = extent;\n if (bins) {\n const step = (high - low) / bins;\n return (\n <div {...css.attrs(mapChartStyles.legend)} aria-hidden=\"true\">\n {Array.from({ length: bins }, (_, index) => {\n const from = low + step * index;\n const to = index === bins - 1 ? high : from + step;\n return (\n <span key={index} {...css.attrs(mapChartStyles.bin)}>\n <span\n {...css.attrs(\n mapChartStyles.swatch,\n mapChartStyles.swatchColor(colorOf((from + to) / 2)),\n )}\n />\n {numberText(from)} – {numberText(to)}\n </span>\n );\n })}\n </div>\n );\n }\n const stops =\n scheme === 'diverging'\n ? [colorOf(low), colors.fill, colorOf(high)]\n : [colorOf(low), colorOf(high)];\n return (\n <div {...css.attrs(mapChartStyles.legend)} aria-hidden=\"true\">\n <span>{numberText(low)}</span>\n <span\n {...css.attrs(\n mapChartStyles.ramp,\n mapChartStyles.rampColors(`linear-gradient(to right, ${stops.join(', ')})`),\n )}\n />\n <span>{numberText(high)}</span>\n </div>\n );\n }\n\n // 滚轮默认滚动页面,按住 Ctrl(或 ⌘、触控板捏合)才缩放地图(同 Google 地图的 cooperative 手势):\n // 否则滚动页面经过地图时会把地图缩小。拦下的滚轮在顶栏提示一下\n let wheelHint = _state(false);\n let hintTimer: ReturnType<typeof setTimeout> | undefined;\n useEventListener(\n () => (zoomable ? plot : null),\n 'wheel',\n (event) => {\n if (event.ctrlKey || event.metaKey) return;\n event.stopPropagation();\n wheelHint = true;\n clearTimeout(hintTimer);\n hintTimer = setTimeout(() => (wheelHint = false), 1500);\n },\n { capture: true },\n );\n _effect(() => () => clearTimeout(hintTimer));\n\n /** 缩放按钮:放大、缩小、复位;前面是滚轮的提示 */\n const zoomButtons = () => (\n <span {...css.attrs(mapChartStyles.zoom)}>\n {wheelHint && (\n <span {...css.attrs(mapChartStyles.wheelHint)} role=\"status\">\n {lang.chartZoomWheelHint}\n </span>\n )}\n {(\n [\n [Plus, lang.chartZoomIn, () => map?.zoomIn()],\n [Minus, lang.chartZoomOut, () => map?.zoomOut()],\n [Maximize, lang.chartZoomFit, () => map?.fitView()],\n ] as const\n ).map(([icon, label, action]) => (\n <IconButton\n key={label}\n icon={icon}\n size=\"sm\"\n variant=\"ghost\"\n tone=\"neutral\"\n aria-label={label}\n onClick={action}\n />\n ))}\n </span>\n );\n\n return () => (\n <ChartFrame\n {...rest}\n sx={[mapChartStyles.root, sx]}\n unit={unit}\n height={height}\n legend={[]}\n hiddenKeys={[]}\n onLegendToggle={() => {}}\n loading={loading}\n skeleton={<Skeleton sx={mapChartStyles.skeleton} />}\n isEmpty={false}\n empty={empty}\n actions={zoomable ? zoomButtons() : undefined}\n footer={legend()}\n table={{\n columns: [lang.chartCategory, unit ? `${lang.chartValue}(${unit})` : lang.chartValue],\n rows: [\n ...areas.map((area) => ({ header: area.label, value: area.value })),\n ...points.map((point) => ({ header: point.label, value: point.value })),\n ...links.map((link) => ({\n header: lang.chartFlowLabel(\n pointOf(link.from)?.label ?? link.from,\n pointOf(link.to)?.label ?? link.to,\n ),\n value: link.value,\n })),\n ].map((row) => ({\n header: row.header,\n cells: [\n row.value === undefined ? lang.emptyValue : format.number(row.value, valueFormat),\n ],\n })),\n }}\n plotRef={(element) => (plot = element)}\n />\n );\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MapChart.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps","_createTextVNode","_vue_ref"],"sources":["../../src/charts/MapChart.tsx"],"sourcesContent":["/**\n * 地图:按区域着色(分省的销售额、各国的采购额),标出地点(工厂、供应商)与它们之间的流向。\n * 地理数据是 TopoJSON:Unovis 自带中国省份、世界、美国等(`@unovis/ts/maps`),也可以用自己的。\n *\n * import { ChinaTopoJSON } from '@unovis/ts/maps';\n * <MapChart\n * aria-label=\"各省销售额\"\n * topology={ChinaTopoJSON}\n * feature=\"provinces\"\n * areas={[{ id: 'CN-JS', label: '江苏', value: 623 }, …]} // id 是地图要素的 id\n * points={[{ id: 'sh', label: '上海组装', longitude: 121.47, latitude: 31.23, value: 860 }]}\n * links={[{ from: 'xa', to: 'sh', value: 120 }]}\n * bins={5}\n * areaLabels\n * />\n *\n * 投影:默认按地理数据的范围选——一个国家、一个地区用以它为中心的等积圆锥投影(中国地图常用的 Albers,正着、不歪),\n * 跨了大半个地球时用 Natural Earth;也可以指定 mercator、equalEarth、orthographic(地球仪)或自己的 d3 投影。\n *\n * 着色:sequential(默认)按数值深浅;diverging 以 midpoint 为界两头两种颜色(同比的涨跌);\n * bins 分成几档(分级着色,图例是几个色块),不写时连续着色(图例是色带);区域写了 color 时按它(分类着色)。\n * 没有数据的区域是底色。地点:value 决定大小(面积按比例),color、shape 决定颜色与形状;名字自动避让\n * (换方位、挤时往外退并画引线,数值大的先放,放不下的悬停看;压住名字、地点的区域名藏起来);\n * links 是地点之间的流向,粗细按 value,flow 时有流动的粒子。\n * zoomable 时可以拖动、按住 Ctrl 滚轮缩放,右上角有放大、缩小、复位的按钮。悬停看名称与数值;读屏的数据表列出各区域、地点与流向。\n */\nimport {\n MapProjection,\n TopoJSONMap,\n type MapGraphData,\n type TopoJSONMapConfigInterface,\n} from '@unovis/ts';\nimport { Maximize, Minus, Plus } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { presimplify, simplify } from 'topojson-simplify';\nimport type { VNodeChild } from 'vue';\nimport { IconButton } from '../base/IconButton';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { colors } from '../config/theme/tokens';\nimport { Skeleton } from '../feedback/Skeleton';\nimport { toNumber, type NumericValue } from '../utils/data/numeric';\nimport { useEventListener } from '../utils/dom/event-listener';\nimport type { PartProps } from '../utils/props';\nimport { chartTooltip, ChartFrame, type ChartFrameParts } from './frame';\nimport { placeLabels, rectsOverlap, type LabelRect } from './label-layout';\nimport { resolveColor, type ChartColor } from './series';\nimport { useSingleChart, type SingleChart } from './single';\n\n/** 一个区域的数据 */\nexport interface MapArea {\n /** 地图要素的 id(Unovis 的中国省份是 'CN-JS' 这样的写法) */\n id: string;\n /** 显示的名称:提示框、区域名、数据表 */\n label: string;\n /** 数值:决定颜色 */\n value?: NumericValue;\n /** 指定颜色:不按数值着色(分类着色,如所属大区) */\n color?: ChartColor;\n}\n\n/** 一个地点 */\nexport interface MapPoint {\n /** 标识:流向的 from、to 指向它 */\n id: string;\n /** 名称:写在点下方 */\n label: string;\n /** 经度 */\n longitude: number;\n /** 纬度 */\n latitude: number;\n /** 数值:决定点的大小(面积按比例),也显示在提示框 */\n value?: NumericValue;\n /** 颜色,默认 danger */\n color?: ChartColor;\n /** 形状,默认 circle */\n shape?: 'circle' | 'square' | 'triangle';\n}\n\n/** 两个地点之间的流向 */\nexport interface MapLink {\n /** 起点(地点的 id) */\n from: string;\n /** 终点(地点的 id) */\n to: string;\n /** 数值:决定线的粗细,也显示在数据表 */\n value?: NumericValue;\n /** 颜色,默认次要色 */\n color?: ChartColor;\n}\n\n/** 投影的预设 */\nexport interface MapProjections {\n /** 等积圆锥(Albers):以数据为中心,一个国家、一个地区用它(中国地图常用),正着、面积不失真 */\n conic: unknown;\n /** 墨卡托:网页地图常见,高纬度会放大 */\n mercator: unknown;\n /** Natural Earth:世界地图,形状与面积都比较自然 */\n naturalEarth: unknown;\n /** Equal Earth:世界地图,面积准确 */\n equalEarth: unknown;\n /** 正射(地球仪):以数据为中心看半个地球 */\n orthographic: unknown;\n}\n\n/** d3 的投影(TopoJSONMap 的 projection) */\nexport type MapGeoProjection = NonNullable<TopoJSONMapConfigInterface<MapArea>['projection']>;\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface MapChartProps extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 地理数据(TopoJSON),如 `@unovis/ts/maps` 的 ChinaTopoJSON、WorldMapTopoJSON */\n topology: NonNullable<TopoJSONMapConfigInterface<MapArea>['topojson']>;\n /** 画哪一组要素(TopoJSON 的 objects 里的名字),如中国省份是 'provinces'、世界是 'countries' */\n feature: string;\n /** 投影:预设的名字,或 d3 的投影;不写时按数据的范围选 conic 或 naturalEarth */\n projection?: keyof MapProjections | MapGeoProjection;\n /** 投影的中心 [经度, 纬度]:中央经线(世界地图写 [150, 0] 以太平洋为中心),orthographic 还用纬度;不写时取地理数据范围的中心 */\n center?: readonly [number, number];\n /** 各区域的数值 */\n areas?: readonly MapArea[];\n /** 地点 */\n points?: readonly MapPoint[];\n /** 地点之间的流向 */\n links?: readonly MapLink[];\n /** 着色方式:sequential 按数值深浅(默认),diverging 以 midpoint 为界两头两种颜色 */\n scheme?: 'sequential' | 'diverging';\n /** sequential 的基色,默认 accent */\n color?: ChartColor;\n /** diverging 的两头 [低, 高],默认 ['danger', 'success'] */\n divergingColors?: readonly [ChartColor, ChartColor];\n /** diverging 的分界,默认 0 */\n midpoint?: number;\n /** 分成几档(分级着色);不写时连续着色 */\n bins?: number;\n /** 在区域上写名字(区域够大时) */\n areaLabels?: boolean;\n /** 流向上有流动的粒子 */\n flow?: boolean;\n /** 数值的格式 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方,提示框与数据表的数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 400\n */\n height?: number | string;\n /** 可以拖动、滚轮缩放,右上角有放大、缩小、复位的按钮;默认关(不抢页面的滚动) */\n zoomable?: boolean;\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n /** 悬停时的提示框,默认 true */\n tooltip?: boolean;\n /** 点了一个有数据的区域 */\n onAreaClick?: (area: MapArea) => void;\n /** 点了一个地点 */\n onPointClick?: (point: MapPoint) => void;\n}\n\n/** MapChart 的样式 */\nexport const mapChartStyles = css.create({\n // 地图跟随主题:底色、边界是表面色,文字是正文色\n root: {\n '--vis-map-feature-color': colors.fill,\n '--vis-map-boundary-color': colors.surface,\n '--vis-map-point-label-text-color-dark': colors.text,\n '--vis-map-point-label-text-color-light': colors.text,\n '--vis-map-area-label-text-color': colors.text,\n '--vis-map-area-label-font-size': '10px',\n '--vis-map-area-label-font-weight': '400',\n '--vis-map-point-default-stroke-color': colors.surface,\n '--vis-map-point-default-stroke-width': '1.5px',\n },\n skeleton: { display: 'block', width: '100%', height: '100%' },\n // 地点的标签:描一圈表面色的边,压在区域、连线上也看得清;字号、描边宽度随缩放在行内设置\n pointLabels: {\n fontWeight: 600,\n fill: colors.text,\n stroke: colors.surface,\n paintOrder: 'stroke',\n strokeLinejoin: 'round',\n pointerEvents: 'none',\n },\n leader: { stroke: colors.textMuted },\n // 缩放按钮:在标题行的结束边(导出菜单前面)\n zoom: { display: 'inline-flex', alignItems: 'center', gap: '2px', marginInlineStart: 'auto' },\n wheelHint: { marginInlineEnd: '_sm', color: '_textMuted', fontSize: '_xs' },\n // 图例:连续是色带,分档是一排色块\n legend: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n columnGap: '_md',\n rowGap: '_xs',\n fontSize: '_xs',\n color: '_textMuted',\n paddingInline: '_sm',\n },\n ramp: { flexGrow: 1, maxWidth: '16rem', height: '0.5rem', borderRadius: '_full' },\n rampColors: (gradient: string) => ({ backgroundImage: gradient }),\n bin: { display: 'inline-flex', alignItems: 'center', gap: '0.375em', whiteSpace: 'nowrap' },\n swatch: { width: '0.875rem', height: '0.625rem', borderRadius: '2px' },\n swatchColor: (color: string) => ({ backgroundColor: color }),\n});\n\n/** 地点的标签四周留的空(屏幕像素) */\nconst labelPadding = 3;\n\n/** 新建一个 SVG 元素 */\nconst svgElement = <K extends keyof SVGElementTagNameMap>(name: K) =>\n document.createElementNS('http://www.w3.org/2000/svg', name);\n\n/** 混色:基色占 percent,其余透明(落在底色上) */\nconst tint = (color: string, percent: number) =>\n `color-mix(in srgb, ${color} ${Math.round(percent)}%, transparent)`;\n\ntype MapTopology = MapChartProps['topology'];\n\n/** 算好了各点权重的地理数据:同一份 TopoJSON 只算一次 */\nconst presimplified = new WeakMap<MapTopology, MapTopology>();\n/**\n * 简化过的地理数据放进这个类的实例:Unovis 的 setConfig 深拷贝配置,但跳过类的实例,\n * 每次更新就不必把整份 TopoJSON 再拷一遍\n */\nclass SharedTopology {}\n\n/** 简化过的地理数据:TopoJSON → 档位 → 结果 */\nconst simplified = new WeakMap<MapTopology, Map<number, MapTopology>>();\n\n/**\n * 简化地理数据:去掉与前后两点围成的三角形面积不到 minArea(坐标单位的平方,经纬度是平方度)的点\n * (Visvalingam,topojson-simplify)。相邻区域共用的边界一起简化,不会出现缝隙;各段弧的两端总保留。\n * minArea 按 2 的整数次幂分档缓存:绘图区大小变一点不重算。\n */\nexport function simplifyTopology(topology: MapTopology, minArea: number): MapTopology {\n if (!(minArea > 0) || !Number.isFinite(minArea)) return topology;\n const level = 2 ** Math.floor(Math.log2(minArea));\n let byLevel = simplified.get(topology);\n if (!byLevel) simplified.set(topology, (byLevel = new Map()));\n let result = byLevel.get(level);\n if (!result) {\n // topojson-simplify 的类型里要素属性不能是 null(GeoJSON 允许):边界上转一下\n type Input = Parameters<typeof presimplify>[0];\n let weighted = presimplified.get(topology);\n if (!weighted)\n presimplified.set(topology, (weighted = presimplify(topology as Input) as MapTopology));\n result = Object.assign(new SharedTopology(), simplify(weighted as Input, level)) as MapTopology;\n byLevel.set(level, result);\n }\n return result;\n}\n\n/** TopoJSON 的经纬度范围 [西, 南, 东, 北]:有 bbox 用它,否则解出各段弧的坐标(量化的弧是逐点的差值) */\nexport function topologyBounds(\n topology: MapChartProps['topology'],\n): [number, number, number, number] {\n if (topology.bbox) {\n const [west, south, east, north] = topology.bbox;\n return [west, south, east, north];\n }\n const quantized = topology.transform;\n const [scaleX, scaleY] = quantized?.scale ?? [1, 1];\n const [translateX, translateY] = quantized?.translate ?? [0, 0];\n let [west, south, east, north] = [Infinity, Infinity, -Infinity, -Infinity];\n for (const arc of topology.arcs) {\n let x = 0;\n let y = 0;\n for (const position of arc) {\n x = quantized ? x + position[0]! : position[0]!;\n y = quantized ? y + position[1]! : position[1]!;\n const longitude = x * scaleX + translateX;\n const latitude = y * scaleY + translateY;\n west = Math.min(west, longitude);\n east = Math.max(east, longitude);\n south = Math.min(south, latitude);\n north = Math.max(north, latitude);\n }\n }\n return [west, south, east, north];\n}\n\n/** 地图 */\nexport const MapChart = _component(\n ({\n topology,\n feature,\n projection,\n center,\n areas = [],\n points = [],\n links = [],\n scheme = 'sequential',\n color = 'accent',\n divergingColors = ['danger', 'success'],\n midpoint = 0,\n bins,\n areaLabels = false,\n flow = false,\n valueFormat,\n unit,\n height = 400,\n zoomable = false,\n loading = false,\n empty,\n tooltip = true,\n onAreaClick,\n onPointClick,\n sx,\n ...rest\n }: MapChartProps) => {\n const lang = useLang();\n const format = useFormat();\n const bounds = _derived(topologyBounds(topology));\n const numbers = _derived(\n areas.flatMap((area) => (area.value === undefined ? [] : [toNumber(area.value)])),\n );\n const extent = _derived<[number, number] | null>(\n numbers.length ? [Math.min(...numbers), Math.max(...numbers)] : null,\n );\n const largest = (values: readonly { value?: NumericValue }[]) =>\n Math.max(0, ...values.map((item) => (item.value === undefined ? 0 : toNumber(item.value))));\n const valueText = (value: NumericValue | undefined) =>\n value === undefined\n ? lang.emptyValue\n : format.number(value, unit ? { ...valueFormat, suffix: unit } : valueFormat);\n const numberText = (value: number) => format.number(value, valueFormat);\n\n /** 数值 → 颜色:sequential 从 12% 到 100%;diverging 两头各自从分界往外加深;bins 时按档取 */\n function colorOf(value: number): string {\n const [low, high] = extent ?? [0, 0];\n if (scheme === 'diverging') {\n const [lowColor, highColor] = divergingColors.map((item) => resolveColor(item, 0));\n const reach = Math.max(midpoint - low, high - midpoint) || 1;\n let ratio = Math.min(Math.abs(value - midpoint) / reach, 1);\n if (bins) ratio = Math.max(Math.ceil(ratio * bins), 1) / bins;\n return tint(value < midpoint ? lowColor! : highColor!, 12 + ratio * 88);\n }\n let ratio = high === low ? 1 : (value - low) / (high - low);\n if (bins) ratio = Math.min(Math.floor(ratio * bins), bins - 1) / Math.max(bins - 1, 1);\n return tint(resolveColor(color, 0), 12 + ratio * 88);\n }\n const areaColor = (area: MapArea) =>\n area.color\n ? resolveColor(area.color, 0)\n : area.value === undefined\n ? undefined\n : colorOf(toNumber(area.value));\n\n /** 投影:预设按中心旋转;不写时按范围选 */\n function createProjection(): MapGeoProjection {\n if (projection && typeof projection !== 'string') return projection;\n const [west, south, east, north] = bounds;\n const [longitude, latitude] = center ?? [(west + east) / 2, (south + north) / 2];\n const kind = projection ?? (east - west > 180 ? 'naturalEarth' : 'conic');\n if (kind === 'conic')\n // 标准纬线取范围的 1/6 与 5/6 处(中国约是 25°、47°),中央经线是中心\n return MapProjection.ConicEqualArea()\n .rotate([-longitude, 0])\n .parallels([south + (north - south) / 6, north - (north - south) / 6]);\n if (kind === 'orthographic')\n return MapProjection.Orthographic().rotate([-longitude, -latitude]);\n const create =\n kind === 'mercator'\n ? MapProjection.Mercator\n : kind === 'equalEarth'\n ? MapProjection.EqualEarth\n : MapProjection.NaturalEarth1;\n return create().rotate([-longitude, 0]);\n }\n\n // Unovis 只在第一次画时按绘图区适配投影(之后变了大小也会),换上的新投影只沿用旧的比例与平移,地图会画歪、画小;\n // 所以投影的输入(预设、中心、范围、自己的投影)变了就换一个新的 TopoJSONMap,第一次画时由它自己适配\n let mapKey: unknown[] = [];\n let generation = 0;\n let mapProjection: MapGeoProjection | undefined;\n function updateProjection() {\n const key = [projection, center?.[0], center?.[1], ...bounds];\n if (key.some((item, index) => item !== mapKey[index])) {\n if (mapKey.length) {\n map?.destroy();\n generation += 1;\n }\n mapKey = key;\n mapProjection = createProjection();\n }\n }\n\n // Unovis 每次绘制都把整份 TopoJSON 投影成路径:自带的中国省份有 3.5 万个点,画在几百像素里大多看不出来。\n // 按绘图区里一像素对应的经纬度简化(三角形不到一平方像素的点去掉),绘制快一个数量级;\n // 能缩放时留到放大一倍也看不出折角\n function drawnTopology(): MapTopology {\n const width = plot?.clientWidth ?? 0;\n const height = plot?.clientHeight ?? 0;\n if (!width || !height) return topology;\n const [west, south, east, north] = bounds;\n const degreesPerPixel =\n Math.max((east - west) / width, (north - south) / height) / (zoomable ? 2 : 1);\n return simplifyTopology(topology, degreesPerPixel ** 2);\n }\n\n const pointOf = (id: string) => points.find((point) => point.id === id);\n /** Unovis 画连线时给的是 { source, target }(克隆过的地点),不是原来的流向:按两端的 id 找回 */\n const linkOf = (drawn: MapLink) => {\n const { source, target } = drawn as unknown as { source: MapPoint; target: MapPoint };\n return links.find((link) => link.from === source.id && link.to === target.id);\n };\n let map: TopoJSONMap<MapArea, MapPoint, MapLink> | undefined;\n let plot = _state.raw<HTMLElement | null>(null);\n\n const pointMax = _derived(largest(points));\n // 面积按数值比例:半径 3–8 px\n const radiusOf = (point: MapPoint) =>\n point.value === undefined || pointMax === 0\n ? 4\n : 3 + Math.sqrt(toNumber(point.value) / pointMax) * 5;\n\n let labelFrame = 0;\n /** 画完、缩放之后,下一帧重排地点的标签 */\n function scheduleLabels() {\n cancelAnimationFrame(labelFrame);\n labelFrame = requestAnimationFrame(layoutLabels);\n }\n _effect(() => () => cancelAnimationFrame(labelFrame));\n\n /**\n * 地点的标签:Unovis 的标签相撞时只会藏起来,这里用 placeLabels 挪到放得下的方位(挤时画引线),\n * 画在地点那一组里(跟着缩放、拖动);压在标签、地点上的区域名藏起来。\n * 按屏幕像素算:地点那一组的坐标乘缩放级别\n */\n function layoutLabels() {\n const root = map?.g.node();\n const group = root?.querySelector<SVGGElement>(`.${TopoJSONMap.selectors.points}`);\n const svg = group?.ownerSVGElement;\n if (!root || !group || !svg || !mapProjection) return;\n const projectionAt = mapProjection;\n const zoom = Number(svg.style.getPropertyValue('--vis-map-current-zoom-level')) || 1;\n const layer =\n group.querySelector<SVGGElement>(':scope > [data-point-labels]') ?? svgElement('g');\n layer.setAttribute('data-point-labels', '');\n layer.setAttribute('class', css.attrs(mapChartStyles.pointLabels).class ?? '');\n layer.style.fontSize = `${11 / zoom}px`;\n layer.style.strokeWidth = `${3 / zoom}px`;\n // 放在最后:之后加入的地点不会盖住标签\n group.append(layer);\n\n const items = points.flatMap((point) => {\n const position = projectionAt([point.longitude, point.latitude]);\n if (!position || !point.label) return [];\n const text = svgElement('text');\n text.textContent = point.label;\n text.setAttribute('text-anchor', 'middle');\n return [{ point, text, x: position[0] * zoom, y: position[1] * zoom }];\n });\n layer.replaceChildren(...items.map((item) => item.text));\n // 在原点量字形的框:中文字体的行高、基线的位置各浏览器不同,摆放时按量到的上沿对齐\n const glyphs = items.map((item) => item.text.getBBox());\n const anchors = items.map((item, index) => {\n const box = glyphs[index]!;\n return {\n x: item.x,\n y: item.y,\n radius: radiusOf(item.point),\n // 四周留出描边(1.5 px)与一点空隙;Firefox 量到的框比字形的墨迹窄一点\n width: box.width * zoom + labelPadding * 2,\n height: box.height * zoom + labelPadding * 2,\n priority: item.point.value === undefined ? 0 : toNumber(item.point.value),\n };\n });\n\n const areaTexts = [\n ...root.querySelectorAll<SVGTextElement>(`text.${TopoJSONMap.selectors.areaLabel}`),\n ].filter((text) => text.getAttribute('visibility') !== 'hidden');\n const areaBoxes = areaTexts.map((text): LabelRect => {\n text.style.display = '';\n const { e, f } = text.transform.baseVal.consolidate()?.matrix ?? { e: 0, f: 0 };\n const box = text.getBBox();\n return {\n x: (e + box.x) * zoom,\n y: (f + box.y) * zoom,\n width: box.width * zoom,\n height: box.height * zoom,\n };\n });\n // 没放大时整张图在绘图区里:标签也不出界;放大后本来就只看得到一部分\n const bounds =\n zoom === 1 ? { x: 0, y: 0, width: svg.clientWidth, height: svg.clientHeight } : undefined;\n const placements = placeLabels(anchors, { bounds, soft: areaBoxes });\n\n const taken: LabelRect[] = anchors.map((anchor) => ({\n x: anchor.x - anchor.radius,\n y: anchor.y - anchor.radius,\n width: anchor.radius * 2,\n height: anchor.radius * 2,\n }));\n placements.forEach((placement, index) => {\n const { text } = items[index]!;\n if (!placement) {\n text.remove();\n return;\n }\n const { box, leader } = placement;\n taken.push(box);\n text.setAttribute('x', String((box.x + box.width / 2) / zoom));\n text.setAttribute('y', String((box.y + labelPadding) / zoom - glyphs[index]!.y));\n if (leader) layer.insertBefore(leaderLine(anchors[index]!, box, zoom), text);\n });\n areaTexts.forEach((text, index) => {\n if (taken.some((rect) => rectsOverlap(rect, areaBoxes[index]!)))\n text.style.display = 'none';\n });\n }\n\n /** 引线:从标记的边到标签矩形上离标记最近的点 */\n function leaderLine(\n anchor: { x: number; y: number; radius: number },\n box: LabelRect,\n zoom: number,\n ) {\n const toX = Math.min(Math.max(anchor.x, box.x), box.x + box.width);\n const toY = Math.min(Math.max(anchor.y, box.y), box.y + box.height);\n const length = Math.hypot(toX - anchor.x, toY - anchor.y) || 1;\n const line = svgElement('line');\n line.setAttribute('class', css.attrs(mapChartStyles.leader).class ?? '');\n line.setAttribute(\n 'x1',\n String((anchor.x + ((toX - anchor.x) / length) * anchor.radius) / zoom),\n );\n line.setAttribute(\n 'y1',\n String((anchor.y + ((toY - anchor.y) / length) * anchor.radius) / zoom),\n );\n line.setAttribute('x2', String(toX / zoom));\n line.setAttribute('y2', String(toY / zoom));\n line.style.strokeWidth = `${1 / zoom}px`;\n return line;\n }\n const chart: SingleChart = useSingleChart<MapGraphData<MapArea, MapPoint, MapLink>>(() => ({\n element: plot,\n ready: !loading,\n tooltip,\n build: (instance) => {\n const linkMax = largest(links);\n updateProjection();\n map = instance(`map-${generation}`, () => {\n const created = new TopoJSONMap<MapArea, MapPoint, MapLink>();\n // 热力模式的滤镜是写死的 id=\"heatmapFilter\",一页多张地图时 id 重复;不用热力模式,去掉\n created.g.select('filter#heatmapFilter').remove();\n // 缩放时 Unovis 把缩放级别写到 svg 的 style 上:跟着重排标签(拖动只是平移,标签随地点那一组走)\n const observer = new MutationObserver(scheduleLabels);\n queueMicrotask(() => {\n const svg = created.g.node()?.parentElement;\n if (svg) observer.observe(svg, { attributes: true, attributeFilter: ['style'] });\n });\n const destroy = created.destroy.bind(created);\n created.destroy = () => {\n observer.disconnect();\n destroy();\n };\n return created;\n });\n map.setConfig({\n topojson: drawnTopology(),\n mapFeatureName: feature,\n projection: mapProjection,\n disableZoom: !zoomable,\n areaId: (area) => area.id,\n areaColor,\n areaLabel: areaLabels ? (area) => area.label : undefined,\n areaCursor: onAreaClick ? () => 'pointer' : undefined,\n pointId: (point) => point.id,\n longitude: (point) => point.longitude,\n latitude: (point) => point.latitude,\n pointColor: (point) => resolveColor(point.color ?? 'danger', 0),\n pointRadius: radiusOf,\n pointShape: (point) => point.shape ?? 'circle',\n pointCursor: onPointClick ? () => 'pointer' : undefined,\n // 名字由 layoutLabels 自己画(pointLabel 写在点里面,pointBottomLabel 相撞时只会藏起来)\n pointLabel: () => '',\n pointBottomLabel: () => '',\n // 两端给 id:Unovis 克隆了地点,按对象找不到\n linkSource: (link) => link.from,\n linkTarget: (link) => link.to,\n linkColor: (drawn) => resolveColor(linkOf(drawn)?.color ?? 'neutral', 0),\n linkWidth: (drawn) => {\n const value = linkOf(drawn)?.value;\n return value === undefined || linkMax === 0 ? 1.5 : 1 + (toNumber(value) / linkMax) * 4;\n },\n enableFlowAnimation: flow,\n // 流动的粒子按原来的流向画,两端的经纬度直接给;起点已经有地点的标记,不再加一个\n sourceLongitude: (link) => pointOf(link.from)?.longitude,\n sourceLatitude: (link) => pointOf(link.from)?.latitude,\n targetLongitude: (link) => pointOf(link.to)?.longitude,\n targetLatitude: (link) => pointOf(link.to)?.latitude,\n sourcePointRadius: 0,\n flowParticleColor: (link) => resolveColor(link.color ?? 'accent', 0),\n flowParticleRadius: 2,\n // 每经度 0.15 个粒子:默认的 0.6 太密,连成一条线盖住了连线\n flowParticleDensity: 0.15,\n events: {\n [TopoJSONMap.selectors.feature]: {\n click: (shape: { data?: MapArea }) => {\n if (shape.data) onAreaClick?.(shape.data);\n },\n },\n [TopoJSONMap.selectors.point]: {\n click: (point: MapPoint) => onPointClick?.(point),\n },\n },\n });\n return {\n component: map,\n onRender: scheduleLabels,\n data: {\n areas: [...areas],\n points: [...points],\n links: links.filter((link) => pointOf(link.from) && pointOf(link.to)),\n },\n triggers: {\n [TopoJSONMap.selectors.feature]: (shape: { data?: MapArea }) =>\n shape.data\n ? chart.tooltip(\n chartTooltip(shape.data.label, [\n {\n label: lang.chartValue,\n color: areaColor(shape.data) ?? 'transparent',\n value: valueText(shape.data.value),\n },\n ]),\n )\n : undefined,\n [TopoJSONMap.selectors.point]: (point: MapPoint) =>\n chart.tooltip(\n chartTooltip(point.label, [\n {\n label: lang.chartValue,\n color: resolveColor(point.color ?? 'danger', 0),\n value: valueText(point.value),\n },\n ]),\n ),\n },\n };\n },\n }));\n\n /** 图例:分档时每档一个色块与范围,连续时一条色带两端写最小最大 */\n function legend() {\n if (!extent || areas.every((area) => area.color)) return null;\n const [low, high] = extent;\n if (bins) {\n const step = (high - low) / bins;\n return (\n <div {...css.attrs(mapChartStyles.legend)} aria-hidden=\"true\">\n {Array.from({ length: bins }, (_, index) => {\n const from = low + step * index;\n const to = index === bins - 1 ? high : from + step;\n return (\n <span key={index} {...css.attrs(mapChartStyles.bin)}>\n <span\n {...css.attrs(\n mapChartStyles.swatch,\n mapChartStyles.swatchColor(colorOf((from + to) / 2)),\n )}\n />\n {numberText(from)} – {numberText(to)}\n </span>\n );\n })}\n </div>\n );\n }\n const stops =\n scheme === 'diverging'\n ? [colorOf(low), colors.fill, colorOf(high)]\n : [colorOf(low), colorOf(high)];\n return (\n <div {...css.attrs(mapChartStyles.legend)} aria-hidden=\"true\">\n <span>{numberText(low)}</span>\n <span\n {...css.attrs(\n mapChartStyles.ramp,\n mapChartStyles.rampColors(`linear-gradient(to right, ${stops.join(', ')})`),\n )}\n />\n <span>{numberText(high)}</span>\n </div>\n );\n }\n\n // 滚轮默认滚动页面,按住 Ctrl(或 ⌘、触控板捏合)才缩放地图(同 Google 地图的 cooperative 手势):\n // 否则滚动页面经过地图时会把地图缩小。拦下的滚轮在顶栏提示一下\n let wheelHint = _state(false);\n let hintTimer: ReturnType<typeof setTimeout> | undefined;\n useEventListener(\n () => (zoomable ? plot : null),\n 'wheel',\n (event) => {\n if (event.ctrlKey || event.metaKey) return;\n event.stopPropagation();\n wheelHint = true;\n clearTimeout(hintTimer);\n hintTimer = setTimeout(() => (wheelHint = false), 1500);\n },\n { capture: true },\n );\n _effect(() => () => clearTimeout(hintTimer));\n\n /** 缩放按钮:放大、缩小、复位;前面是滚轮的提示 */\n const zoomButtons = () => (\n <span {...css.attrs(mapChartStyles.zoom)}>\n {wheelHint && (\n <span {...css.attrs(mapChartStyles.wheelHint)} role=\"status\">\n {lang.chartZoomWheelHint}\n </span>\n )}\n {(\n [\n [Plus, lang.chartZoomIn, () => map?.zoomIn()],\n [Minus, lang.chartZoomOut, () => map?.zoomOut()],\n [Maximize, lang.chartZoomFit, () => map?.fitView()],\n ] as const\n ).map(([icon, label, action]) => (\n <IconButton\n key={label}\n icon={icon}\n size=\"sm\"\n variant=\"ghost\"\n tone=\"neutral\"\n aria-label={label}\n onClick={action}\n />\n ))}\n </span>\n );\n\n return () => (\n <ChartFrame\n {...rest}\n sx={[mapChartStyles.root, sx]}\n unit={unit}\n height={height}\n legend={[]}\n hiddenKeys={[]}\n onLegendToggle={() => {}}\n loading={loading}\n skeleton={<Skeleton sx={mapChartStyles.skeleton} />}\n isEmpty={false}\n empty={empty}\n actions={zoomable ? zoomButtons() : undefined}\n footer={legend()}\n table={{\n columns: [lang.chartCategory, unit ? `${lang.chartValue}(${unit})` : lang.chartValue],\n rows: [\n ...areas.map((area) => ({ header: area.label, value: area.value })),\n ...points.map((point) => ({ header: point.label, value: point.value })),\n ...links.map((link) => ({\n header: lang.chartFlowLabel(\n pointOf(link.from)?.label ?? link.from,\n pointOf(link.to)?.label ?? link.to,\n ),\n value: link.value,\n })),\n ].map((row) => ({\n header: row.header,\n cells: [\n row.value === undefined ? lang.emptyValue : format.number(row.value, valueFormat),\n ],\n })),\n }}\n plotRef={(element) => (plot = element)}\n />\n );\n },\n);\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
2
|
import type { VNodeChild } from 'vue';
|
|
3
3
|
import { type NumericFormat } from '../config/lang/format';
|
|
4
4
|
import type { PartProps } from '../utils/props';
|
|
@@ -7,7 +7,7 @@ import { ChartFrame } from "./frame.js";
|
|
|
7
7
|
import { resolveSeries, seriesNumber, seriesValue } from "./series.js";
|
|
8
8
|
import { computed, createVNode, ref } from "vue";
|
|
9
9
|
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
10
|
-
import
|
|
10
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
11
11
|
//#region src/charts/RadarChart.tsx
|
|
12
12
|
/** 未声明的属性落到外层 div(role="figure")上;aria-label 是图表的名称 */
|
|
13
13
|
/** RadarChart 的样式 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadarChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/charts/RadarChart.tsx"],"sourcesContent":["/**\n * 雷达图:几个维度上同时比较几个对象(供应商的质量、交期、价格、服务评分,方案的各项指标)。\n * 每个维度一根轴,从中心往外是 0 到 max;每个系列连成一个多边形,填一层浅色。\n *\n * <RadarChart\n * aria-label=\"供应商评分\"\n * data={[{ dimension: '质量', huachen: 86, hengyuan: 78 }, …]}\n * index=\"dimension\"\n * series={[{ key: 'huachen', label: '华辰精密' }, { key: 'hengyuan', label: '恒远五金' }]}\n * max={100}\n * />\n *\n * Unovis 没有雷达图:这里用 SVG 直接画,外层结构(图例、单位、加载与空状态、给读屏的数据表)同其他图表。\n * 悬停一个维度时那根轴加粗,各系列在这一维的数值标在顶点旁边;点图例隐藏系列。\n */\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 { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { Skeleton } from '../feedback/Skeleton';\nimport type { PartProps } from '../utils/props';\nimport { niceStep } from './axis-ticks';\nimport { ChartFrame, type ChartFrameParts } from './frame';\nimport { resolveSeries, seriesNumber, seriesValue, type ChartSeries } from './series';\nimport { svgNumber } from '../utils/data/number';\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface RadarChartProps<T extends object>\n extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 数据:每一行是一个维度(质量、交期…) */\n data: readonly T[];\n /** 维度名的字段 */\n index: keyof T & string;\n /** 系列:每个系列连成一个多边形 */\n series: readonly ChartSeries<T>[];\n /** 轴的最大值;不写时按数据取一个整齐的值 */\n max?: number;\n /**\n * 网格的圈数\n * @default 4\n */\n levels?: number;\n /** 网格画成多边形(默认)或圆 */\n grid?: 'polygon' | 'circle';\n /** 数值的格式:刻度、顶点旁的数值、数据表共用 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 300\n */\n height?: number | string;\n /** 图例:默认多于一个系列时显示 */\n legend?: boolean;\n /** 隐藏的系列:点图例时写回,父级可以写 _hiddenSeries={keys} */\n _hiddenSeries?: string[];\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n}\n\n/** RadarChart 的样式 */\nexport const radarChartStyles = css.create({\n svg: { display: 'block', width: '100%', height: '100%', overflow: 'visible' },\n grid: { fill: 'none', stroke: '_borderMuted', strokeWidth: 1 },\n spoke: { stroke: '_borderMuted', strokeWidth: 1 },\n spokeActive: { stroke: '_textMuted', strokeWidth: 1.5 },\n tick: { fill: '_textMuted', fontSize: '9px' },\n label: { fill: '_text', fontSize: '11px' },\n labelActive: { fontWeight: '_semibold' },\n // 几个系列叠在一起:填充很浅,混在一起也不发灰\n area: { fillOpacity: 0.08, strokeWidth: 2, strokeLinejoin: 'round' },\n vertex: { strokeWidth: 0 },\n value: { fontSize: '10px', fontWeight: '_semibold', paintOrder: 'stroke', strokeWidth: 3 },\n // 悬停用的扇区:透明,只接指针\n sector: { fill: 'transparent' },\n skeleton: {\n display: 'block',\n height: '100%',\n aspectRatio: '1',\n marginInline: 'auto',\n borderRadius: '50%',\n },\n stroke: (color: string) => ({ stroke: color, fill: color }),\n surfaceStroke: { stroke: '_surface' },\n});\n\n// 画布:360 × 300,中心 (180, 150),半径 108;文字在半径 124 的圈上\nconst WIDTH = 360;\nconst HEIGHT = 300;\nconst CX = WIDTH / 2;\nconst CY = HEIGHT / 2;\nconst RADIUS = 108;\nconst LABEL_RADIUS = 124;\n\n/** 第 index 个维度(共 count 个)、比例 ratio 处的点:第一个维度在正上方,顺时针 */\nfunction polar(index: number, count: number, ratio: number) {\n const angle = (Math.PI * 2 * index) / count - Math.PI / 2;\n return {\n x: svgNumber(CX + Math.cos(angle) * RADIUS * ratio),\n y: svgNumber(CY + Math.sin(angle) * RADIUS * ratio),\n angle,\n };\n}\n\n/** 雷达图 */\nexport const RadarChart = _component(\n <T extends object>({\n data,\n index,\n series,\n max,\n levels = 4,\n grid = 'polygon',\n valueFormat,\n unit,\n height = 300,\n legend,\n _hiddenSeries: hiddenSeries = _bindable<string[]>([]),\n loading = false,\n empty,\n ...rest\n }: RadarChartProps<T>) => {\n const lang = useLang();\n const format = useFormat();\n const resolved = _derived(resolveSeries(series));\n const visible = _derived(resolved.filter((item) => !hiddenSeries.includes(item.key)));\n // 悬停的维度\n let active = _state<number | null>(null);\n\n function toggle(key: string) {\n hiddenSeries = hiddenSeries.includes(key)\n ? hiddenSeries.filter((item) => item !== key)\n : [...hiddenSeries, key];\n }\n\n return () => {\n const count = data.length;\n const values = data.flatMap((row) => visible.map((item) => seriesNumber(row, item.key) ?? 0));\n // 轴的最大值:给了用它,否则取 levels 格整齐步长的整数倍\n const top = max ?? niceStep(Math.max(...values, 1) / levels) * levels;\n const ratioOf = (value: number) => Math.max(0, Math.min(value / top, 1));\n const ring = (ratio: number) =>\n grid === 'circle'\n ? null\n : data\n .map((_row, position) => polar(position, count, ratio))\n .map((p) => `${p.x},${p.y}`)\n .join(' ');\n\n const plot =\n count < 3 ? null : (\n <svg\n {...css.attrs(radarChartStyles.svg)}\n viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n aria-hidden=\"true\"\n onPointerleave={() => (active = null)}\n >\n {Array.from({ length: levels }, (_, level) => {\n const ratio = (level + 1) / levels;\n return grid === 'circle' ? (\n <circle\n key={level}\n cx={CX}\n cy={CY}\n r={RADIUS * ratio}\n {...css.attrs(radarChartStyles.grid)}\n />\n ) : (\n <polygon key={level} points={ring(ratio)!} {...css.attrs(radarChartStyles.grid)} />\n );\n })}\n {data.map((row, position) => {\n const end = polar(position, count, 1);\n const label = polar(position, count, LABEL_RADIUS / RADIUS);\n const cos = Math.cos(label.angle);\n return (\n <g key={position}>\n <line\n x1={CX}\n y1={CY}\n x2={end.x}\n y2={end.y}\n {...css.attrs(\n radarChartStyles.spoke,\n active === position && radarChartStyles.spokeActive,\n )}\n />\n <text\n x={label.x}\n y={label.y}\n text-anchor={Math.abs(cos) < 0.2 ? 'middle' : cos > 0 ? 'start' : 'end'}\n dominant-baseline=\"middle\"\n {...css.attrs(\n radarChartStyles.label,\n active === position && radarChartStyles.labelActive,\n )}\n >\n {String(row[index] ?? '')}\n </text>\n </g>\n );\n })}\n {Array.from({ length: levels }, (_, level) => (\n <text\n key={`tick-${level}`}\n x={CX + 3}\n y={CY - (RADIUS * (level + 1)) / levels}\n dominant-baseline=\"middle\"\n {...css.attrs(radarChartStyles.tick)}\n >\n {format.number((top * (level + 1)) / levels, valueFormat)}\n </text>\n ))}\n {visible.map((item) => {\n const points = data.map((row, position) =>\n polar(position, count, ratioOf(seriesNumber(row, item.key) ?? 0)),\n );\n return (\n <g key={item.key}>\n <polygon\n points={points.map((p) => `${p.x},${p.y}`).join(' ')}\n {...css.attrs(radarChartStyles.area, radarChartStyles.stroke(item.color))}\n />\n {points.map((p, position) => (\n <circle\n key={position}\n cx={p.x}\n cy={p.y}\n r={active === position ? 4 : 2.5}\n {...css.attrs(radarChartStyles.vertex, radarChartStyles.stroke(item.color))}\n />\n ))}\n {active !== null && (\n <text\n x={points[active]!.x}\n y={points[active]!.y - 8}\n text-anchor=\"middle\"\n {...css.attrs(\n radarChartStyles.value,\n radarChartStyles.stroke(item.color),\n radarChartStyles.surfaceStroke,\n )}\n >\n {format.number(seriesValue(data[active]!, item.key) ?? 0, valueFormat)}\n </text>\n )}\n </g>\n );\n })}\n {/* 悬停:每个维度一块扇区 */}\n {data.map((_row, position) => {\n const a = polar(position - 0.5, count, 1.2);\n const b = polar(position + 0.5, count, 1.2);\n return (\n <path\n key={`sector-${position}`}\n d={`M${CX} ${CY} L${a.x} ${a.y} L${b.x} ${b.y} Z`}\n {...css.attrs(radarChartStyles.sector)}\n onPointerenter={() => (active = position)}\n />\n );\n })}\n </svg>\n );\n\n return (\n <ChartFrame\n {...rest}\n unit={unit}\n height={height}\n legend={(legend ?? resolved.length > 1) ? resolved : []}\n hiddenKeys={hiddenSeries}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={<Skeleton sx={radarChartStyles.skeleton} />}\n isEmpty={data.length === 0}\n empty={empty}\n table={{\n columns: [\n lang.chartCategory,\n ...resolved.map((item) => (unit ? `${item.label}(${unit})` : item.label)),\n ],\n rows: data.map((row) => ({\n header: String(row[index] ?? ''),\n cells: resolved.map((item) => {\n const value = seriesValue(row, item.key);\n return value === undefined ? lang.emptyValue : format.number(value, valueFormat);\n }),\n })),\n }}\n plot={plot}\n />\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;;AAiEA,IAAa,mBAAmB,IAAI,OAAO;CACzC,KAAK;EAAE,SAAS;EAAS,OAAO;EAAQ,QAAQ;EAAQ,UAAU;CAAU;CAC5E,MAAM;EAAE,MAAM;EAAQ,QAAQ;EAAgB,aAAa;CAAE;CAC7D,OAAO;EAAE,QAAQ;EAAgB,aAAa;CAAE;CAChD,aAAa;EAAE,QAAQ;EAAc,aAAa;CAAI;CACtD,MAAM;EAAE,MAAM;EAAc,UAAU;CAAM;CAC5C,OAAO;EAAE,MAAM;EAAS,UAAU;CAAO;CACzC,aAAa,EAAE,YAAY,YAAY;CAEvC,MAAM;EAAE,aAAa;EAAM,aAAa;EAAG,gBAAgB;CAAQ;CACnE,QAAQ,EAAE,aAAa,EAAE;CACzB,OAAO;EAAE,UAAU;EAAQ,YAAY;EAAa,YAAY;EAAU,aAAa;CAAE;CAEzF,QAAQ,EAAE,MAAM,cAAc;CAC9B,UAAU;EACR,SAAS;EACT,QAAQ;EACR,aAAa;EACb,cAAc;EACd,cAAc;CAChB;CACA,SAAS,WAAmB;EAAE,QAAQ;EAAO,MAAM;CAAM;CACzD,eAAe,EAAE,QAAQ,WAAW;AACtC,CAAC;AAGD,IAAM,QAAQ;AACd,IAAM,SAAS;AACf,IAAM,KAAK,QAAQ;AACnB,IAAM,KAAK,SAAS;AACpB,IAAM,SAAS;AACf,IAAM,eAAe;;AAGrB,SAAS,MAAM,OAAe,OAAe,OAAe;CAC1D,MAAM,QAAS,KAAK,KAAK,IAAI,QAAS,QAAQ,KAAK,KAAK;CACxD,OAAO;EACL,GAAG,UAAU,KAAK,KAAK,IAAI,KAAK,IAAI,SAAS,KAAK;EAClD,GAAG,UAAU,KAAK,KAAK,IAAI,KAAK,IAAI,SAAS,KAAK;EAClD;CACF;AACF;;AAGA,IAAa,aAAa,0BACxB,QAAA,SAe0B;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,MAAAA,aAAA,QAAA,KAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,UAVf,CAAC;CAAA,MAAA,OAAAA,aAAA,QAAA,QACH,SAAS;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,UAGP,GAAG;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,eAAAC,SAAA,QAAA,uBAEsC,CAAA,GAAE,KAAA,IAAA;CAAA,MAAA,UAAAD,aAAA,QAAA,WAC1C,KAAK;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAEZ,OAAIE,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,OAAO,QAAQ;CACrB,MAAM,SAAS,UAAU;CACzB,MAAM,WAAQC,eAAY,cAAa,OAAA,KAAO,CAAC;CAC/C,MAAM,UAAOA,eAAY,SAAA,MAAS,QAAQ,SAAS,CAAC,aAAA,MAAa,SAAS,KAAK,GAAG,CAAC,CAAC;CAEpF,IAAI,SAAMC,IAAyB,IAAI;CAEvC,SAAS,OAAO,KAAa;EAC3B,aAAA,QAAe,aAAA,MAAa,SAAS,GAAG,IACpC,aAAA,MAAa,QAAQ,SAAS,SAAS,GAAG,IAC1C,CAAC,GAAA,aAAA,OAAiB,GAAG;CAC3B;CAEA,aAAa;EACX,MAAM,QAAQ,KAAA,MAAK;EACnB,MAAM,SAAS,KAAA,MAAK,SAAS,QAAQ,QAAA,MAAQ,KAAK,SAAS,aAAa,KAAK,KAAK,GAAG,KAAK,CAAC,CAAC;EAE5F,MAAM,MAAM,IAAA,SAAO,SAAS,KAAK,IAAI,GAAG,QAAQ,CAAC,IAAC,OAAA,KAAS,IAAC,OAAA;EAC5D,MAAM,WAAW,UAAkB,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,KAAK,CAAC,CAAC;EACvE,MAAM,QAAQ,UACZ,KAAA,UAAS,WACL,OACA,KAAA,MACG,KAAK,MAAM,aAAa,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC,CACtD,KAAK,MAAM,GAAG,EAAE,EAAC,GAAI,EAAE,GAAG,CAAC,CAC3B,KAAK,GAAG;EAEjB,MAAM,OACJ,QAAQ,IAAI,OAAIC,YAAA,OAAAC,cAER,IAAI,MAAM,iBAAiB,GAAG,GAAC;GAAA,WAC1B,OAAO,MAAK,GAAI;GAAQ,eAAA;GAAA,kBAAA,OAAA,OAAA,OAAA,WAEV,OAAA,QAAS;EAAK,CAAA,GAAA;GAEpC,MAAM,KAAK,EAAE,QAAM,OAAA,MAAS,IAAI,GAAG,UAAU;IAC5C,MAAM,SAAS,QAAQ,KAAC,OAAA;IACxB,OAAO,KAAA,UAAS,WAAQD,YAAA,UAAAC,cAAA;KAAA,OAEf;KAAK,MACN;KAAE,MACF;KAAE,KACH,SAAS;IAAK,GACb,IAAI,MAAM,iBAAiB,IAAI,CAAC,GAAA,IAAA,IAAAD,YAAA,WAAAC,cAAA;KAAA,OAGxB;KAAK,UAAU,KAAK,KAAK;IAAC,GAAO,IAAI,MAAM,iBAAiB,IAAI,CAAC,GAAA,IAAA;GAEnF,CAAC;GACA,KAAA,MAAK,KAAK,KAAK,aAAa;IAC3B,MAAM,MAAM,MAAM,UAAU,OAAO,CAAC;IACpC,MAAM,QAAQ,MAAM,UAAU,OAAO,eAAe,MAAM;IAC1D,MAAM,MAAM,KAAK,IAAI,MAAM,KAAK;IAChC,OAAAD,YAAA,KAAA,EAAA,OACU,SAAQ,GAAA,CAAAA,YAAA,QAAAC,cAAA;KAAA,MAER;KAAE,MACF;KAAE,MACF,IAAI;KAAC,MACL,IAAI;IAAC,GACL,IAAI,MACN,iBAAiB,OACjB,OAAA,UAAW,YAAY,iBAAiB,WAC1C,CAAC,GAAA,IAAA,GAAAD,YAAA,QAAAC,cAAA;KAAA,KAGE,MAAM;KAAC,KACP,MAAM;KAAC,eACG,KAAK,IAAI,GAAG,IAAI,KAAM,WAAW,MAAM,IAAI,UAAU;KAAK,qBAAA;IAAA,GAEnE,IAAI,MACN,iBAAiB,OACjB,OAAA,UAAW,YAAY,iBAAiB,WAC1C,CAAC,GAAA,CAEA,OAAO,IAAG,MAAA,UAAW,EAAE,CAAC,CAAA,CAAA,CAAA;GAIjC,CAAC;GACA,MAAM,KAAK,EAAE,QAAM,OAAA,MAAS,IAAI,GAAG,UAAKD,YAAA,QAAAC,cAAA;IAAA,OAEhC,QAAQ;IAAO,KACjB;IAAM,KACN,KAAM,UAAU,QAAQ,KAAE,OAAA;IAAU,qBAAA;GAAA,GAEnC,IAAI,MAAM,iBAAiB,IAAI,CAAC,GAAA,CAEnC,OAAO,OAAQ,OAAO,QAAQ,KAAE,OAAA,OAAU,YAAA,KAAa,CAAC,CAAA,CAE5D;GACA,QAAA,MAAQ,KAAK,SAAS;IACrB,MAAM,SAAS,KAAA,MAAK,KAAK,KAAK,aAC5B,MAAM,UAAU,OAAO,QAAQ,aAAa,KAAK,KAAK,GAAG,KAAK,CAAC,CAAC,CAClE;IACA,OAAAD,YAAA,KAAA,EAAA,OACU,KAAK,IAAG,GAAA;KAAAA,YAAA,WAAAC,cAAA,EAAA,UAEJ,OAAO,KAAK,MAAM,GAAG,EAAE,EAAC,GAAI,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,EAAC,GAChD,IAAI,MAAM,iBAAiB,MAAI,IAAA,KAAE,iBAAiB,cAAM,CAAC,KAAK,KAAK,CAAA,CAAC,CAAC,GAAA,IAAA;KAE1E,OAAO,KAAK,GAAG,aAAQD,YAAA,UAAAC,cAAA;MAAA,OAEf;MAAQ,MACT,EAAE;MAAC,MACH,EAAE;MAAC,KACJ,OAAA,UAAW,WAAW,IAAI;KAAG,GAC5B,IAAI,MAAM,iBAAiB,QAAM,IAAA,KAAE,iBAAiB,cAAM,CAAC,KAAK,KAAK,CAAA,CAAC,CAAC,GAAA,IAAA,CAE9E;KACA,OAAA,UAAW,QAAID,YAAA,QAAAC,cAAA;MAAA,KAET,OAAM,OAAA,MAAQ,CAAE;MAAC,KACjB,OAAM,OAAA,MAAQ,CAAE,IAAI;MAAC,eAAA;KAAA,GAEpB,IAAI,MACN,iBAAiB,OAAK,IAAA,KACtB,iBAAiB,cAAM,CAAC,KAAK,KAAK,CAAA,GAClC,iBAAiB,aACnB,CAAC,GAAA,CAEA,OAAO,OAAO,YAAY,KAAA,MAAA,OAAA,QAAe,KAAK,GAAG,KAAK,GAAC,YAAA,KAAa,CAAC,CAAA;IAEzE,CAAA;GAGP,CAAC;GAEA,KAAA,MAAK,KAAK,MAAM,aAAa;IAC5B,MAAM,IAAI,MAAM,WAAW,IAAK,OAAO,GAAG;IAC1C,MAAM,IAAI,MAAM,WAAW,IAAK,OAAO,GAAG;IAC1C,OAAAD,YAAA,QAAAC,cAAA;KAAA,OAES,UAAU;KAAU,KACtB,IAAI,GAAE,GAAI,GAAE,IAAK,EAAE,EAAC,GAAI,EAAE,EAAC,IAAK,EAAE,EAAC,GAAI,EAAE,EAAC;IAAI,GAC7C,IAAI,MAAM,iBAAiB,MAAM,GAAC,EAAA,wBACf,OAAA,QAAS,SAAS,CAAA,GAAA,IAAA;GAG/C,CAAC;EAAC,CAAA;EAIR,OAAAD,YAAA,YAAAC,cAEQ,MAAI;GAAA,QAAA,KAAA;GAAA,UAAA,OAAA;GAAA,UAGC,OAAA,SAAU,SAAA,MAAS,SAAS,IAAC,SAAA,QAAe,CAAA;GAAE,cAAA,aAAA;GAAA,kBAEvC;GAAM,WAAA,QAAA;GAAA,YAAAD,YAAA,UAAA,EAAA,MAEE,iBAAiB,SAAQ,GAAA,IAAA;GAAA,WACxC,KAAA,MAAK,WAAW;GAAC,SAAA,MAAA;GAAA,SAEnB;IACL,SAAS,CACP,KAAK,eACL,GAAG,SAAA,MAAS,KAAK,SAAU,KAAA,QAAO,GAAG,KAAK,MAAK,GAAA,KAAA,MAAA,KAAc,KAAK,KAAM,CAAC;IAE3E,MAAM,KAAA,MAAK,KAAK,SAAS;KACvB,QAAQ,OAAO,IAAG,MAAA,UAAW,EAAE;KAC/B,OAAO,SAAA,MAAS,KAAK,SAAS;MAC5B,MAAM,QAAQ,YAAY,KAAK,KAAK,GAAG;MACvC,OAAO,UAAU,KAAA,IAAY,KAAK,aAAa,OAAO,OAAO,OAAK,YAAA,KAAa;KACjF,CAAC;IACH,EAAE;GACJ;GAAC,QACK;EAAI,CAAA,GAAA,IAAA;CAGhB;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
|
1
|
+
{"version":3,"file":"RadarChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/charts/RadarChart.tsx"],"sourcesContent":["/**\n * 雷达图:几个维度上同时比较几个对象(供应商的质量、交期、价格、服务评分,方案的各项指标)。\n * 每个维度一根轴,从中心往外是 0 到 max;每个系列连成一个多边形,填一层浅色。\n *\n * <RadarChart\n * aria-label=\"供应商评分\"\n * data={[{ dimension: '质量', huachen: 86, hengyuan: 78 }, …]}\n * index=\"dimension\"\n * series={[{ key: 'huachen', label: '华辰精密' }, { key: 'hengyuan', label: '恒远五金' }]}\n * max={100}\n * />\n *\n * Unovis 没有雷达图:这里用 SVG 直接画,外层结构(图例、单位、加载与空状态、给读屏的数据表)同其他图表。\n * 悬停一个维度时那根轴加粗,各系列在这一维的数值标在顶点旁边;点图例隐藏系列。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { Skeleton } from '../feedback/Skeleton';\nimport type { PartProps } from '../utils/props';\nimport { niceStep } from './axis-ticks';\nimport { ChartFrame, type ChartFrameParts } from './frame';\nimport { resolveSeries, seriesNumber, seriesValue, type ChartSeries } from './series';\nimport { svgNumber } from '../utils/data/number';\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface RadarChartProps<T extends object>\n extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 数据:每一行是一个维度(质量、交期…) */\n data: readonly T[];\n /** 维度名的字段 */\n index: keyof T & string;\n /** 系列:每个系列连成一个多边形 */\n series: readonly ChartSeries<T>[];\n /** 轴的最大值;不写时按数据取一个整齐的值 */\n max?: number;\n /**\n * 网格的圈数\n * @default 4\n */\n levels?: number;\n /** 网格画成多边形(默认)或圆 */\n grid?: 'polygon' | 'circle';\n /** 数值的格式:刻度、顶点旁的数值、数据表共用 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 300\n */\n height?: number | string;\n /** 图例:默认多于一个系列时显示 */\n legend?: boolean;\n /** 隐藏的系列:点图例时写回,父级可以写 _hiddenSeries={keys} */\n _hiddenSeries?: string[];\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n}\n\n/** RadarChart 的样式 */\nexport const radarChartStyles = css.create({\n svg: { display: 'block', width: '100%', height: '100%', overflow: 'visible' },\n grid: { fill: 'none', stroke: '_borderMuted', strokeWidth: 1 },\n spoke: { stroke: '_borderMuted', strokeWidth: 1 },\n spokeActive: { stroke: '_textMuted', strokeWidth: 1.5 },\n tick: { fill: '_textMuted', fontSize: '9px' },\n label: { fill: '_text', fontSize: '11px' },\n labelActive: { fontWeight: '_semibold' },\n // 几个系列叠在一起:填充很浅,混在一起也不发灰\n area: { fillOpacity: 0.08, strokeWidth: 2, strokeLinejoin: 'round' },\n vertex: { strokeWidth: 0 },\n value: { fontSize: '10px', fontWeight: '_semibold', paintOrder: 'stroke', strokeWidth: 3 },\n // 悬停用的扇区:透明,只接指针\n sector: { fill: 'transparent' },\n skeleton: {\n display: 'block',\n height: '100%',\n aspectRatio: '1',\n marginInline: 'auto',\n borderRadius: '50%',\n },\n stroke: (color: string) => ({ stroke: color, fill: color }),\n surfaceStroke: { stroke: '_surface' },\n});\n\n// 画布:360 × 300,中心 (180, 150),半径 108;文字在半径 124 的圈上\nconst WIDTH = 360;\nconst HEIGHT = 300;\nconst CX = WIDTH / 2;\nconst CY = HEIGHT / 2;\nconst RADIUS = 108;\nconst LABEL_RADIUS = 124;\n\n/** 第 index 个维度(共 count 个)、比例 ratio 处的点:第一个维度在正上方,顺时针 */\nfunction polar(index: number, count: number, ratio: number) {\n const angle = (Math.PI * 2 * index) / count - Math.PI / 2;\n return {\n x: svgNumber(CX + Math.cos(angle) * RADIUS * ratio),\n y: svgNumber(CY + Math.sin(angle) * RADIUS * ratio),\n angle,\n };\n}\n\n/** 雷达图 */\nexport const RadarChart = _component(\n <T extends object>({\n data,\n index,\n series,\n max,\n levels = 4,\n grid = 'polygon',\n valueFormat,\n unit,\n height = 300,\n legend,\n _hiddenSeries: hiddenSeries = _bindable<string[]>([]),\n loading = false,\n empty,\n ...rest\n }: RadarChartProps<T>) => {\n const lang = useLang();\n const format = useFormat();\n const resolved = _derived(resolveSeries(series));\n const visible = _derived(resolved.filter((item) => !hiddenSeries.includes(item.key)));\n // 悬停的维度\n let active = _state<number | null>(null);\n\n function toggle(key: string) {\n hiddenSeries = hiddenSeries.includes(key)\n ? hiddenSeries.filter((item) => item !== key)\n : [...hiddenSeries, key];\n }\n\n return () => {\n const count = data.length;\n const values = data.flatMap((row) => visible.map((item) => seriesNumber(row, item.key) ?? 0));\n // 轴的最大值:给了用它,否则取 levels 格整齐步长的整数倍\n const top = max ?? niceStep(Math.max(...values, 1) / levels) * levels;\n const ratioOf = (value: number) => Math.max(0, Math.min(value / top, 1));\n const ring = (ratio: number) =>\n grid === 'circle'\n ? null\n : data\n .map((_row, position) => polar(position, count, ratio))\n .map((p) => `${p.x},${p.y}`)\n .join(' ');\n\n const plot =\n count < 3 ? null : (\n <svg\n {...css.attrs(radarChartStyles.svg)}\n viewBox={`0 0 ${WIDTH} ${HEIGHT}`}\n aria-hidden=\"true\"\n onPointerleave={() => (active = null)}\n >\n {Array.from({ length: levels }, (_, level) => {\n const ratio = (level + 1) / levels;\n return grid === 'circle' ? (\n <circle\n key={level}\n cx={CX}\n cy={CY}\n r={RADIUS * ratio}\n {...css.attrs(radarChartStyles.grid)}\n />\n ) : (\n <polygon key={level} points={ring(ratio)!} {...css.attrs(radarChartStyles.grid)} />\n );\n })}\n {data.map((row, position) => {\n const end = polar(position, count, 1);\n const label = polar(position, count, LABEL_RADIUS / RADIUS);\n const cos = Math.cos(label.angle);\n return (\n <g key={position}>\n <line\n x1={CX}\n y1={CY}\n x2={end.x}\n y2={end.y}\n {...css.attrs(\n radarChartStyles.spoke,\n active === position && radarChartStyles.spokeActive,\n )}\n />\n <text\n x={label.x}\n y={label.y}\n text-anchor={Math.abs(cos) < 0.2 ? 'middle' : cos > 0 ? 'start' : 'end'}\n dominant-baseline=\"middle\"\n {...css.attrs(\n radarChartStyles.label,\n active === position && radarChartStyles.labelActive,\n )}\n >\n {String(row[index] ?? '')}\n </text>\n </g>\n );\n })}\n {Array.from({ length: levels }, (_, level) => (\n <text\n key={`tick-${level}`}\n x={CX + 3}\n y={CY - (RADIUS * (level + 1)) / levels}\n dominant-baseline=\"middle\"\n {...css.attrs(radarChartStyles.tick)}\n >\n {format.number((top * (level + 1)) / levels, valueFormat)}\n </text>\n ))}\n {visible.map((item) => {\n const points = data.map((row, position) =>\n polar(position, count, ratioOf(seriesNumber(row, item.key) ?? 0)),\n );\n return (\n <g key={item.key}>\n <polygon\n points={points.map((p) => `${p.x},${p.y}`).join(' ')}\n {...css.attrs(radarChartStyles.area, radarChartStyles.stroke(item.color))}\n />\n {points.map((p, position) => (\n <circle\n key={position}\n cx={p.x}\n cy={p.y}\n r={active === position ? 4 : 2.5}\n {...css.attrs(radarChartStyles.vertex, radarChartStyles.stroke(item.color))}\n />\n ))}\n {active !== null && (\n <text\n x={points[active]!.x}\n y={points[active]!.y - 8}\n text-anchor=\"middle\"\n {...css.attrs(\n radarChartStyles.value,\n radarChartStyles.stroke(item.color),\n radarChartStyles.surfaceStroke,\n )}\n >\n {format.number(seriesValue(data[active]!, item.key) ?? 0, valueFormat)}\n </text>\n )}\n </g>\n );\n })}\n {/* 悬停:每个维度一块扇区 */}\n {data.map((_row, position) => {\n const a = polar(position - 0.5, count, 1.2);\n const b = polar(position + 0.5, count, 1.2);\n return (\n <path\n key={`sector-${position}`}\n d={`M${CX} ${CY} L${a.x} ${a.y} L${b.x} ${b.y} Z`}\n {...css.attrs(radarChartStyles.sector)}\n onPointerenter={() => (active = position)}\n />\n );\n })}\n </svg>\n );\n\n return (\n <ChartFrame\n {...rest}\n unit={unit}\n height={height}\n legend={(legend ?? resolved.length > 1) ? resolved : []}\n hiddenKeys={hiddenSeries}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={<Skeleton sx={radarChartStyles.skeleton} />}\n isEmpty={data.length === 0}\n empty={empty}\n table={{\n columns: [\n lang.chartCategory,\n ...resolved.map((item) => (unit ? `${item.label}(${unit})` : item.label)),\n ],\n rows: data.map((row) => ({\n header: String(row[index] ?? ''),\n cells: resolved.map((item) => {\n const value = seriesValue(row, item.key);\n return value === undefined ? lang.emptyValue : format.number(value, valueFormat);\n }),\n })),\n }}\n plot={plot}\n />\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
2
|
import type { VNodeChild } from 'vue';
|
|
3
3
|
import { type NumericFormat } from '../config/lang/format';
|
|
4
4
|
import type { PartProps } from '../utils/props';
|
|
@@ -7,7 +7,7 @@ import { flowData, resolveFlowNodes } from "./flow.js";
|
|
|
7
7
|
import { useSingleChart } from "./single.js";
|
|
8
8
|
import { computed, createVNode, shallowRef } from "vue";
|
|
9
9
|
import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
10
|
-
import
|
|
10
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
11
11
|
import { FitMode, Sankey, SankeyNodeAlign } from "@unovis/ts";
|
|
12
12
|
//#region src/charts/SankeyChart.tsx
|
|
13
13
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SankeyChart.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/charts/SankeyChart.tsx"],"sourcesContent":["/**\n * 桑基图:节点之间的流量画成粗细不同的带子,看量从哪来、到哪去、在哪流失(转化漏斗、预算分配、能源流向)。\n *\n * <SankeyChart aria-label=\"注册转化\" nodes={steps} links={flows} unit=\"人\" />\n *\n * 节点是 { id, label?, color? },流向是 { source, target, value }(value 可以是 Decimal、bigint,要大于 0;不能成环)。\n * 带子取起点节点的颜色;悬停带子出“起点 → 终点”的流量,悬停节点出它的总量。节点旁写名字与总量。\n * 单位、加载与空状态、给读屏的数据表(每条流向一行)同其他图表(见 ChartFrame)。\n */\nimport { FitMode, Sankey, SankeyNodeAlign } from '@unovis/ts';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport
|
|
1
|
+
{"version":3,"file":"SankeyChart.js","names":["_vtp_readonlyProp","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/charts/SankeyChart.tsx"],"sourcesContent":["/**\n * 桑基图:节点之间的流量画成粗细不同的带子,看量从哪来、到哪去、在哪流失(转化漏斗、预算分配、能源流向)。\n *\n * <SankeyChart aria-label=\"注册转化\" nodes={steps} links={flows} unit=\"人\" />\n *\n * 节点是 { id, label?, color? },流向是 { source, target, value }(value 可以是 Decimal、bigint,要大于 0;不能成环)。\n * 带子取起点节点的颜色;悬停带子出“起点 → 终点”的流量,悬停节点出它的总量。节点旁写名字与总量。\n * 单位、加载与空状态、给读屏的数据表(每条流向一行)同其他图表(见 ChartFrame)。\n */\nimport { FitMode, Sankey, SankeyNodeAlign } from '@unovis/ts';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { colors, fontSizes } from '../config/theme/tokens';\nimport { Skeleton } from '../feedback/Skeleton';\nimport type { PartProps } from '../utils/props';\nimport { flowData, resolveFlowNodes, type FlowLink, type FlowNode } from './flow';\nimport { ChartFrame, chartTooltip, useChartValueText, type ChartFrameParts } from './frame';\nimport { useSingleChart, type SingleChart } from './single';\n\n/** 节点怎样排:justify 两端对齐(默认),left、right 靠向一侧,center 居中 */\nexport interface SankeyAligns {\n /** 两端对齐(默认):按离起点的远近分列,没有流出的节点都排到最右一列 */\n justify: unknown;\n /** 靠左:每个节点排在离起点最近的一列 */\n left: unknown;\n /** 靠右:每个节点排在离终点最近的一列 */\n right: unknown;\n /** 居中:同靠左,但没有流入的节点往右挪,贴着它流向的节点 */\n center: unknown;\n}\n\n/** 未声明的属性落到外层 div(role=\"figure\")上,aria-label 是图表的名称 */\nexport interface SankeyChartProps extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 节点 */\n nodes: readonly FlowNode[];\n /** 流向 */\n links: readonly FlowLink[];\n /** 数值的格式(可缩放,如以万元为单位):节点旁的总量、提示框、数据表共用 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方,数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 320\n */\n height?: number | string;\n /**\n * 节点的排法\n * @default 'justify'\n */\n align?: keyof SankeyAligns;\n /**\n * 悬停时的提示框\n * @default true\n */\n tooltip?: boolean;\n /**\n * 加载中:绘图区显示骨架,带 aria-busy\n * @default false\n */\n loading?: boolean;\n /** 没有数据时显示的内容,默认是“暂无数据” */\n empty?: VNodeChild;\n}\n\n/** SankeyChart 的样式:root(--vis-sankey-* 主题变量)、skeleton */\nexport const sankeyChartStyles = css.create({\n root: {\n '--vis-sankey-node-label-color': colors.text,\n '--vis-sankey-node-label-font-size': fontSizes.xs,\n '--vis-sankey-node-label-font-weight': '500',\n '--vis-sankey-node-label-background-fill-color': colors.surface,\n '--vis-sankey-node-label-background-stroke-color': colors.borderMuted,\n '--vis-sankey-node-sublabel-font-size': fontSizes.xs,\n '--vis-sankey-link-opacity': '0.35',\n '--vis-sankey-link-hover-opacity': '0.6',\n },\n skeleton: { display: 'block', width: '100%', height: '100%' },\n});\n\nconst ALIGNS: Record<keyof SankeyAligns, SankeyNodeAlign> = {\n justify: SankeyNodeAlign.Justify,\n left: SankeyNodeAlign.Left,\n right: SankeyNodeAlign.Right,\n center: SankeyNodeAlign.Center,\n};\n\n/** 交给 Unovis 的节点、流向 */\ntype Data = ReturnType<typeof flowData>;\ntype Node = Data['nodes'][number];\ntype Link = Data['links'][number];\n/** Unovis 布局后:流向的起点、终点换成了节点对象,节点带上了总量 value */\ntype LaidOutNode = Node & { value?: number };\ntype LaidOutLink = Omit<Link, 'source' | 'target'> & { source: LaidOutNode; target: LaidOutNode };\n\n/** 桑基图 */\nexport const SankeyChart = _component(\n ({\n nodes,\n links,\n valueFormat,\n unit,\n height = 320,\n align = 'justify',\n tooltip = true,\n loading = false,\n empty,\n sx,\n ...rest\n }: SankeyChartProps) => {\n const lang = useLang();\n const format = useFormat();\n const resolved = _derived(resolveFlowNodes(nodes));\n const valueText = useChartValueText(() => ({ valueFormat, unit }));\n const labelOf = (id: string) => resolved.get(id)?.label ?? id;\n\n let plot = _state.raw<HTMLElement | null>(null);\n const chart: SingleChart = useSingleChart<{ nodes: Node[]; links?: Link[] }>(() => ({\n element: plot,\n ready: !loading && nodes.length > 0,\n tooltip,\n build: (instance) => {\n const sankey = instance(\n 'sankey',\n () => new Sankey<Node, Link>({ linkValue: (link) => link.amount }),\n );\n sankey.setConfig({\n linkValue: (link) => link.amount,\n nodeColor: (node) => node.color,\n linkColor: (link) => link.source.color,\n nodeAlign: ALIGNS[align],\n label: (node) => node.label,\n subLabel: (node) => (node.value === undefined ? '' : valueText(node.value)),\n nodePadding: 16,\n nodeWidth: 12,\n labelMaxWidth: 120,\n labelMaxWidthTakeAvailableSpace: true,\n labelFit: FitMode.Wrap,\n labelBackground: true,\n enableZoom: false,\n });\n return {\n component: sankey,\n data: flowData(resolved, links),\n triggers: {\n [Sankey.selectors.link]: (link: LaidOutLink) =>\n chart.tooltip(\n chartTooltip(lang.chartFlowLabel(link.source.label, link.target.label), [\n {\n label: lang.chartValue,\n color: link.source.color,\n value: valueText(link.value),\n },\n ]),\n ),\n [Sankey.selectors.node]: (node: LaidOutNode) =>\n chart.tooltip(\n chartTooltip(node.label, [\n { label: lang.chartTotal, color: node.color, value: valueText(node.value) },\n ]),\n ),\n },\n };\n },\n }));\n\n return () => (\n <ChartFrame\n {...rest}\n sx={[sankeyChartStyles.root, sx]}\n unit={unit}\n height={height}\n legend={[]}\n hiddenKeys={[]}\n onLegendToggle={() => {}}\n loading={loading}\n skeleton={<Skeleton sx={sankeyChartStyles.skeleton} />}\n isEmpty={nodes.length === 0}\n empty={empty}\n table={{\n columns: [lang.chartFlow, unit ? `${lang.chartValue}(${unit})` : lang.chartValue],\n rows: links.map((link) => ({\n header: lang.chartFlowLabel(labelOf(link.source), labelOf(link.target)),\n cells: [format.number(link.value, valueFormat)],\n })),\n }}\n plotRef={(element) => (plot = element)}\n />\n );\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAqEA,IAAa,oBAAoB,IAAI,OAAO;CAC1C,MAAM;EACJ,iCAAiC,OAAO;EACxC,qCAAqC,UAAU;EAC/C,uCAAuC;EACvC,iDAAiD,OAAO;EACxD,mDAAmD,OAAO;EAC1D,wCAAwC,UAAU;EAClD,6BAA6B;EAC7B,mCAAmC;CACrC;CACA,UAAU;EAAE,SAAS;EAAS,OAAO;EAAQ,QAAQ;CAAO;AAC9D,CAAC;AAED,IAAM,SAAsD;CAC1D,SAAS,gBAAgB;CACzB,MAAM,gBAAgB;CACtB,OAAO,gBAAgB;CACvB,QAAQ,gBAAgB;AAC1B;;;;AAWA,IAAa,cAAc,0BACzB,QAAA,SAYwB;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,UAPb,GAAG;CAAA,MAAA,QAAAA,aAAA,QAAA,SACJ,SAAS;CAAA,MAAA,UAAAA,aAAA,QAAA,WACP,IAAI;CAAA,MAAA,UAAAA,aAAA,QAAA,WACJ,KAAK;CAAA,MAAA,QAAAA,aAAA,QAAA,OAAA;CAAA,MAAA,KAAAA,aAAA,QAAA,IAAA;CAAA,MAGZ,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,OAAO,QAAQ;CACrB,MAAM,SAAS,UAAU;CACzB,MAAM,WAAQC,eAAY,iBAAgB,MAAA,KAAM,CAAC;CACjD,MAAM,YAAY,yBAAyB;EAAE,aAAW,YAAA;EAAE,MAAI,KAAA;CAAC,EAAE;CACjE,MAAM,WAAW,OAAe,SAAA,MAAS,IAAI,EAAE,CAAC,EAAE,SAAS;CAE3D,IAAI,OAAIC,WAAkC,IAAI;CAC9C,MAAM,QAAqB,sBAAyD;EAClF,SAAO,KAAA;EACP,OAAO,CAAA,QAAA,SAAY,MAAA,MAAM,SAAS;EAClC,SAAO,QAAA;EACP,QAAQ,aAAa;GACnB,MAAM,SAAS,SACb,gBACM,IAAI,OAAmB,EAAE,YAAY,SAAS,KAAK,OAAO,CAAC,CACnE;GACA,OAAO,UAAU;IACf,YAAY,SAAS,KAAK;IAC1B,YAAY,SAAS,KAAK;IAC1B,YAAY,SAAS,KAAK,OAAO;IACjC,WAAW,OAAM,MAAA;IACjB,QAAQ,SAAS,KAAK;IACtB,WAAW,SAAU,KAAK,UAAU,KAAA,IAAY,KAAK,UAAU,KAAK,KAAK;IACzE,aAAa;IACb,WAAW;IACX,eAAe;IACf,iCAAiC;IACjC,UAAU,QAAQ;IAClB,iBAAiB;IACjB,YAAY;GACd,CAAC;GACD,OAAO;IACL,WAAW;IACX,MAAM,SAAQ,SAAA,OAAA,MAAA,KAAgB;IAC9B,UAAU;MACP,OAAO,UAAU,QAAQ,SACxB,MAAM,QACJ,aAAa,KAAK,eAAe,KAAK,OAAO,OAAO,KAAK,OAAO,KAAK,GAAG,CACtE;MACE,OAAO,KAAK;MACZ,OAAO,KAAK,OAAO;MACnB,OAAO,UAAU,KAAK,KAAK;KAC7B,CAAC,CACF,CACH;MACD,OAAO,UAAU,QAAQ,SACxB,MAAM,QACJ,aAAa,KAAK,OAAO,CACvB;MAAE,OAAO,KAAK;MAAY,OAAO,KAAK;MAAO,OAAO,UAAU,KAAK,KAAK;KAAE,CAAC,CAC5E,CACH;IACJ;GACF;EACF;CACF,EAAE;CAEF,aAAOC,YAAA,YAAAC,cAEC,MAAI;EAAA,MACJ,CAAC,kBAAkB,MAAI,GAAA,KAAA;EAAK,QAAA,KAAA;EAAA,UAAA,OAAA;EAAA,UAAA,OAAA,OAAA,OAAA,KAGxB,CAAA;EAAE,cAAA,OAAA,OAAA,OAAA,KACE,CAAA;EAAE,kBAAA,OAAA,OAAA,OAAA,WACQ,CAAC;EAAC,WAAA,QAAA;EAAA,YAAAD,YAAA,UAAA,EAAA,MAEA,kBAAkB,SAAQ,GAAA,IAAA;EAAA,WACzC,MAAA,MAAM,WAAW;EAAC,SAAA,MAAA;EAAA,SAEpB;GACL,SAAS,CAAC,KAAK,WAAW,KAAA,QAAO,GAAG,KAAK,WAAU,GAAA,KAAA,MAAA,KAAc,KAAK,UAAU;GAChF,MAAM,MAAA,MAAM,KAAK,UAAU;IACzB,QAAQ,KAAK,eAAe,QAAQ,KAAK,MAAM,GAAG,QAAQ,KAAK,MAAM,CAAC;IACtE,OAAO,CAAC,OAAO,OAAO,KAAK,OAAK,YAAA,KAAa,CAAC;GAChD,EAAE;EACJ;EAAC,WAAA,OAAA,OAAA,OAAA,MACS,YAAa,KAAA,QAAO;CAAQ,CAAA,GAAA,IAAA;AAG5C,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
2
|
import type { VNodeChild } from 'vue';
|
|
3
3
|
import { type NumericFormat } from '../config/lang/format';
|
|
4
4
|
import type { PartProps } from '../utils/props';
|
|
@@ -7,7 +7,7 @@ import { resolveColor, seriesValue } from "./series.js";
|
|
|
7
7
|
import { useSingleChart } from "./single.js";
|
|
8
8
|
import { computed, createVNode, shallowRef } from "vue";
|
|
9
9
|
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
10
|
-
import
|
|
10
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
11
11
|
import { Treemap } from "@unovis/ts";
|
|
12
12
|
//#region src/charts/TreemapChart.tsx
|
|
13
13
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreemapChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/charts/TreemapChart.tsx"],"sourcesContent":["/**\n * 矩形树图:一个总量按层级分块(销售额按区域 → 供应商、费用按科目),块的面积是数值,一眼看出谁占得多。\n *\n * <TreemapChart\n * aria-label=\"采购额构成\"\n * data={savings}\n * groups={['region', 'supplier']} // 从外到内的层级\n * value=\"amount\"\n * unit=\"万元\"\n * />\n *\n * 数据是扁平的明细,按 groups 的字段逐级分组(Unovis 的 Treemap);同一个顶层分组同一种颜色(按色板),\n * 里面的块按亮度区分;点图例隐藏一个顶层分组,占比按剩下的算。悬停看路径、数值与占比;读屏的数据表列出每一块。\n */\nimport { Treemap, type TreemapNode } from '@unovis/ts';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport
|
|
1
|
+
{"version":3,"file":"TreemapChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/charts/TreemapChart.tsx"],"sourcesContent":["/**\n * 矩形树图:一个总量按层级分块(销售额按区域 → 供应商、费用按科目),块的面积是数值,一眼看出谁占得多。\n *\n * <TreemapChart\n * aria-label=\"采购额构成\"\n * data={savings}\n * groups={['region', 'supplier']} // 从外到内的层级\n * value=\"amount\"\n * unit=\"万元\"\n * />\n *\n * 数据是扁平的明细,按 groups 的字段逐级分组(Unovis 的 Treemap);同一个顶层分组同一种颜色(按色板),\n * 里面的块按亮度区分;点图例隐藏一个顶层分组,占比按剩下的算。悬停看路径、数值与占比;读屏的数据表列出每一块。\n */\nimport { Treemap, type TreemapNode } from '@unovis/ts';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { Skeleton } from '../feedback/Skeleton';\nimport { toNumber, type NumericValue } from '../utils/data/numeric';\nimport type { PartProps } from '../utils/props';\nimport { chartTooltip, ChartFrame, type ChartFrameParts } from './frame';\nimport { resolveColor, seriesValue, type NumericKey } from './series';\nimport { useSingleChart, type SingleChart } from './single';\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface TreemapChartProps<T extends object>\n extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 明细 */\n data: readonly T[];\n /** 分组的字段,从外到内(区域、供应商) */\n groups: readonly (keyof T & string)[];\n /** 面积的数值字段 */\n value: NumericKey<T>;\n /** 数值的格式 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方,提示框与数据表的数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 300\n */\n height?: number | string;\n /** 外层分组也写名字(块够大时) */\n groupLabels?: boolean;\n /** 隐藏的顶层分组:点图例时写回,父级可以写 _hiddenGroups={keys} */\n _hiddenGroups?: string[];\n /** 加载中:绘图区显示骨架 */\n loading?: boolean;\n /** 没有数据时显示的内容 */\n empty?: VNodeChild;\n /** 悬停时的提示框,默认 true */\n tooltip?: boolean;\n}\n\n/** TreemapChart 的样式 */\nexport const treemapChartStyles = css.create({\n skeleton: { display: 'block', width: '100%', height: '100%' },\n});\n\n/** 矩形树图 */\nexport const TreemapChart = _component(\n <T extends object>({\n data,\n groups,\n value,\n valueFormat,\n unit,\n height = 300,\n groupLabels = false,\n _hiddenGroups: hiddenGroups = _bindable<string[]>([]),\n loading = false,\n empty,\n tooltip = true,\n ...rest\n }: TreemapChartProps<T>) => {\n const lang = useLang();\n const format = useFormat();\n const numberOf = (row: T) => {\n const amount = seriesValue(row, value);\n return amount === undefined ? 0 : Math.max(toNumber(amount), 0);\n };\n const topOf = (row: T) => String(row[groups[0]!] ?? '');\n const visible = _derived(data.filter((row) => !hiddenGroups.includes(topOf(row))));\n const total = _derived(visible.reduce((sum, row) => sum + numberOf(row), 0));\n // 顶层分组的颜色:按第一次出现的顺序取色板\n const topColors = _derived(\n new Map(\n [...new Set(data.map(topOf))].map((key, position) => [\n key,\n resolveColor(undefined, position),\n ]),\n ),\n );\n const valueText = (amount: NumericValue) =>\n format.number(amount, unit ? { ...valueFormat, suffix: unit } : valueFormat);\n const shareText = (amount: number) =>\n total === 0\n ? lang.emptyValue\n : format.number(amount / total, { style: 'percent', maximumFractionDigits: 1 });\n /** 一个节点的路径:从顶层到它 */\n const pathOf = (node: TreemapNode<T>) =>\n node\n .ancestors()\n .reverse()\n .slice(1)\n .map((item) => item.data.key ?? '')\n .join(' / ');\n\n function toggle(key: string) {\n hiddenGroups = hiddenGroups.includes(key)\n ? hiddenGroups.filter((item) => item !== key)\n : [...hiddenGroups, key];\n }\n\n let plot = _state.raw<HTMLElement | null>(null);\n const chart: SingleChart = useSingleChart<T[]>(() => ({\n element: plot,\n ready: !loading && visible.length > 0,\n tooltip,\n build: (instance) => {\n const treemap = instance('treemap', () => new Treemap<T>({ layers: [] }));\n treemap.setConfig({\n value: numberOf,\n layers: groups.map((key) => (row: T) => String(row[key] ?? '')),\n // 外层分组是浅色的底,叶子是实色:同一组里的块靠底色的缝隙分开\n tileColor: (node) => {\n const base =\n topColors.get(node.topLevelParent?.data.key ?? '') ?? resolveColor(undefined, 0);\n return node.children ? `color-mix(in srgb, ${base} 18%, transparent)` : base;\n },\n tileLabel: (node) => node.data.key ?? '',\n labelInternalNodes: groupLabels,\n enableTileLabelFontSizeVariation: false,\n tilePadding: 3,\n // 分组的名字写在顶边留出的地方\n tilePaddingTop: groupLabels ? 20 : undefined,\n tileBorderRadius: 4,\n });\n return {\n component: treemap,\n data: [...visible],\n triggers: {\n [Treemap.selectors.tile]: (node: TreemapNode<T>) =>\n chart.tooltip(\n chartTooltip(pathOf(node), [\n {\n label: lang.chartValue,\n color: topColors.get(node.topLevelParent?.data.key ?? '') ?? 'transparent',\n value: valueText(node.value),\n },\n { label: lang.chartShare, color: 'transparent', value: shareText(node.value) },\n ]),\n ),\n },\n };\n },\n }));\n\n return () => (\n <ChartFrame\n {...rest}\n unit={unit}\n height={height}\n legend={[...topColors].map(([key, color]) => ({ key, label: key, color }))}\n hiddenKeys={hiddenGroups}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={<Skeleton sx={treemapChartStyles.skeleton} />}\n isEmpty={data.length === 0}\n empty={empty}\n table={{\n columns: [\n lang.chartCategory,\n unit ? `${lang.chartValue}(${unit})` : lang.chartValue,\n lang.chartShare,\n ],\n rows: visible.map((row) => ({\n header: groups.map((key) => String(row[key] ?? '')).join(' / '),\n cells: [valueText(seriesValue(row, value) ?? 0), shareText(numberOf(row))],\n })),\n }}\n plotRef={(element) => (plot = element)}\n />\n );\n },\n);\n"],"mappings":"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"}
|
package/dist/charts/XYChart.d.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 右侧的刻度文字是不裁剪的 Plotline 标签。
|
|
14
14
|
*/
|
|
15
15
|
import { type XYComponentCore } from '@unovis/ts';
|
|
16
|
-
import
|
|
16
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
17
17
|
import { type VNodeChild } from 'vue';
|
|
18
18
|
import { type NumericFormat } from '../config/lang/format';
|
|
19
19
|
import { type NumericValue } from '../utils/data/numeric';
|
package/dist/charts/XYChart.js
CHANGED
|
@@ -11,7 +11,7 @@ import { ChartFrame, chartDuration, chartTooltip, createChartInstances, uniqueHi
|
|
|
11
11
|
import { resolveColor, resolveSeries, seriesNumber, seriesValue } from "./series.js";
|
|
12
12
|
import { computed, createVNode, shallowRef, useId } from "vue";
|
|
13
13
|
import { _component, bindable, effect, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
14
|
-
import
|
|
14
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
15
15
|
import { Axis, AxisType, Crosshair, Plotband, PlotbandLabelPosition, Plotline, PlotlineLabelPosition, PlotlineLineStylePresets, Position, Scatter, Tooltip, XYContainer } from "@unovis/ts";
|
|
16
16
|
//#region src/charts/XYChart.tsx
|
|
17
17
|
/**
|