@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
package/dist/input/Rating.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
2
|
import { type IconData } from '../base/Icon';
|
|
3
3
|
import { type PartProps } from '../utils/props';
|
|
4
4
|
import { type TextSize } from '../utils/style/typography';
|
package/dist/input/Rating.js
CHANGED
|
@@ -8,7 +8,7 @@ import { visuallyHiddenStyles } from "../base/VisuallyHidden.js";
|
|
|
8
8
|
import { useFieldControl } from "../form/Field.js";
|
|
9
9
|
import { createVNode, ref, useId } from "vue";
|
|
10
10
|
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
11
|
-
import
|
|
11
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
12
12
|
import { Star } from "@lucide/icons";
|
|
13
13
|
//#region src/input/Rating.tsx
|
|
14
14
|
/**
|
package/dist/input/Rating.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Rating.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/input/Rating.tsx"],"sourcesContent":["/**\n * 评分:几颗星(或别的图标)里选一个分数,供应商评价、满意度、优先级。可以半星,可以只读显示。\n *\n * <Field label=\"交付质量\"><Rating _value={score} /></Field>\n * <Rating value={4.5} readonly /> 只读:一个 role=\"img\",读“4.5 星,满分 5 星”\n * <Rating _value={score} allowHalf count={10} icon={Heart} tone=\"danger\" />\n *\n * 可编辑时是单选组(role=\"radiogroup\"):每颗星是一个原生 radio(视觉上隐藏),方向键、表单提交、读屏都是原生的;\n * 名称是“3 星”这样的文字(lang.ratingStar)。指针悬停时预览将要选的分数;再点一次已选的分数清空(clearable,默认开)。\n * 半星:每颗星左右各一半,各是一个 radio。部件:Root(div)、Star(span,每颗星)、Icon。\n */\nimport { Star } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFieldControl } from '../form/Field';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport { t } from '../config/theme/tokens';\n\n/** 角色由组件管理 */\nexport type RatingManaged = 'role';\n\n/** 未声明的属性落到外层 div 上;名称写 aria-label,或放在 Field 里 */\nexport interface RatingProps extends PartProps<'div', RatingManaged> {\n /** 分数:父级写 _value={score};没有评分时是 null */\n _value?: number | null;\n /** 一共几颗星,默认 5 */\n count?: number;\n /** 可以选半颗 */\n allowHalf?: boolean;\n /** 再点一次已选的分数时清空,默认 true */\n clearable?: boolean;\n /** 图标,默认星星 */\n icon?: IconData;\n /** 选中的颜色,默认 warning(金黄) */\n tone?: StatusTone;\n /** 字号档位:图标随之缩放 */\n size?: TextSize;\n /** 只读:只显示分数(一个 role=\"img\") */\n readonly?: boolean;\n /** 不可用(不写时取 Field 的) */\n disabled?: boolean;\n /** 表单提交时的 name */\n name?: string;\n /** 每颗星的部件属性 */\n propsStar?: PartProps<'span'>;\n}\n\n/** Rating 的样式:root、star、readonly、icon、empty、fill、clip、clipIcon、whole、startHalf、endHalf、disabled */\nexport const ratingStyles = css.create({\n root: { display: 'inline-flex', alignItems: 'center', gap: '0.15em', lineHeight: 1 },\n // 每颗星:空心图标打底,填色的那层按比例裁出;radio 盖满(半星时左右各一半)\n star: {\n position: 'relative',\n display: 'inline-grid',\n width: '1.35em',\n height: '1.35em',\n borderRadius: '_sm',\n cursor: 'pointer',\n transition: `scale ${t.durations.sm} ${t.easings.standard}`,\n scale: { default: null, ':hover': '1.12' },\n },\n readonly: { cursor: 'default', scale: null },\n icon: { gridArea: '1 / 1', width: '100%', height: '100%' },\n empty: { color: '_borderStrong' },\n // 填色的那层:currentColor 填满图标\n fill: { fill: 'currentColor' },\n clip: { gridArea: '1 / 1', overflow: 'hidden', pointerEvents: 'none' },\n // 裁出来的那层按整颗星的大小画,不随裁出的宽度缩小\n clipIcon: { display: 'block', width: '1.35em', height: '1.35em', maxWidth: 'none' },\n // 点击区域:整颗;半星时起始边一半、结束边一半\n whole: { position: 'absolute', inset: 0 },\n startHalf: { position: 'absolute', insetBlock: 0, insetInlineStart: 0, width: '50%' },\n endHalf: { position: 'absolute', insetBlock: 0, insetInlineEnd: 0, width: '50%' },\n disabled: { opacity: '_disabled', cursor: 'not-allowed' },\n});\n\n// 选中的颜色用各色调的实色(金黄的星、红色的心):实心与空心靠形状区分,不只靠颜色;Windows 高对比下用系统高亮色\n/** Rating 的颜色:neutral、accent、info、success、warning、danger */\nexport const ratingToneStyles = css.create({\n neutral: { color: { default: '_textMuted', '@media (forced-colors: active)': 'Highlight' } },\n accent: { color: { default: '_accent', '@media (forced-colors: active)': 'Highlight' } },\n info: { color: { default: '_info', '@media (forced-colors: active)': 'Highlight' } },\n success: { color: { default: '_success', '@media (forced-colors: active)': 'Highlight' } },\n warning: { color: { default: '_warning', '@media (forced-colors: active)': 'Highlight' } },\n danger: { color: { default: '_danger', '@media (forced-colors: active)': 'Highlight' } },\n});\n\n/** 填色那层的宽度 */\nexport const ratingClipStyles = css.create({\n width: (percent: string) => ({ width: percent }),\n});\n\n/** 评分:一排可以点的星 */\nexport const Rating = _component(\n ({\n _value: value = _bindable<number | null>(null),\n count = 5,\n allowHalf = false,\n clearable = true,\n icon = Star,\n tone = 'warning',\n size,\n readonly,\n disabled,\n name,\n id,\n propsStar,\n ...rest\n }: RatingProps) => {\n const lang = useLang();\n const generatedName = useId();\n const control = useFieldControl(() => ({ id, disabled, readonly }));\n // 指针悬停时预览的分数\n let hover = _state<number | null>(null);\n\n /** 第 index 颗星(从 1 开始)填了多少:0、50、100 */\n const filled = (shown: number | null, index: number) =>\n shown == null ? 0 : shown >= index ? 100 : shown >= index - 0.5 ? 50 : 0;\n\n function pick(next: number) {\n value = clearable && value === next ? null : next;\n hover = null;\n }\n\n const starIcon = (percent: number) => [\n <Icon icon={icon} sx={[ratingStyles.icon, ratingStyles.empty]} />,\n percent > 0 && (\n <span {...css.attrs(ratingStyles.clip, ratingClipStyles.width(`${percent}%`))}>\n <Icon\n icon={icon}\n sx={[ratingStyles.clipIcon, ratingStyles.fill, ratingToneStyles[tone]]}\n />\n </span>\n ),\n ];\n\n return () => {\n const state = control();\n const stars = Array.from({ length: count }, (_, index) => index + 1);\n\n if (state.readonly) {\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [ratingStyles.root, size && fontSizeStyles[size]],\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n },\n rest,\n { id: state.id, role: 'img', 'aria-label': lang.ratingSummary(value, count) },\n )}\n >\n {stars.map((index) => (\n <span\n key={index}\n aria-hidden=\"true\"\n {...mergeAttrs<'span'>(\n { sx: [ratingStyles.star, ratingStyles.readonly] },\n propsStar,\n )}\n >\n {starIcon(filled(value, index))}\n </span>\n ))}\n </div>\n );\n }\n\n const shown = hover ?? value;\n const radio = (score: number, sx: SxStyles) => (\n <label {...css.attrs(sx)} onPointerenter={() => (hover = score)}>\n <input\n type=\"radio\"\n name={name ?? generatedName}\n value={String(score)}\n checked={value === score}\n disabled={state.disabled}\n aria-label={lang.ratingStar(score)}\n onClick={() => pick(score)}\n {...css.attrs(visuallyHiddenStyles.hidden)}\n />\n </label>\n );\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n ratingStyles.root,\n size && fontSizeStyles[size],\n state.disabled && ratingStyles.disabled,\n ],\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n },\n rest,\n {\n id: state.id,\n role: 'radiogroup',\n 'aria-describedby': state.describedBy,\n 'aria-disabled': state.disabled || undefined,\n onPointerleave: () => (hover = null),\n },\n )}\n >\n {stars.map((index) => (\n <span\n key={index}\n {...mergeAttrs<'span'>(\n {\n sx: [ratingStyles.star, focusRingStyles.within],\n },\n propsStar,\n )}\n data-state={\n filled(value, index) === 100 ? 'full' : filled(value, index) ? 'half' : 'empty'\n }\n >\n {starIcon(filled(shown, index))}\n {allowHalf && radio(index - 0.5, ratingStyles.startHalf)}\n {radio(index, allowHalf ? ratingStyles.endHalf : ratingStyles.whole)}\n </span>\n ))}\n </div>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,IAAa,eAAe,IAAI,OAAO;CACrC,MAAM;EAAE,SAAS;EAAe,YAAY;EAAU,KAAK;EAAU,YAAY;CAAE;CAEnF,MAAM;EACJ,UAAU;EACV,SAAS;EACT,OAAO;EACP,QAAQ;EACR,cAAc;EACd,QAAQ;EACR,YAAY,SAAS,EAAE,UAAU,GAAE,GAAI,EAAE,QAAQ;EACjD,OAAO;GAAE,SAAS;GAAM,UAAU;EAAO;CAC3C;CACA,UAAU;EAAE,QAAQ;EAAW,OAAO;CAAK;CAC3C,MAAM;EAAE,UAAU;EAAS,OAAO;EAAQ,QAAQ;CAAO;CACzD,OAAO,EAAE,OAAO,gBAAgB;CAEhC,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM;EAAE,UAAU;EAAS,UAAU;EAAU,eAAe;CAAO;CAErE,UAAU;EAAE,SAAS;EAAS,OAAO;EAAU,QAAQ;EAAU,UAAU;CAAO;CAElF,OAAO;EAAE,UAAU;EAAY,OAAO;CAAE;CACxC,WAAW;EAAE,UAAU;EAAY,YAAY;EAAG,kBAAkB;EAAG,OAAO;CAAM;CACpF,SAAS;EAAE,UAAU;EAAY,YAAY;EAAG,gBAAgB;EAAG,OAAO;CAAM;CAChF,UAAU;EAAE,SAAS;EAAa,QAAQ;CAAc;AAC1D,CAAC;;AAID,IAAa,mBAAmB,IAAI,OAAO;CACzC,SAAS,EAAE,OAAO;EAAE,SAAS;EAAc,kCAAkC;CAAY,EAAE;CAC3F,QAAQ,EAAE,OAAO;EAAE,SAAS;EAAW,kCAAkC;CAAY,EAAE;CACvF,MAAM,EAAE,OAAO;EAAE,SAAS;EAAS,kCAAkC;CAAY,EAAE;CACnF,SAAS,EAAE,OAAO;EAAE,SAAS;EAAY,kCAAkC;CAAY,EAAE;CACzF,SAAS,EAAE,OAAO;EAAE,SAAS;EAAY,kCAAkC;CAAY,EAAE;CACzF,QAAQ,EAAE,OAAO;EAAE,SAAS;EAAW,kCAAkC;CAAY,EAAE;AACzF,CAAC;;AAGD,IAAa,mBAAmB,IAAI,OAAO,EACzC,QAAQ,aAAqB,EAAE,OAAO,QAAQ,GAChD,CAAC;;AAGD,IAAa,SAAS,0BACpB,QAAA,SAcmB;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,QAAAA,SAAA,QAAA,gBAbwB,MAAI,KAAA,IAAA;CAAA,MAAA,QAAAC,aAAA,QAAA,SACrC,CAAC;CAAA,MAAA,YAAAA,aAAA,QAAA,aACG,KAAK;CAAA,MAAA,YAAAA,aAAA,QAAA,aACL,IAAI;CAAA,MAAA,OAAAA,aAAA,QAAA,cACT,IAAI;CAAA,MAAA,OAAAA,aAAA,QAAA,QACJ,SAAS;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,KAAAA,aAAA,QAAA,IAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAOb,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,OAAO,QAAQ;CACrB,MAAM,gBAAgB,MAAM;CAC5B,MAAM,UAAU,uBAAuB;EAAE,IAAE,GAAA;EAAE,UAAQ,SAAA;EAAE,UAAQ,SAAA;CAAC,EAAE;CAElE,IAAI,QAAKC,IAAyB,IAAI;;CAGtC,MAAM,UAAU,OAAsB,UACpC,SAAS,OAAO,IAAI,SAAS,QAAQ,MAAM,SAAS,QAAQ,KAAM,KAAK;CAEzE,SAAS,KAAK,MAAc;EAC1B,MAAA,QAAQ,UAAA,SAAa,MAAA,UAAU,OAAO,OAAO;EAC7C,MAAA,QAAQ;CACV;CAEA,MAAM,YAAY,YAAoB,CAAAC,YAAA,MAAA;EAAA,QAAA,KAAA;EAAA,MAAA,OAAA,OAAA,OAAA,KACd,CAAC,aAAa,MAAM,aAAa,KAAK;CAAC,GAAA,IAAA,GAC7D,UAAU,KAACA,YAAA,QACC,IAAI,MAAM,aAAa,MAAM,iBAAiB,MAAM,GAAG,QAAO,EAAG,CAAC,GAAC,CAAAA,YAAA,MAAA;EAAA,QAAA,KAAA;EAAA,MAGrE;GAAC,aAAa;GAAU,aAAa;GAAM,iBAAgB,KAAA;EAAM;CAAC,GAAA,IAAA,CAAA,CAAA,CAG3E;CAGH,aAAa;EACX,MAAM,QAAQ,QAAQ;EACtB,MAAM,QAAQ,MAAM,KAAK,EAAE,QAAM,MAAA,MAAQ,IAAI,GAAG,UAAU,QAAQ,CAAC;EAEnE,IAAI,MAAM,UACR,OAAAA,YAAA,OAEQ,WACF;GACE,IAAI,CAAC,aAAa,MAAM,KAAA,SAAQ,eAAc,KAAA,MAAM;GACpD,mBAAmB,kBAAkB,MAAM,MAAM,UAAU;EAC7D,GACA,MACA;GAAE,IAAI,MAAM;GAAI,MAAM;GAAO,cAAc,KAAK,cAAa,MAAA,OAAA,MAAA,KAAa;EAAE,CAC9E,GAAC,CAEA,MAAM,KAAK,UAAKA,YAAA,QAAAC,cAAA;GAAA,OAER;GAAK,eAAA;EAAA,GAEN,WACF,EAAE,IAAI,CAAC,aAAa,MAAM,aAAa,QAAQ,EAAE,GAAC,UAAA,KAEpD,CAAC,GAAA,CAEA,SAAS,OAAM,MAAA,OAAQ,KAAK,CAAC,CAAC,CAAA,CAElC,CAAC,CAAA;EAKR,MAAM,QAAQ,MAAA,SAAA,MAAA;EACd,MAAM,SAAS,OAAe,OAAYD,YAAA,SAAAC,cAC7B,IAAI,MAAM,EAAE,GAAC,EAAA,wBAAyB,MAAA,QAAQ,MAAM,CAAA,GAAA,CAAAD,YAAA,SAAAC,cAAA;GAAA,QAAA;GAAA,QAGrD,KAAA,SAAQ;GAAa,SACpB,OAAO,KAAK;GAAC,WACX,MAAA,UAAU;GAAK,YACd,MAAM;GAAQ,cACZ,KAAK,WAAW,KAAK;GAAC,iBACnB,KAAK,KAAK;EAAC,GACtB,IAAI,MAAM,qBAAqB,MAAM,CAAC,GAAA,IAAA,CAAA,CAAA;EAIhD,OAAAD,YAAA,OAEQ,WACF;GACE,IAAI;IACF,aAAa;IACb,KAAA,SAAQ,eAAc,KAAA;IACtB,MAAM,YAAY,aAAa;GAAQ;GAEzC,mBAAmB,kBAAkB,MAAM,MAAM,UAAU;EAC7D,GACA,MACA;GACE,IAAI,MAAM;GACV,MAAM;GACN,oBAAoB,MAAM;GAC1B,iBAAiB,MAAM,YAAY,KAAA;GACnC,sBAAuB,MAAA,QAAQ;EACjC,CACF,GAAC,CAEA,MAAM,KAAK,UAAKA,YAAA,QAAAC,cAAA,EAAA,OAER,MAAK,GACN,WACF,EACE,IAAI,CAAC,aAAa,MAAM,gBAAgB,MAAM,EAChD,GAAC,UAAA,KAEH,GAAC,EAAA,cAEC,OAAM,MAAA,OAAQ,KAAK,MAAM,MAAM,SAAS,OAAM,MAAA,OAAQ,KAAK,IAAI,SAAS,QAAO,CAAA,GAAA;GAGhF,SAAS,OAAO,OAAO,KAAK,CAAC;GAC7B,UAAA,SAAa,MAAM,QAAQ,IAAK,aAAa,SAAS;GACtD,MAAM,OAAO,UAAA,QAAY,aAAa,UAAU,aAAa,KAAK;EAAC,CAAA,CAEvE,CAAC,CAAA;CAGR;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
|
1
|
+
{"version":3,"file":"Rating.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_ref","_createVNode","_mergeProps"],"sources":["../../src/input/Rating.tsx"],"sourcesContent":["/**\n * 评分:几颗星(或别的图标)里选一个分数,供应商评价、满意度、优先级。可以半星,可以只读显示。\n *\n * <Field label=\"交付质量\"><Rating _value={score} /></Field>\n * <Rating value={4.5} readonly /> 只读:一个 role=\"img\",读“4.5 星,满分 5 星”\n * <Rating _value={score} allowHalf count={10} icon={Heart} tone=\"danger\" />\n *\n * 可编辑时是单选组(role=\"radiogroup\"):每颗星是一个原生 radio(视觉上隐藏),方向键、表单提交、读屏都是原生的;\n * 名称是“3 星”这样的文字(lang.ratingStar)。指针悬停时预览将要选的分数;再点一次已选的分数清空(clearable,默认开)。\n * 半星:每颗星左右各一半,各是一个 radio。部件:Root(div)、Star(span,每颗星)、Icon。\n */\nimport { Star } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId } from 'vue';\nimport { Icon, type IconData } from '../base/Icon';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFieldControl } from '../form/Field';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport { t } from '../config/theme/tokens';\n\n/** 角色由组件管理 */\nexport type RatingManaged = 'role';\n\n/** 未声明的属性落到外层 div 上;名称写 aria-label,或放在 Field 里 */\nexport interface RatingProps extends PartProps<'div', RatingManaged> {\n /** 分数:父级写 _value={score};没有评分时是 null */\n _value?: number | null;\n /** 一共几颗星,默认 5 */\n count?: number;\n /** 可以选半颗 */\n allowHalf?: boolean;\n /** 再点一次已选的分数时清空,默认 true */\n clearable?: boolean;\n /** 图标,默认星星 */\n icon?: IconData;\n /** 选中的颜色,默认 warning(金黄) */\n tone?: StatusTone;\n /** 字号档位:图标随之缩放 */\n size?: TextSize;\n /** 只读:只显示分数(一个 role=\"img\") */\n readonly?: boolean;\n /** 不可用(不写时取 Field 的) */\n disabled?: boolean;\n /** 表单提交时的 name */\n name?: string;\n /** 每颗星的部件属性 */\n propsStar?: PartProps<'span'>;\n}\n\n/** Rating 的样式:root、star、readonly、icon、empty、fill、clip、clipIcon、whole、startHalf、endHalf、disabled */\nexport const ratingStyles = css.create({\n root: { display: 'inline-flex', alignItems: 'center', gap: '0.15em', lineHeight: 1 },\n // 每颗星:空心图标打底,填色的那层按比例裁出;radio 盖满(半星时左右各一半)\n star: {\n position: 'relative',\n display: 'inline-grid',\n width: '1.35em',\n height: '1.35em',\n borderRadius: '_sm',\n cursor: 'pointer',\n transition: `scale ${t.durations.sm} ${t.easings.standard}`,\n scale: { default: null, ':hover': '1.12' },\n },\n readonly: { cursor: 'default', scale: null },\n icon: { gridArea: '1 / 1', width: '100%', height: '100%' },\n empty: { color: '_borderStrong' },\n // 填色的那层:currentColor 填满图标\n fill: { fill: 'currentColor' },\n clip: { gridArea: '1 / 1', overflow: 'hidden', pointerEvents: 'none' },\n // 裁出来的那层按整颗星的大小画,不随裁出的宽度缩小\n clipIcon: { display: 'block', width: '1.35em', height: '1.35em', maxWidth: 'none' },\n // 点击区域:整颗;半星时起始边一半、结束边一半\n whole: { position: 'absolute', inset: 0 },\n startHalf: { position: 'absolute', insetBlock: 0, insetInlineStart: 0, width: '50%' },\n endHalf: { position: 'absolute', insetBlock: 0, insetInlineEnd: 0, width: '50%' },\n disabled: { opacity: '_disabled', cursor: 'not-allowed' },\n});\n\n// 选中的颜色用各色调的实色(金黄的星、红色的心):实心与空心靠形状区分,不只靠颜色;Windows 高对比下用系统高亮色\n/** Rating 的颜色:neutral、accent、info、success、warning、danger */\nexport const ratingToneStyles = css.create({\n neutral: { color: { default: '_textMuted', '@media (forced-colors: active)': 'Highlight' } },\n accent: { color: { default: '_accent', '@media (forced-colors: active)': 'Highlight' } },\n info: { color: { default: '_info', '@media (forced-colors: active)': 'Highlight' } },\n success: { color: { default: '_success', '@media (forced-colors: active)': 'Highlight' } },\n warning: { color: { default: '_warning', '@media (forced-colors: active)': 'Highlight' } },\n danger: { color: { default: '_danger', '@media (forced-colors: active)': 'Highlight' } },\n});\n\n/** 填色那层的宽度 */\nexport const ratingClipStyles = css.create({\n width: (percent: string) => ({ width: percent }),\n});\n\n/** 评分:一排可以点的星 */\nexport const Rating = _component(\n ({\n _value: value = _bindable<number | null>(null),\n count = 5,\n allowHalf = false,\n clearable = true,\n icon = Star,\n tone = 'warning',\n size,\n readonly,\n disabled,\n name,\n id,\n propsStar,\n ...rest\n }: RatingProps) => {\n const lang = useLang();\n const generatedName = useId();\n const control = useFieldControl(() => ({ id, disabled, readonly }));\n // 指针悬停时预览的分数\n let hover = _state<number | null>(null);\n\n /** 第 index 颗星(从 1 开始)填了多少:0、50、100 */\n const filled = (shown: number | null, index: number) =>\n shown == null ? 0 : shown >= index ? 100 : shown >= index - 0.5 ? 50 : 0;\n\n function pick(next: number) {\n value = clearable && value === next ? null : next;\n hover = null;\n }\n\n const starIcon = (percent: number) => [\n <Icon icon={icon} sx={[ratingStyles.icon, ratingStyles.empty]} />,\n percent > 0 && (\n <span {...css.attrs(ratingStyles.clip, ratingClipStyles.width(`${percent}%`))}>\n <Icon\n icon={icon}\n sx={[ratingStyles.clipIcon, ratingStyles.fill, ratingToneStyles[tone]]}\n />\n </span>\n ),\n ];\n\n return () => {\n const state = control();\n const stars = Array.from({ length: count }, (_, index) => index + 1);\n\n if (state.readonly) {\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [ratingStyles.root, size && fontSizeStyles[size]],\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n },\n rest,\n { id: state.id, role: 'img', 'aria-label': lang.ratingSummary(value, count) },\n )}\n >\n {stars.map((index) => (\n <span\n key={index}\n aria-hidden=\"true\"\n {...mergeAttrs<'span'>(\n { sx: [ratingStyles.star, ratingStyles.readonly] },\n propsStar,\n )}\n >\n {starIcon(filled(value, index))}\n </span>\n ))}\n </div>\n );\n }\n\n const shown = hover ?? value;\n const radio = (score: number, sx: SxStyles) => (\n <label {...css.attrs(sx)} onPointerenter={() => (hover = score)}>\n <input\n type=\"radio\"\n name={name ?? generatedName}\n value={String(score)}\n checked={value === score}\n disabled={state.disabled}\n aria-label={lang.ratingStar(score)}\n onClick={() => pick(score)}\n {...css.attrs(visuallyHiddenStyles.hidden)}\n />\n </label>\n );\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n ratingStyles.root,\n size && fontSizeStyles[size],\n state.disabled && ratingStyles.disabled,\n ],\n 'aria-labelledby': defaultLabelledBy(rest, state.labelledBy),\n },\n rest,\n {\n id: state.id,\n role: 'radiogroup',\n 'aria-describedby': state.describedBy,\n 'aria-disabled': state.disabled || undefined,\n onPointerleave: () => (hover = null),\n },\n )}\n >\n {stars.map((index) => (\n <span\n key={index}\n {...mergeAttrs<'span'>(\n {\n sx: [ratingStyles.star, focusRingStyles.within],\n },\n propsStar,\n )}\n data-state={\n filled(value, index) === 100 ? 'full' : filled(value, index) ? 'half' : 'empty'\n }\n >\n {starIcon(filled(shown, index))}\n {allowHalf && radio(index - 0.5, ratingStyles.startHalf)}\n {radio(index, allowHalf ? ratingStyles.endHalf : ratingStyles.whole)}\n </span>\n ))}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
package/dist/input/Select.d.ts
CHANGED
|
@@ -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 { PresetIconButtonProps } from '../base/CloseButton';
|
|
4
4
|
import { type IconProps } from '../base/Icon';
|
package/dist/input/Select.js
CHANGED
|
@@ -18,7 +18,7 @@ import { SelectedTags } from "./SelectedTags.js";
|
|
|
18
18
|
import { TextField } from "./TextField.js";
|
|
19
19
|
import { Fragment, createVNode, shallowRef, useId, watch } from "vue";
|
|
20
20
|
import { _component, bindable, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
21
|
-
import
|
|
21
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
22
22
|
import { ChevronDown, Plus, Search } from "@lucide/icons";
|
|
23
23
|
//#region src/input/Select.tsx
|
|
24
24
|
/**
|
package/dist/input/Select.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/input/Select.tsx"],"sourcesContent":["/**\n * 下拉选择(WAI-ARIA 的 select-only combobox):点触发框弹出选项列表,单选或多选。\n *\n * <Field label=\"城市\"><Select items={['北京', '上海', '广州']} _value={city} placeholder=\"选择城市\" /></Field>\n * <Select items={tags} selectionMode=\"multiple\" _value={picked} clearable aria-label=\"标签\" />\n * <Select items={users} toOption={(user) => ({ value: user.id, label: user.name })} _value={id} />\n * <Select items={suppliers} searchable _value={supplier} /> 选项多时:弹出层顶部带搜索框\n *\n * <Select items={tags} selectionMode=\"multiple\" maxTagCount=\"responsive\" creatable onCreate={(text) => tags.push(text)} … />\n *\n * 组合已有的部件:外壳是输入框外壳(controlParts),弹出层用 useAnchoredPopover(与外壳同宽、最高到视口剩余空间),\n * 列表是 ListboxView(状态与键盘见 list-state.ts)。焦点一直在触发按钮上,高亮项经 aria-activedescendant 告诉读屏。\n *\n * 多选时已选的项是触发按钮前面的一排 Tag(不能放进 button 里:按钮里不能有按钮),各带移除按钮。\n * 这排标签只给指针用(aria-hidden、移除按钮不进 Tab 顺序):读屏从触发按钮里念出全部已选内容,\n * 键盘在列表里取消勾选,或在触发按钮(及空的搜索框)里按 Backspace 移除最后一项(同 TagsInput)。\n * maxTagCount 是数字时只显示前几个,'responsive' 时排成一行按宽度放,其余收进“+N”(SelectedTags,TreeSelect 共用)。\n *\n * 键盘:关闭时 ↓ / Enter / 空格打开(↑ 打开并高亮最后一项),单选时直接按字母选中以它开头的项(同原生 select);\n * 打开时 ↑↓、Home / End、Page Up / Down 移动,Enter / 空格选中(单选随后关闭),Esc、Tab 关闭。\n * 写了 name 时用隐藏的 input 随表单提交(多选时每个值一个)。\n *\n * searchable 时弹出层顶部有搜索框:打开后焦点在搜索框里,输入就过滤选项(按显示文字,忽略大小写与重音,或用 filter),\n * ↑↓ 移动、Enter 选中、Esc 关闭并把焦点还给触发按钮。已选的项被过滤掉、或 items 换了(远程搜索)时,\n * 触发框里仍显示它的文字(useSelectedOptions)。\n *\n * 远程选项:给 load 时打开就按搜索词请求,输入停下 300 ms 再请求,只采用最后一次(remote-items.ts);\n * 自己管请求时写 _search={keyword} 拿到搜索词、filter={false} 关掉本地过滤,items 与 loading 自己给。\n *\n * <Select searchable load={(q, signal) => http.get<User[]>('/users', { query: { q }, signal })} toOption={…} _value={owner} />\n *\n * creatable 时自带搜索框,输入的文字没有对应的选项时列表末尾多一项“新建“…””:选中后值就是这段文字,onCreate 报告它。\n *\n * 部件:Root(外壳)、Tags(多选时的那排标签)、Tag、Trigger(button,主元素)、Value、Clear、Chevron、Popover、\n * Search(TextField)、Listbox。\n */\nimport { ChevronDown, Plus, Search } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, watch, type VNodeChild } from 'vue';\nimport type { PresetIconButtonProps } from '../base/CloseButton';\nimport { buttonBaseStyles } from '../base/button-core';\nimport { Icon, type IconProps } from '../base/Icon';\nimport type { TagProps } from '../base/Tag';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { useAnchoredPopover, type FloatingPlacement } from '../utils/dom/floating';\nimport { openSetter, type OpenChangeProps } from '../utils/dom/open-change';\nimport { ListPopover } from './ListPopover';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { selectedValues, type SelectionProps } from '../utils/data/selection';\nimport {\n controlClear,\n controlParts,\n clickOnShell,\n focusOnShell,\n controlIcon,\n useControlAppearance,\n type ControlIconOptions,\n type ControlOptions,\n} from './control';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { disclosureStyles } from '../utils/style/transitions';\nimport { activeOptionId, type ListboxViewProps, type OptionRenderState } from './Listbox';\nimport {\n handleListKeydown,\n useListState,\n useResultAnnouncement,\n useSelectedOptions,\n type ListboxOption,\n type OptionMapping,\n toListboxOption,\n} from './list-state';\nimport { useRemoteItems, type OptionsLoader } from './remote-items';\nimport { SelectedTags, type SelectedTagsProps } from './SelectedTags';\nimport { TextField, type TextFieldProps } from './TextField';\n\n/** 角色、展开状态与可用性由组件管理 */\nexport type SelectManaged =\n | 'type'\n | 'role'\n | 'value'\n | 'disabled'\n | 'aria-haspopup'\n | 'aria-expanded'\n | 'aria-controls'\n | 'aria-activedescendant'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-describedby';\n\n/** 下拉选择共有的属性;未声明的属性落到触发按钮(主元素)上,外壳用 propsRoot */\nexport interface SelectBaseProps<T>\n extends PartProps<'button', SelectManaged>, ControlOptions, ControlIconOptions, OpenChangeProps {\n /** 数据:ListboxOption、字符串,或任意数据加 toOption;有 load 时是第一次加载之前的选项(编辑页放上已选的那一项) */\n items?: readonly T[];\n /** 没有选择时显示的文字,默认取语言包(请选择) */\n placeholder?: string;\n /** 是否打开:父级可以写 _open={x} */\n _open?: boolean;\n /** 弹出位置,默认 bottom-start */\n placement?: FloatingPlacement;\n /** 有选择时显示清空按钮 */\n clearable?: boolean;\n /** 弹出层顶部带搜索框,输入过滤选项:选项多(供应商、人员、件号)时用 */\n searchable?: boolean;\n /** 搜索时怎样算匹配;默认显示文字包含输入(忽略大小写与重音)。false 时不在本地过滤(服务端按 search 过滤) */\n filter?: false | ((item: T, query: string) => boolean);\n /** 搜索框里的文字:打开时清空;父级写 _search={x} 拿到它(自己发请求时) */\n _search?: string;\n /** 远程选项:打开时与搜索词停下 300 ms 后调用,结果代替 items;只采用最后一次,被顶掉的请求 signal 中止 */\n load?: OptionsLoader<T>;\n /**\n * 可以新建选项(自带搜索框):输入的文字没有对应的选项时,列表末尾多一项“新建“…””,选中后值就是这段文字。\n * 在 onCreate 里把它加进 items(或存到服务端);不加时触发框里照样显示这段文字\n */\n creatable?: boolean;\n /** 新建了一项(creatable 时):参数是输入的文字,也就是选中的值 */\n onCreate?: (text: string) => void;\n /** 多选时触发框里最多显示几个标签,其余收进“+N”;'responsive' 时排成一行、按宽度放,放不下的收起 */\n maxTagCount?: number | 'responsive';\n /** 表单提交时的 name(用隐藏的 input) */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、能看到已选的内容,不能打开、不能清空 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 自定义选项内容:`{(option, { selected, active }) => …}` */\n children?: (item: T, state: OptionRenderState) => VNodeChild;\n /** 自定义触发框里显示的内容(已选的选项);默认单选显示文字、多选显示标签 */\n renderValue?: (selected: readonly T[]) => VNodeChild;\n /** 正在取选项(异步加载):没有选项时列表里是骨架行,已有选项时顶部显示进度条 */\n loading?: boolean;\n /** 没有选项时列表里显示的内容 */\n empty?: VNodeChild;\n /** 外壳的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 已选内容那一层的部件属性 */\n propsValue?: PartProps<'span'>;\n /** 多选时每个标签的部件属性 */\n propsTag?: Partial<TagProps>;\n /** 多选时那排标签的部件属性 */\n propsTags?: Partial<SelectedTagsProps>;\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 下拉箭头的部件属性 */\n propsChevron?: Partial<IconProps>;\n /** 弹出层的部件属性 */\n propsPopover?: PartProps<'div', 'id' | 'popover'>;\n /** 列表的部件属性 */\n propsListbox?: Partial<ListboxViewProps<T>>;\n /** 搜索框的部件属性(searchable 时) */\n propsSearch?: Partial<TextFieldProps>;\n}\n\n/** 单选或多选;items 不是 ListboxOption 或字符串时要给 toOption */\nexport type SelectProps<T = ListboxOption> = SelectBaseProps<T> & SelectionProps & OptionMapping<T>;\n\n/** Select 的样式:root、trigger、value、placeholder、chevronOpen 等 */\nexport const selectStyles = css.create({\n // 在 ControlGroup 里也按内容宽(输入框才分剩余宽度)\n root: { cursor: 'pointer', flexGrow: 0 },\n // 去掉按钮默认外观用 buttonBaseStyles;像输入框一样没有自己的焦点环与波纹(焦点环画在外壳上)\n trigger: {\n display: 'flex',\n alignItems: 'center',\n flexGrow: 1,\n minWidth: 0,\n alignSelf: 'stretch',\n textAlign: 'start',\n cursor: 'inherit',\n outlineStyle: 'none',\n },\n value: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '_xs',\n minWidth: 0,\n paddingBlock: '_xs',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n // 是真正的文字(不是原生 placeholder),要满足 4.5:1:用 textMuted 而不是 textPlaceholder\n placeholder: { color: '_textMuted' },\n // 多选时标签排在触发按钮前面(SelectedTags)占剩余宽度,触发按钮里只剩读屏用的文字\n triggerBehindTags: { flexGrow: 0 },\n chevronOpen: { rotate: '180deg' },\n // 弹出层顶部的搜索框占满宽度\n search: { width: '_full' },\n});\n\n/** creatable 时列表末尾那一项“新建“…””:不是 items 里的数据 */\nclass Creation {\n readonly text: string;\n constructor(text: string) {\n this.text = text;\n }\n}\n\n/** 下拉选择:触发框 + 弹出的选项列表 */\nexport const Select = _component(\n <T,>({\n items = [],\n toOption,\n selectionMode = 'single',\n _value: value = _bindable<string | string[] | null>(null),\n _open: open = _bindable(false),\n onOpenChange,\n placeholder,\n placement = 'bottom-start',\n clearable = false,\n searchable = false,\n filter,\n _search: search = _bindable(''),\n load,\n creatable = false,\n onCreate,\n maxTagCount,\n name,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n id,\n icon,\n children,\n renderValue,\n empty,\n loading = false,\n propsRoot,\n propsIcon,\n propsValue,\n propsTag,\n propsTags,\n propsClear,\n propsChevron,\n propsPopover,\n propsListbox,\n propsSearch,\n ...rest\n }: SelectProps<T>) => {\n const lang = useLang();\n const textMatcher = useTextMatcher();\n const listId = useId();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const multiple = () => selectionMode === 'multiple';\n const optionOf = (item: T) => toListboxOption(item, toOption);\n const remote = useRemoteItems({\n load: () => load,\n query: () => search,\n open: () => open,\n items: () => items,\n });\n // 本地过滤:有 load 或 filter={false} 时交给服务端\n const localFilter = () => !load && filter !== false;\n const matches = (item: T, text: string) =>\n filter ? filter(item, text) : textMatcher()(optionOf(item).label, text);\n // creatable 自带搜索框\n const withSearch = () => searchable || creatable;\n // creatable:输入的文字没有同名(或同值)的选项时,列表末尾多一项“新建”\n const creation = () => {\n const text = search.trim();\n if (!creatable || !text) return undefined;\n const exists = remote.items().some((item) => {\n const option = optionOf(item);\n return option.value === text || option.label.toLowerCase() === text.toLowerCase();\n });\n return exists ? undefined : new Creation(text);\n };\n const list = useListState<T | Creation>({\n items: () => {\n const all = remote.items();\n const shown =\n withSearch() && search && localFilter()\n ? all.filter((item) => matches(item, search))\n : all;\n const created = creation();\n return created ? [...shown, created] : shown;\n },\n toOption: (item) =>\n item instanceof Creation\n ? { value: item.text, label: lang.selectCreate(item.text), icon: Plus }\n : optionOf(item),\n selected: () => selectedValues(value),\n mode: () => selectionMode,\n onChange: (next) => {\n const created = creation();\n if (created && next.includes(created.text)) {\n onCreate?.(created.text);\n search = '';\n }\n value = multiple() ? [...next] : (next[0] ?? null);\n },\n // 单选时再点已选的一项不取消(同原生 select);要清空用清除按钮\n required: () => !multiple(),\n });\n // 已选项的文字取自全部 items(过滤掉的、远程搜索换掉的也在)\n const selectedOptions = useSelectedOptions({ items: remote.items, toOption: optionOf });\n let shell = _state.raw<HTMLElement | null>(null);\n let trigger = _state.raw<HTMLElement | null>(null);\n let panel = _state.raw<HTMLElement | null>(null);\n const setOpen = openSetter(\n () => open,\n (next) => (open = next),\n () => onOpenChange,\n );\n\n /** 多选时移除一项(标签的移除按钮、Backspace) */\n function remove(target: string) {\n value = selectedValues(value).filter((item) => item !== target);\n }\n\n function removeLast() {\n const last = selectedValues(value).at(-1);\n if (last !== undefined) remove(last);\n }\n\n function show(highlight: 'default' | 'last' = 'default', event?: Event) {\n search = '';\n list.activateDefault();\n if (highlight === 'last' && selectedValues(value).length === 0) list.move('last');\n setOpen(true, 'trigger', event);\n }\n\n useResultAnnouncement(() => ({ query: search, count: list.options.length }));\n\n // 输入搜索词:高亮第一个匹配的。打开时清空搜索词不算:那时高亮的是已选项\n watch(\n () => search,\n (text) => text && list.move('first'),\n );\n\n // 选中一项:单选时关闭\n function picked(event?: Event) {\n if (!multiple()) setOpen(false, 'select', event);\n }\n\n /** Ctrl / Cmd / Alt 组合键是浏览器的(刷新、复制、查找),不做按字母跳转 */\n const hasModifier = (event: KeyboardEvent) => event.altKey || event.ctrlKey || event.metaKey;\n\n function onKeydown(event: KeyboardEvent) {\n if (control().disabled || control().readonly) return;\n if (event.key === 'Backspace' && multiple()) {\n event.preventDefault();\n removeLast();\n return;\n }\n if (!open) {\n if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n show('default', event);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n show('last', event);\n } else if (!multiple() && !hasModifier(event) && list.typeahead(event.key)) {\n // 同原生 select:关闭时按字母直接选中\n event.preventDefault();\n if (list.active !== undefined && !list.isSelected(list.active)) list.select(list.active);\n }\n return;\n }\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (handleListKeydown(list, event, { space: true, typeahead: true }, () => picked(event))) {\n event.preventDefault();\n }\n }\n\n // 搜索框里:↑↓ 移动、Enter 选中(Home / End、空格留给输入),Tab 关闭后照常移到下一个;\n // 多选时空的搜索框里按 Backspace 移除最后一项\n function onSearchKeydown(event: KeyboardEvent) {\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (event.key === 'Backspace' && !search && multiple()) {\n event.preventDefault();\n removeLast();\n return;\n }\n if (handleListKeydown(list, event, { homeEnd: false }, () => picked(event)))\n event.preventDefault();\n }\n\n function clear() {\n value = multiple() ? [] : null;\n trigger?.focus();\n }\n\n // 弹层贴着外壳、与它同宽;焦点一直在触发按钮上,关闭时不用归还(searchable 时见 onPanelToggle)\n const { onToggle } = useAnchoredPopover(\n () => ({\n open,\n anchor: shell,\n panel,\n floating: { placement, matchWidth: true, fitHeight: true },\n restoreFocus: false,\n }),\n { close: (reason, event) => setOpen(false, reason, event) },\n );\n\n // searchable:打开后焦点进搜索框;关闭时焦点还在弹层里(Esc、选中、点外面)就还给触发按钮\n function onPanelToggle(event: ToggleEvent) {\n onToggle(event);\n if (!withSearch()) return;\n if (event.newState === 'open') {\n panel?.querySelector<HTMLInputElement>('input[type=\"search\"]')?.focus();\n return;\n }\n const active = document.activeElement;\n if (!active || active === document.body || panel?.contains(active)) trigger?.focus();\n }\n\n return () => {\n const state = control();\n const values = selectedValues(value);\n const selected = selectedOptions(values);\n const off = state.disabled;\n // 只读:能聚焦,不能打开、不能改\n const locked = off || state.readonly;\n // 多选的默认显示:触发按钮前面一排标签,按钮里只留给读屏的文字\n const tagged = multiple() && !renderValue && selected.length > 0;\n const shown = tagged ? (\n <span {...css.attrs(visuallyHiddenStyles.hidden)}>\n {lang.selectSummary(selected.map((option) => option.label))}\n </span>\n ) : (\n (renderValue?.(\n selected.flatMap((option) => (option.item === undefined ? [] : [option.item])),\n ) ??\n (selected.length === 0 ? (\n <span {...css.attrs(selectStyles.placeholder)}>\n {placeholder ?? lang.selectPlaceholder}\n </span>\n ) : (\n selected[0]!.label\n )))\n );\n const tags = tagged && (\n <SelectedTags\n {...mergePartProps<SelectedTagsProps>(\n {\n tags: selected,\n maxTagCount,\n onRemove: locked ? undefined : remove,\n propsTag,\n },\n propsTags,\n )}\n />\n );\n const s = controlParts(appearance(), state);\n return (\n <>\n <div\n {...mergeAttrs<'div'>({ ...s.root, sx: [s.root.sx, selectStyles.root] }, propsRoot, {\n ref: _toRef(shell),\n // 点在外壳空白处(含多选的标签):焦点交给触发按钮,并与点触发按钮一样切换打开(只读时只聚焦)\n onPointerdown: off ? undefined : focusOnShell(() => trigger),\n onClick: locked\n ? undefined\n : clickOnShell(\n () => trigger,\n (event) => (open ? setOpen(false, 'trigger', event) : show('default', event)),\n ),\n })}\n data-state={open ? 'open' : 'closed'}\n data-invalid={state.invalid || undefined}\n data-disabled={off || undefined}\n >\n {controlIcon(s, icon, propsIcon)}\n {tags}\n <button\n {...mergeAttrs<'button'>(\n {\n sx: [\n buttonBaseStyles.root,\n selectStyles.trigger,\n tagged && selectStyles.triggerBehindTags,\n ],\n },\n rest,\n {\n ref: _toRef(trigger),\n id: state.id,\n type: 'button',\n role: 'combobox',\n disabled: off,\n 'aria-haspopup': 'listbox',\n 'aria-expanded': open,\n 'aria-controls': listId,\n 'aria-activedescendant': open ? activeOptionId(list, listId) : undefined,\n 'aria-invalid': state.invalid || undefined,\n 'aria-required': state.required || undefined,\n 'aria-readonly': state.readonly || undefined,\n 'aria-describedby': state.describedBy,\n onClick: (event: MouseEvent) => {\n // Safari 点击按钮不会聚焦它:焦点要在触发按钮上,键盘与 aria-activedescendant 才有效\n trigger?.focus();\n if (locked) return;\n if (open) setOpen(false, 'trigger', event);\n else show('default', event);\n },\n onKeydown,\n },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: selectStyles.value }, propsValue)}>{shown}</span>\n </button>\n {clearable && values.length > 0 && !locked && controlClear(s, propsClear, clear)}\n <Icon\n {...mergePartProps<IconProps>(\n {\n ...s.icon,\n icon: ChevronDown,\n sx: [s.icon.sx, disclosureStyles.icon, open && selectStyles.chevronOpen],\n },\n propsChevron,\n )}\n />\n <FormValue name={name} value={values} disabled={state.disabled} />\n </div>\n <ListPopover\n panelRef={_toRef(panel)}\n onToggle={onPanelToggle}\n size={appearance().size}\n labelledBy={state.labelledBy}\n label={rest['aria-label']}\n loading={loading || remote.loading()}\n onPick={() => picked()}\n header={\n withSearch() && (\n <TextField\n {...mergePartProps<TextFieldProps>(\n {\n icon: Search,\n variant: 'soft',\n placeholder: lang.selectSearch,\n 'aria-label': lang.selectSearch,\n propsRoot: { sx: selectStyles.search },\n },\n propsSearch,\n )}\n type=\"search\"\n _value={search}\n aria-controls={listId}\n aria-activedescendant={open ? activeOptionId(list, listId) : undefined}\n onKeydown={onSearchKeydown}\n />\n )\n }\n listbox={{\n list,\n id: listId,\n empty: remote.failure() ?? (search ? lang.selectNoMatch : empty),\n renderOption:\n children &&\n ((item: T | Creation, state: OptionRenderState) =>\n item instanceof Creation ? lang.selectCreate(item.text) : children(item, state)),\n multiple: multiple(),\n }}\n // 使用方按 T 写列表的部件属性;creatable 时多出的“新建”那一项由上面的 renderOption 处理\n propsListbox={propsListbox as Partial<ListboxViewProps<T | Creation>> | undefined}\n propsPopover={propsPopover}\n />\n </>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/input/Select.tsx"],"sourcesContent":["/**\n * 下拉选择(WAI-ARIA 的 select-only combobox):点触发框弹出选项列表,单选或多选。\n *\n * <Field label=\"城市\"><Select items={['北京', '上海', '广州']} _value={city} placeholder=\"选择城市\" /></Field>\n * <Select items={tags} selectionMode=\"multiple\" _value={picked} clearable aria-label=\"标签\" />\n * <Select items={users} toOption={(user) => ({ value: user.id, label: user.name })} _value={id} />\n * <Select items={suppliers} searchable _value={supplier} /> 选项多时:弹出层顶部带搜索框\n *\n * <Select items={tags} selectionMode=\"multiple\" maxTagCount=\"responsive\" creatable onCreate={(text) => tags.push(text)} … />\n *\n * 组合已有的部件:外壳是输入框外壳(controlParts),弹出层用 useAnchoredPopover(与外壳同宽、最高到视口剩余空间),\n * 列表是 ListboxView(状态与键盘见 list-state.ts)。焦点一直在触发按钮上,高亮项经 aria-activedescendant 告诉读屏。\n *\n * 多选时已选的项是触发按钮前面的一排 Tag(不能放进 button 里:按钮里不能有按钮),各带移除按钮。\n * 这排标签只给指针用(aria-hidden、移除按钮不进 Tab 顺序):读屏从触发按钮里念出全部已选内容,\n * 键盘在列表里取消勾选,或在触发按钮(及空的搜索框)里按 Backspace 移除最后一项(同 TagsInput)。\n * maxTagCount 是数字时只显示前几个,'responsive' 时排成一行按宽度放,其余收进“+N”(SelectedTags,TreeSelect 共用)。\n *\n * 键盘:关闭时 ↓ / Enter / 空格打开(↑ 打开并高亮最后一项),单选时直接按字母选中以它开头的项(同原生 select);\n * 打开时 ↑↓、Home / End、Page Up / Down 移动,Enter / 空格选中(单选随后关闭),Esc、Tab 关闭。\n * 写了 name 时用隐藏的 input 随表单提交(多选时每个值一个)。\n *\n * searchable 时弹出层顶部有搜索框:打开后焦点在搜索框里,输入就过滤选项(按显示文字,忽略大小写与重音,或用 filter),\n * ↑↓ 移动、Enter 选中、Esc 关闭并把焦点还给触发按钮。已选的项被过滤掉、或 items 换了(远程搜索)时,\n * 触发框里仍显示它的文字(useSelectedOptions)。\n *\n * 远程选项:给 load 时打开就按搜索词请求,输入停下 300 ms 再请求,只采用最后一次(remote-items.ts);\n * 自己管请求时写 _search={keyword} 拿到搜索词、filter={false} 关掉本地过滤,items 与 loading 自己给。\n *\n * <Select searchable load={(q, signal) => http.get<User[]>('/users', { query: { q }, signal })} toOption={…} _value={owner} />\n *\n * creatable 时自带搜索框,输入的文字没有对应的选项时列表末尾多一项“新建“…””:选中后值就是这段文字,onCreate 报告它。\n *\n * 部件:Root(外壳)、Tags(多选时的那排标签)、Tag、Trigger(button,主元素)、Value、Clear、Chevron、Popover、\n * Search(TextField)、Listbox。\n */\nimport { ChevronDown, Plus, Search } from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, watch, type VNodeChild } from 'vue';\nimport type { PresetIconButtonProps } from '../base/CloseButton';\nimport { buttonBaseStyles } from '../base/button-core';\nimport { Icon, type IconProps } from '../base/Icon';\nimport type { TagProps } from '../base/Tag';\nimport { visuallyHiddenStyles } from '../base/VisuallyHidden';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { useAnchoredPopover, type FloatingPlacement } from '../utils/dom/floating';\nimport { openSetter, type OpenChangeProps } from '../utils/dom/open-change';\nimport { ListPopover } from './ListPopover';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { selectedValues, type SelectionProps } from '../utils/data/selection';\nimport {\n controlClear,\n controlParts,\n clickOnShell,\n focusOnShell,\n controlIcon,\n useControlAppearance,\n type ControlIconOptions,\n type ControlOptions,\n} from './control';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { disclosureStyles } from '../utils/style/transitions';\nimport { activeOptionId, type ListboxViewProps, type OptionRenderState } from './Listbox';\nimport {\n handleListKeydown,\n useListState,\n useResultAnnouncement,\n useSelectedOptions,\n type ListboxOption,\n type OptionMapping,\n toListboxOption,\n} from './list-state';\nimport { useRemoteItems, type OptionsLoader } from './remote-items';\nimport { SelectedTags, type SelectedTagsProps } from './SelectedTags';\nimport { TextField, type TextFieldProps } from './TextField';\n\n/** 角色、展开状态与可用性由组件管理 */\nexport type SelectManaged =\n | 'type'\n | 'role'\n | 'value'\n | 'disabled'\n | 'aria-haspopup'\n | 'aria-expanded'\n | 'aria-controls'\n | 'aria-activedescendant'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-describedby';\n\n/** 下拉选择共有的属性;未声明的属性落到触发按钮(主元素)上,外壳用 propsRoot */\nexport interface SelectBaseProps<T>\n extends PartProps<'button', SelectManaged>, ControlOptions, ControlIconOptions, OpenChangeProps {\n /** 数据:ListboxOption、字符串,或任意数据加 toOption;有 load 时是第一次加载之前的选项(编辑页放上已选的那一项) */\n items?: readonly T[];\n /** 没有选择时显示的文字,默认取语言包(请选择) */\n placeholder?: string;\n /** 是否打开:父级可以写 _open={x} */\n _open?: boolean;\n /** 弹出位置,默认 bottom-start */\n placement?: FloatingPlacement;\n /** 有选择时显示清空按钮 */\n clearable?: boolean;\n /** 弹出层顶部带搜索框,输入过滤选项:选项多(供应商、人员、件号)时用 */\n searchable?: boolean;\n /** 搜索时怎样算匹配;默认显示文字包含输入(忽略大小写与重音)。false 时不在本地过滤(服务端按 search 过滤) */\n filter?: false | ((item: T, query: string) => boolean);\n /** 搜索框里的文字:打开时清空;父级写 _search={x} 拿到它(自己发请求时) */\n _search?: string;\n /** 远程选项:打开时与搜索词停下 300 ms 后调用,结果代替 items;只采用最后一次,被顶掉的请求 signal 中止 */\n load?: OptionsLoader<T>;\n /**\n * 可以新建选项(自带搜索框):输入的文字没有对应的选项时,列表末尾多一项“新建“…””,选中后值就是这段文字。\n * 在 onCreate 里把它加进 items(或存到服务端);不加时触发框里照样显示这段文字\n */\n creatable?: boolean;\n /** 新建了一项(creatable 时):参数是输入的文字,也就是选中的值 */\n onCreate?: (text: string) => void;\n /** 多选时触发框里最多显示几个标签,其余收进“+N”;'responsive' 时排成一行、按宽度放,放不下的收起 */\n maxTagCount?: number | 'responsive';\n /** 表单提交时的 name(用隐藏的 input) */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、能看到已选的内容,不能打开、不能清空 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 自定义选项内容:`{(option, { selected, active }) => …}` */\n children?: (item: T, state: OptionRenderState) => VNodeChild;\n /** 自定义触发框里显示的内容(已选的选项);默认单选显示文字、多选显示标签 */\n renderValue?: (selected: readonly T[]) => VNodeChild;\n /** 正在取选项(异步加载):没有选项时列表里是骨架行,已有选项时顶部显示进度条 */\n loading?: boolean;\n /** 没有选项时列表里显示的内容 */\n empty?: VNodeChild;\n /** 外壳的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 已选内容那一层的部件属性 */\n propsValue?: PartProps<'span'>;\n /** 多选时每个标签的部件属性 */\n propsTag?: Partial<TagProps>;\n /** 多选时那排标签的部件属性 */\n propsTags?: Partial<SelectedTagsProps>;\n /** 清空按钮的部件属性 */\n propsClear?: Partial<PresetIconButtonProps>;\n /** 下拉箭头的部件属性 */\n propsChevron?: Partial<IconProps>;\n /** 弹出层的部件属性 */\n propsPopover?: PartProps<'div', 'id' | 'popover'>;\n /** 列表的部件属性 */\n propsListbox?: Partial<ListboxViewProps<T>>;\n /** 搜索框的部件属性(searchable 时) */\n propsSearch?: Partial<TextFieldProps>;\n}\n\n/** 单选或多选;items 不是 ListboxOption 或字符串时要给 toOption */\nexport type SelectProps<T = ListboxOption> = SelectBaseProps<T> & SelectionProps & OptionMapping<T>;\n\n/** Select 的样式:root、trigger、value、placeholder、chevronOpen 等 */\nexport const selectStyles = css.create({\n // 在 ControlGroup 里也按内容宽(输入框才分剩余宽度)\n root: { cursor: 'pointer', flexGrow: 0 },\n // 去掉按钮默认外观用 buttonBaseStyles;像输入框一样没有自己的焦点环与波纹(焦点环画在外壳上)\n trigger: {\n display: 'flex',\n alignItems: 'center',\n flexGrow: 1,\n minWidth: 0,\n alignSelf: 'stretch',\n textAlign: 'start',\n cursor: 'inherit',\n outlineStyle: 'none',\n },\n value: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '_xs',\n minWidth: 0,\n paddingBlock: '_xs',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n // 是真正的文字(不是原生 placeholder),要满足 4.5:1:用 textMuted 而不是 textPlaceholder\n placeholder: { color: '_textMuted' },\n // 多选时标签排在触发按钮前面(SelectedTags)占剩余宽度,触发按钮里只剩读屏用的文字\n triggerBehindTags: { flexGrow: 0 },\n chevronOpen: { rotate: '180deg' },\n // 弹出层顶部的搜索框占满宽度\n search: { width: '_full' },\n});\n\n/** creatable 时列表末尾那一项“新建“…””:不是 items 里的数据 */\nclass Creation {\n readonly text: string;\n constructor(text: string) {\n this.text = text;\n }\n}\n\n/** 下拉选择:触发框 + 弹出的选项列表 */\nexport const Select = _component(\n <T,>({\n items = [],\n toOption,\n selectionMode = 'single',\n _value: value = _bindable<string | string[] | null>(null),\n _open: open = _bindable(false),\n onOpenChange,\n placeholder,\n placement = 'bottom-start',\n clearable = false,\n searchable = false,\n filter,\n _search: search = _bindable(''),\n load,\n creatable = false,\n onCreate,\n maxTagCount,\n name,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n id,\n icon,\n children,\n renderValue,\n empty,\n loading = false,\n propsRoot,\n propsIcon,\n propsValue,\n propsTag,\n propsTags,\n propsClear,\n propsChevron,\n propsPopover,\n propsListbox,\n propsSearch,\n ...rest\n }: SelectProps<T>) => {\n const lang = useLang();\n const textMatcher = useTextMatcher();\n const listId = useId();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const multiple = () => selectionMode === 'multiple';\n const optionOf = (item: T) => toListboxOption(item, toOption);\n const remote = useRemoteItems({\n load: () => load,\n query: () => search,\n open: () => open,\n items: () => items,\n });\n // 本地过滤:有 load 或 filter={false} 时交给服务端\n const localFilter = () => !load && filter !== false;\n const matches = (item: T, text: string) =>\n filter ? filter(item, text) : textMatcher()(optionOf(item).label, text);\n // creatable 自带搜索框\n const withSearch = () => searchable || creatable;\n // creatable:输入的文字没有同名(或同值)的选项时,列表末尾多一项“新建”\n const creation = () => {\n const text = search.trim();\n if (!creatable || !text) return undefined;\n const exists = remote.items().some((item) => {\n const option = optionOf(item);\n return option.value === text || option.label.toLowerCase() === text.toLowerCase();\n });\n return exists ? undefined : new Creation(text);\n };\n const list = useListState<T | Creation>({\n items: () => {\n const all = remote.items();\n const shown =\n withSearch() && search && localFilter()\n ? all.filter((item) => matches(item, search))\n : all;\n const created = creation();\n return created ? [...shown, created] : shown;\n },\n toOption: (item) =>\n item instanceof Creation\n ? { value: item.text, label: lang.selectCreate(item.text), icon: Plus }\n : optionOf(item),\n selected: () => selectedValues(value),\n mode: () => selectionMode,\n onChange: (next) => {\n const created = creation();\n if (created && next.includes(created.text)) {\n onCreate?.(created.text);\n search = '';\n }\n value = multiple() ? [...next] : (next[0] ?? null);\n },\n // 单选时再点已选的一项不取消(同原生 select);要清空用清除按钮\n required: () => !multiple(),\n });\n // 已选项的文字取自全部 items(过滤掉的、远程搜索换掉的也在)\n const selectedOptions = useSelectedOptions({ items: remote.items, toOption: optionOf });\n let shell = _state.raw<HTMLElement | null>(null);\n let trigger = _state.raw<HTMLElement | null>(null);\n let panel = _state.raw<HTMLElement | null>(null);\n const setOpen = openSetter(\n () => open,\n (next) => (open = next),\n () => onOpenChange,\n );\n\n /** 多选时移除一项(标签的移除按钮、Backspace) */\n function remove(target: string) {\n value = selectedValues(value).filter((item) => item !== target);\n }\n\n function removeLast() {\n const last = selectedValues(value).at(-1);\n if (last !== undefined) remove(last);\n }\n\n function show(highlight: 'default' | 'last' = 'default', event?: Event) {\n search = '';\n list.activateDefault();\n if (highlight === 'last' && selectedValues(value).length === 0) list.move('last');\n setOpen(true, 'trigger', event);\n }\n\n useResultAnnouncement(() => ({ query: search, count: list.options.length }));\n\n // 输入搜索词:高亮第一个匹配的。打开时清空搜索词不算:那时高亮的是已选项\n watch(\n () => search,\n (text) => text && list.move('first'),\n );\n\n // 选中一项:单选时关闭\n function picked(event?: Event) {\n if (!multiple()) setOpen(false, 'select', event);\n }\n\n /** Ctrl / Cmd / Alt 组合键是浏览器的(刷新、复制、查找),不做按字母跳转 */\n const hasModifier = (event: KeyboardEvent) => event.altKey || event.ctrlKey || event.metaKey;\n\n function onKeydown(event: KeyboardEvent) {\n if (control().disabled || control().readonly) return;\n if (event.key === 'Backspace' && multiple()) {\n event.preventDefault();\n removeLast();\n return;\n }\n if (!open) {\n if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n show('default', event);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n show('last', event);\n } else if (!multiple() && !hasModifier(event) && list.typeahead(event.key)) {\n // 同原生 select:关闭时按字母直接选中\n event.preventDefault();\n if (list.active !== undefined && !list.isSelected(list.active)) list.select(list.active);\n }\n return;\n }\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (handleListKeydown(list, event, { space: true, typeahead: true }, () => picked(event))) {\n event.preventDefault();\n }\n }\n\n // 搜索框里:↑↓ 移动、Enter 选中(Home / End、空格留给输入),Tab 关闭后照常移到下一个;\n // 多选时空的搜索框里按 Backspace 移除最后一项\n function onSearchKeydown(event: KeyboardEvent) {\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (event.key === 'Backspace' && !search && multiple()) {\n event.preventDefault();\n removeLast();\n return;\n }\n if (handleListKeydown(list, event, { homeEnd: false }, () => picked(event)))\n event.preventDefault();\n }\n\n function clear() {\n value = multiple() ? [] : null;\n trigger?.focus();\n }\n\n // 弹层贴着外壳、与它同宽;焦点一直在触发按钮上,关闭时不用归还(searchable 时见 onPanelToggle)\n const { onToggle } = useAnchoredPopover(\n () => ({\n open,\n anchor: shell,\n panel,\n floating: { placement, matchWidth: true, fitHeight: true },\n restoreFocus: false,\n }),\n { close: (reason, event) => setOpen(false, reason, event) },\n );\n\n // searchable:打开后焦点进搜索框;关闭时焦点还在弹层里(Esc、选中、点外面)就还给触发按钮\n function onPanelToggle(event: ToggleEvent) {\n onToggle(event);\n if (!withSearch()) return;\n if (event.newState === 'open') {\n panel?.querySelector<HTMLInputElement>('input[type=\"search\"]')?.focus();\n return;\n }\n const active = document.activeElement;\n if (!active || active === document.body || panel?.contains(active)) trigger?.focus();\n }\n\n return () => {\n const state = control();\n const values = selectedValues(value);\n const selected = selectedOptions(values);\n const off = state.disabled;\n // 只读:能聚焦,不能打开、不能改\n const locked = off || state.readonly;\n // 多选的默认显示:触发按钮前面一排标签,按钮里只留给读屏的文字\n const tagged = multiple() && !renderValue && selected.length > 0;\n const shown = tagged ? (\n <span {...css.attrs(visuallyHiddenStyles.hidden)}>\n {lang.selectSummary(selected.map((option) => option.label))}\n </span>\n ) : (\n (renderValue?.(\n selected.flatMap((option) => (option.item === undefined ? [] : [option.item])),\n ) ??\n (selected.length === 0 ? (\n <span {...css.attrs(selectStyles.placeholder)}>\n {placeholder ?? lang.selectPlaceholder}\n </span>\n ) : (\n selected[0]!.label\n )))\n );\n const tags = tagged && (\n <SelectedTags\n {...mergePartProps<SelectedTagsProps>(\n {\n tags: selected,\n maxTagCount,\n onRemove: locked ? undefined : remove,\n propsTag,\n },\n propsTags,\n )}\n />\n );\n const s = controlParts(appearance(), state);\n return (\n <>\n <div\n {...mergeAttrs<'div'>({ ...s.root, sx: [s.root.sx, selectStyles.root] }, propsRoot, {\n ref: _toRef(shell),\n // 点在外壳空白处(含多选的标签):焦点交给触发按钮,并与点触发按钮一样切换打开(只读时只聚焦)\n onPointerdown: off ? undefined : focusOnShell(() => trigger),\n onClick: locked\n ? undefined\n : clickOnShell(\n () => trigger,\n (event) => (open ? setOpen(false, 'trigger', event) : show('default', event)),\n ),\n })}\n data-state={open ? 'open' : 'closed'}\n data-invalid={state.invalid || undefined}\n data-disabled={off || undefined}\n >\n {controlIcon(s, icon, propsIcon)}\n {tags}\n <button\n {...mergeAttrs<'button'>(\n {\n sx: [\n buttonBaseStyles.root,\n selectStyles.trigger,\n tagged && selectStyles.triggerBehindTags,\n ],\n },\n rest,\n {\n ref: _toRef(trigger),\n id: state.id,\n type: 'button',\n role: 'combobox',\n disabled: off,\n 'aria-haspopup': 'listbox',\n 'aria-expanded': open,\n 'aria-controls': listId,\n 'aria-activedescendant': open ? activeOptionId(list, listId) : undefined,\n 'aria-invalid': state.invalid || undefined,\n 'aria-required': state.required || undefined,\n 'aria-readonly': state.readonly || undefined,\n 'aria-describedby': state.describedBy,\n onClick: (event: MouseEvent) => {\n // Safari 点击按钮不会聚焦它:焦点要在触发按钮上,键盘与 aria-activedescendant 才有效\n trigger?.focus();\n if (locked) return;\n if (open) setOpen(false, 'trigger', event);\n else show('default', event);\n },\n onKeydown,\n },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: selectStyles.value }, propsValue)}>{shown}</span>\n </button>\n {clearable && values.length > 0 && !locked && controlClear(s, propsClear, clear)}\n <Icon\n {...mergePartProps<IconProps>(\n {\n ...s.icon,\n icon: ChevronDown,\n sx: [s.icon.sx, disclosureStyles.icon, open && selectStyles.chevronOpen],\n },\n propsChevron,\n )}\n />\n <FormValue name={name} value={values} disabled={state.disabled} />\n </div>\n <ListPopover\n panelRef={_toRef(panel)}\n onToggle={onPanelToggle}\n size={appearance().size}\n labelledBy={state.labelledBy}\n label={rest['aria-label']}\n loading={loading || remote.loading()}\n onPick={() => picked()}\n header={\n withSearch() && (\n <TextField\n {...mergePartProps<TextFieldProps>(\n {\n icon: Search,\n variant: 'soft',\n placeholder: lang.selectSearch,\n 'aria-label': lang.selectSearch,\n propsRoot: { sx: selectStyles.search },\n },\n propsSearch,\n )}\n type=\"search\"\n _value={search}\n aria-controls={listId}\n aria-activedescendant={open ? activeOptionId(list, listId) : undefined}\n onKeydown={onSearchKeydown}\n />\n )\n }\n listbox={{\n list,\n id: listId,\n empty: remote.failure() ?? (search ? lang.selectNoMatch : empty),\n renderOption:\n children &&\n ((item: T | Creation, state: OptionRenderState) =>\n item instanceof Creation ? lang.selectCreate(item.text) : children(item, state)),\n multiple: multiple(),\n }}\n // 使用方按 T 写列表的部件属性;creatable 时多出的“新建”那一项由上面的 renderOption 处理\n propsListbox={propsListbox as Partial<ListboxViewProps<T | Creation>> | undefined}\n propsPopover={propsPopover}\n />\n </>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { Tag } from "../base/Tag.js";
|
|
|
4
4
|
import { useOverflowItems } from "../utils/dom/overflow.js";
|
|
5
5
|
import { createVNode, isVNode, shallowRef } from "vue";
|
|
6
6
|
import { _component, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
7
|
-
import
|
|
7
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
8
8
|
//#region src/input/SelectedTags.tsx
|
|
9
9
|
/** 一个已选的标签 */
|
|
10
10
|
/** 未声明的属性落到这一排的 span 上 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectedTags.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/input/SelectedTags.tsx"],"sourcesContent":["/**\n * 多选下拉的触发按钮前面那一排已选标签:Select、TreeSelect 共用。\n *\n * <SelectedTags tags={selected} maxTagCount=\"responsive\" onRemove={(value) => remove(value)} />\n *\n * 标签不能放进触发按钮里(按钮里不能有按钮),所以排在它前面。这排标签只给指针用:aria-hidden、移除按钮不进 Tab 顺序、\n * 按下时不抢焦点;读屏从触发按钮里念全部已选(lang.selectSummary),键盘在列表里取消勾选,或在触发按钮上按 Backspace。\n * maxTagCount 是数字时只显示前几个,'responsive' 时排成一行按宽度放(useOverflowItems),其余收进“+N”。\n * 未声明的属性落到这一排的 span 上。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport
|
|
1
|
+
{"version":3,"file":"SelectedTags.js","names":["_isVNode","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/input/SelectedTags.tsx"],"sourcesContent":["/**\n * 多选下拉的触发按钮前面那一排已选标签:Select、TreeSelect 共用。\n *\n * <SelectedTags tags={selected} maxTagCount=\"responsive\" onRemove={(value) => remove(value)} />\n *\n * 标签不能放进触发按钮里(按钮里不能有按钮),所以排在它前面。这排标签只给指针用:aria-hidden、移除按钮不进 Tab 顺序、\n * 按下时不抢焦点;读屏从触发按钮里念全部已选(lang.selectSummary),键盘在列表里取消勾选,或在触发按钮上按 Backspace。\n * maxTagCount 是数字时只显示前几个,'responsive' 时排成一行按宽度放(useOverflowItems),其余收进“+N”。\n * 未声明的属性落到这一排的 span 上。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { Tag, type TagProps } from '../base/Tag';\nimport { useLang } from '../config/context';\nimport { useOverflowItems } from '../utils/dom/overflow';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\n\n/** 一个已选的标签 */\nexport interface SelectedTag {\n /** 值:移除时交给 onRemove */\n value: string;\n /** 显示的文字 */\n label: string;\n}\n\n/** 未声明的属性落到这一排的 span 上 */\nexport interface SelectedTagsProps extends PartProps<'span', 'aria-hidden'> {\n /** 要显示的标签 */\n tags: readonly SelectedTag[];\n /** 最多显示几个,其余收进“+N”;'responsive' 时排成一行、按宽度放 */\n maxTagCount?: number | 'responsive';\n /** 点标签的移除按钮;不写时(只读、不可用)标签没有移除按钮 */\n onRemove?: (value: string) => void;\n /** 每个标签的部件属性 */\n propsTag?: Partial<TagProps>;\n}\n\n/** SelectedTags 的样式:root、line */\nexport const selectedTagsStyles = css.create({\n // 占触发框里剩下的宽度;触发按钮里只剩读屏用的文字\n root: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '_xs',\n flexGrow: 1,\n minWidth: 0,\n paddingBlock: '_xs',\n },\n // responsive:一行,放不下的移出排版(useOverflowItems 要求容器 position: relative);\n // contain: inline-size 让这一行不按内容撑宽外壳(不然按内容宽度排版的祖先会被整行标签撑开,永远“放得下”)\n line: { flexWrap: 'nowrap', position: 'relative', overflow: 'hidden', contain: 'inline-size' },\n});\n\n/** 移除按钮按下时不抢焦点:焦点留在触发按钮上 */\nconst keepFocus = (event: PointerEvent) => event.preventDefault();\n\n/** 多选下拉的已选标签:可移除,可按数量或宽度收起 */\nexport const SelectedTags = _component(\n ({ tags, maxTagCount, onRemove, propsTag, ...rest }: SelectedTagsProps) => {\n const lang = useLang();\n let row = _state.raw<HTMLElement | null>(null);\n const overflow = useOverflowItems({\n container: () => (maxTagCount === 'responsive' ? row : null),\n count: () => tags.length,\n min: () => 1,\n });\n return () => {\n const responsive = maxTagCount === 'responsive';\n const shown =\n typeof maxTagCount === 'number' ? tags.slice(0, Math.max(0, maxTagCount)) : tags;\n const hiddenCount = responsive ? overflow.hidden : tags.length - shown.length;\n return (\n <span\n {...mergeAttrs<'span'>(\n { sx: [selectedTagsStyles.root, responsive && selectedTagsStyles.line] },\n rest,\n { ref: _toRef(row), 'aria-hidden': 'true' },\n )}\n >\n {shown.map((tag, index) => (\n <Tag\n key={tag.value}\n {...mergePartProps<TagProps>(\n {\n size: 'sm',\n variant: 'soft',\n onRemove: onRemove && (() => onRemove(tag.value)),\n propsRemove: { tabindex: -1, onPointerdown: keepFocus },\n },\n propsTag,\n )}\n {...(responsive ? overflow.itemProps(index) : {})}\n >\n {tag.label}\n </Tag>\n ))}\n {/* responsive 时“+N”一直在(没有折起的项时藏起来,但仍要量它的宽度) */}\n {(responsive || hiddenCount > 0) && (\n <Tag size=\"sm\" variant=\"soft\" {...(responsive ? overflow.restProps() : {})}>\n {lang.selectMoreTags(hiddenCount)}\n </Tag>\n )}\n </span>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;AAyBA,SAAA,QAAA,GAAA;CAAA,OAAA,OAAA,MAAA,cAAA,OAAA,UAAA,SAAA,KAAA,CAAA,MAAA,qBAAA,CAAAA,QAAA,CAAA;AAAA;;AAaA,IAAa,qBAAqB,IAAI,OAAO;CAE3C,MAAM;EACJ,SAAS;EACT,UAAU;EACV,YAAY;EACZ,KAAK;EACL,UAAU;EACV,UAAU;EACV,cAAc;CAChB;CAGA,MAAM;EAAE,UAAU;EAAU,UAAU;EAAY,UAAU;EAAU,SAAS;CAAc;AAC/F,CAAC;;AAGD,IAAM,aAAa,UAAwB,MAAM,eAAe;;AAGhE,IAAa,eAAe,0BAC1B,QAAA,SAA2E;CAAA,MAAA,OAAAC,aAAA,QAAA,MAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAA9B,OAAIC,UAAA,QAAA,MAAA,IAAA;CAC/C,MAAM,OAAO,QAAQ;CACrB,IAAI,MAAGC,WAAkC,IAAI;CAC7C,MAAM,WAAW,iBAAiB;EAChC,iBAAkB,YAAA,UAAgB,eAAY,IAAA,QAAS;EACvD,aAAa,KAAA,MAAK;EAClB,WAAW;CACb,CAAC;CACD,aAAa;EAAA,IAAA;EACX,MAAM,aAAa,YAAA,UAAgB;EACnC,MAAM,QACJ,OAAA,YAAA,UAAuB,WAAW,KAAA,MAAK,MAAM,GAAG,KAAK,IAAI,GAAC,YAAA,KAAa,CAAC,IAAC,KAAA;EAC3E,MAAM,cAAc,aAAa,SAAS,SAAS,KAAA,MAAK,SAAS,MAAM;EACvE,OAAAC,YAAA,QAEQ,WACF,EAAE,IAAI,CAAC,mBAAmB,MAAM,cAAc,mBAAmB,IAAI,EAAE,GACvE,MACA;GAAE,KAAG;GAAe,eAAe;EAAO,CAC5C,GAAC,CAEA,MAAM,KAAK,KAAK,UAAKA,YAAA,KAAAC,cAAA,EAAA,OAEb,IAAI,MAAK,GACV,eACF;GACE,MAAM;GACN,SAAS;GACT,UAAU,SAAA,gBAAmB,SAAA,MAAS,IAAI,KAAK;GAC/C,aAAa;IAAE,UAAU;IAAI,eAAe;GAAU;EACxD,GAAC,SAAA,KAEH,GACK,aAAa,SAAS,UAAU,KAAK,IAAI,CAAC,CAAC,GAAA,EAAA,eAAA,CAE/C,IAAI,KAAK,EAAA,CAAA,CAEb,IAEC,cAAc,cAAc,MAACD,YAAA,KAAAC,cAAA;GAAA,QAAA;GAAA,WAAA;EAAA,GACM,aAAa,SAAS,UAAU,IAAI,CAAC,CAAC,GAAA,QAAA,QACtE,KAAK,eAAe,WAAW,CAAC,IAAA,QAAA,EAAA,eAAA,CAAA,KAAA,EAAA,CAAA,CAEpC,CAAA;CAGP;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
package/dist/input/Slider.d.ts
CHANGED
|
@@ -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 PartProps } from '../utils/props';
|
|
4
4
|
import { type StatusTone } from '../utils/style/tone-styles';
|
package/dist/input/Slider.js
CHANGED
|
@@ -12,7 +12,7 @@ import { useFieldControl } from "../form/Field.js";
|
|
|
12
12
|
import { FormValue } from "../form/FormValue.js";
|
|
13
13
|
import { createVNode, isVNode, shallowRef, useId } from "vue";
|
|
14
14
|
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
15
|
-
import
|
|
15
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
16
16
|
//#region src/input/Slider.tsx
|
|
17
17
|
/** 滑块方向 */
|
|
18
18
|
/** 单值,或范围 [低, 高] */
|
package/dist/input/Slider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slider.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/input/Slider.tsx"],"sourcesContent":["/**\n * 滑块:在一个范围里拖动选值(音量、进度、价格)。WAI-ARIA 的 Slider 模式:滑块是 role=\"slider\",\n * 方向键 ±step,Page Up / Page Down ±bigStep,Home / End 到两端;从右到左排版时横向的方向键反过来。\n * 点击轨道任意位置直接跳过去并接着拖动。参考 Radix Slider、React Aria useSlider。\n *\n * <Slider _value={volume} aria-label=\"音量\" />\n * <Slider _value={price} min={0} max={1000} step={50} valueText={(v) => `${v} 元`} />\n * <Slider _value={range} aria-label=\"价格\" marks={[0, { value: 500, label: '500' }, 1000]} /> 范围:[低, 高]\n *\n * value 是数组 [低, 高] 时是范围选择:两个滑块各自可聚焦、可拖动,不能交叉;点击轨道移动离得近的那个。\n * 两个滑块的名称在 aria-label(或 Field 的标签)后面加上“最小值”“最大值”,取值范围互相限制(同 WAI-ARIA 多滑块)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { startMove } from '../utils/dom/move';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { toneFillStyles, type StatusTone } from '../utils/style/tone-styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { clamp, snapToStep } from '../utils/data/number';\nimport { inlineArrows, isRtl } from '../utils/dom/direction';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { t } from '../config/theme/tokens';\n\n/** 滑块方向 */\nexport interface SliderOrientations {\n /** 横向(默认):起始端是最小值 */\n horizontal: unknown;\n /** 纵向:底端是最小值;高度由使用方给,默认 10em */\n vertical: unknown;\n}\n\n/** 单值,或范围 [低, 高] */\nexport type SliderValue = number | readonly [number, number];\n\n/** 轨道上的一个刻度 */\nexport interface SliderMark {\n /** 刻度所在的值 */\n value: number;\n /** 刻度下方(纵向时右侧)的文字 */\n label?: VNodeChild;\n}\n\n/** 角色、取值与可聚焦由组件管理 */\nexport type SliderManaged =\n | 'role'\n | 'tabindex'\n | 'aria-valuemin'\n | 'aria-valuemax'\n | 'aria-valuenow'\n | 'aria-valuetext'\n | 'aria-orientation'\n | 'aria-disabled';\n\n/** 未声明的属性落到滑块(role=\"slider\" 的主元素,范围时两个都有)上,名称写 aria-label;外层用 propsRoot */\nexport interface SliderProps<V extends SliderValue = number> extends PartProps<\n 'div',\n SliderManaged\n> {\n /** 当前值:父级写 _value={x} 双向绑定,拖动中实时写回;数组 [低, 高] 时是范围选择 */\n _value?: V;\n /** 最小值,默认 0 */\n min?: number;\n /** 最大值,默认 100 */\n max?: number;\n /** 步长,默认 1;取值总是对齐到 min + n × step */\n step?: number;\n /** Page Up / Page Down 的步长,默认为范围的十分之一(至少一个 step) */\n bigStep?: number;\n /** 方向,默认 horizontal */\n orientation?: keyof SliderOrientations;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:滑块能聚焦、读屏念“只读”,拖动与方向键不改值(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 字号档位,滑块与轨道随之缩放;不写时继承 */\n size?: TextSize;\n /** 已选范围与滑块描边的色调(与 Button、Badge 等同一套),默认 accent */\n tone?: StatusTone;\n /** 刻度:数字或带文字的 { value, label };有文字时滑块下方(纵向时右侧)留出位置 */\n marks?: readonly (number | SliderMark)[];\n /** 读屏念的取值文字(aria-valuetext),如 `(v) => \\`${v}%\\``;不写时念数字 */\n valueText?: (value: number) => string;\n /** 表单字段名:给了就带隐藏的 input(范围时两个同名),随表单提交 */\n name?: string;\n /** 一次操作结束(松开、按键)时的值:保存、发请求放在这里,不必每次移动都发 */\n onValueCommit?: (value: V) => void;\n /** 外层(轨道与滑块的容器)的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 轨道的部件属性 */\n propsTrack?: PartProps<'div'>;\n /** 已选范围(轨道上着色的部分)的部件属性;位置与长度由组件写 */\n propsRange?: PartProps<'div'>;\n /** 刻度点的部件属性 */\n propsMark?: PartProps<'span'> | ((mark: SliderMark) => PartProps<'span'>);\n /** 刻度文字的部件属性 */\n propsMarkLabel?: PartProps<'span'> | ((mark: SliderMark) => PartProps<'span'>);\n}\n\n/** Slider 的样式:root、horizontal、vertical、disabled、readonly、track、range、thumb、mark、markLabel 等 */\nexport const sliderStyles = css.create({\n root: {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n // 触摸拖动不触发页面滚动\n touchAction: 'none',\n userSelect: 'none',\n cursor: 'pointer',\n },\n // 点击区域至少 24px(WCAG 2.5.8)。滑块的中心对准取值,两端各留半个滑块的外边距:\n // 滑块在最小、最大值时不伸出组件的盒子,不压到旁边的控件\n horizontal: {\n width: `calc(100% - ${t.space.lg} - ${t.space.xs})`,\n marginInline: `calc((${t.space.lg} + ${t.space.xs}) / 2)`,\n minHeight: '_minTarget',\n },\n vertical: {\n flexDirection: 'column',\n height: '10em',\n marginBlock: `calc((${t.space.lg} + ${t.space.xs}) / 2)`,\n minWidth: '_minTarget',\n },\n // 刻度文字放在轨道下方(纵向时右侧),给它留出位置\n labelledHorizontal: { paddingBlockEnd: '1.5em' },\n labelledVertical: { paddingInlineEnd: '3em' },\n disabled: { opacity: '_disabled', cursor: 'not-allowed' },\n readonly: { cursor: 'default' },\n track: {\n position: 'relative',\n flexGrow: 1,\n borderRadius: '_full',\n backgroundColor: '_fill',\n overflow: 'hidden',\n },\n trackHorizontal: { height: `calc(${t.space.xs} * 1.5)` },\n trackVertical: { width: `calc(${t.space.xs} * 1.5)` },\n range: { position: 'absolute', backgroundColor: 'var(--tone-fill)' },\n rangeHorizontal: { insetBlock: 0 },\n rangeVertical: { insetInline: 0 },\n thumb: {\n position: 'absolute',\n boxSizing: 'border-box',\n width: `calc(${t.space.lg} + ${t.space.xs})`,\n height: `calc(${t.space.lg} + ${t.space.xs})`,\n borderWidth: '_sm',\n borderStyle: 'solid',\n borderColor: 'var(--tone-fill)',\n borderRadius: '_full',\n backgroundColor: '_surface',\n boxShadow: '_sm',\n cursor: 'grab',\n },\n // 用逻辑方向的外边距把滑块的中心对准取值位置:从右到左排版时也对\n thumbHorizontal: { marginInlineStart: `calc((${t.space.lg} + ${t.space.xs}) / -2)` },\n thumbVertical: { marginBottom: `calc((${t.space.lg} + ${t.space.xs}) / -2)` },\n // 轨道里的小圆点;在已选范围里时换成反色\n mark: {\n position: 'absolute',\n width: '_space.xs',\n height: '_space.xs',\n borderRadius: '_full',\n backgroundColor: '_borderStrong',\n pointerEvents: 'none',\n },\n markHorizontal: { top: '50%', translate: { default: '-50% -50%', ':dir(rtl)': '50% -50%' } },\n markVertical: { left: '50%', translate: '-50% 50%' },\n markActive: { backgroundColor: 'var(--tone-on-fill)' },\n markLabel: {\n position: 'absolute',\n fontSize: '_sm',\n lineHeight: '_tight',\n color: '_textMuted',\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n },\n markLabelHorizontal: {\n top: `calc(50% + ${t.space.sm})`,\n translate: { default: '-50% -0.75em', ':dir(rtl)': '50% -0.75em' },\n },\n markLabelVertical: { left: `calc(50% + ${t.space.md})`, translate: '0 50%' },\n});\n\n// 位置是任意值,用动态样式(编译为 CSS 变量);单独一个 create,见 COMPONENTS.md §4\n/** Slider 的样式:inline(横向的起点)、size(横向的长度)、bottom、height(纵向) */\nexport const sliderPositionStyles = css.create({\n inline: (percent: string) => ({ insetInlineStart: percent }),\n width: (percent: string) => ({ width: percent }),\n bottom: (percent: string) => ({ bottom: percent }),\n height: (percent: string) => ({ height: percent }),\n});\n\n/** 滑块:在 min–max 之间按 step 拖动或用键盘选值;value 为 [低, 高] 时选一个范围 */\nexport const Slider = _component(\n <V extends SliderValue = number>({\n _value: value = _bindable<V>(0 as V),\n min = 0,\n max = 100,\n step = 1,\n bigStep,\n orientation = 'horizontal',\n disabled,\n readonly,\n size,\n tone = 'accent',\n marks,\n valueText,\n name,\n onValueCommit,\n propsRoot,\n propsTrack,\n propsRange,\n propsMark,\n propsMarkLabel,\n id,\n ...rest\n }: SliderProps<V>) => {\n const lang = useLang();\n // 在 Field 里时:标签作为名称、关联说明与错误、沿用不可用与只读\n const control = useFieldControl(() => ({ id, disabled, readonly }));\n /** 不接受改值:不可用或只读 */\n const off = () => control().disabled || control().readonly;\n const labelId = useId();\n let track = _state.raw<HTMLElement | null>(null);\n const thumbs: (HTMLElement | null)[] = [null, null];\n\n const isRange = () => Array.isArray(value);\n /** 各滑块的值(单值时只有一个) */\n const values = (): number[] => (Array.isArray(value) ? [...value] : [value as number]);\n /** 夹在范围内并对齐到步长 */\n const snap = (raw: number) => snapToStep(raw, step, min, max);\n const rtl = () => orientation === 'horizontal' && !!track && isRtl(track);\n\n /** 第 index 个滑块能取的范围:范围选择时不能越过另一个 */\n function bounds(index: number): [number, number] {\n if (!isRange()) return [min, max];\n const [low, high] = values() as [number, number];\n return index === 0 ? [min, high] : [low, max];\n }\n\n /** 改第 index 个滑块的值 */\n function set(index: number, raw: number) {\n const [lower, upper] = bounds(index);\n const next = clamp(snap(raw), lower, upper);\n if (!isRange()) {\n value = next as V;\n return;\n }\n const pair = values() as [number, number];\n pair[index] = next;\n value = pair as unknown as V;\n }\n\n /** 指针位置对应的值 */\n function valueAt(clientX: number, clientY: number) {\n const rect = track!.getBoundingClientRect();\n let ratio =\n orientation === 'vertical'\n ? (rect.bottom - clientY) / rect.height\n : (clientX - rect.left) / rect.width;\n if (rtl()) ratio = 1 - ratio;\n return snap(min + clamp(ratio, 0, 1) * (max - min));\n }\n\n /** 离 target 最近的滑块;两个重合时按方向选(往高处去的拿高的那个) */\n function nearest(target: number) {\n if (!isRange()) return 0;\n const [low, high] = values() as [number, number];\n if (low === high) return target > high ? 1 : 0;\n return Math.abs(target - low) <= Math.abs(target - high) ? 0 : 1;\n }\n\n function grab(event: PointerEvent) {\n if (off() || event.button !== 0 || !track) return;\n // 不让浏览器把焦点放到别处、开始选中文字;焦点交给滑块,键盘接着可以微调\n event.preventDefault();\n const target = valueAt(event.clientX, event.clientY);\n const index = nearest(target);\n thumbs[index]?.focus();\n set(index, target);\n startMove(event, {\n onMove: ({ clientX, clientY }) => set(index, valueAt(clientX, clientY)),\n onEnd: () => onValueCommit?.(value),\n });\n }\n\n function onKeydown(index: number, event: KeyboardEvent) {\n if (off()) return;\n const current = values()[index]!;\n const big = bigStep ?? Math.max(step, (max - min) / 10);\n // 从右到左排版时,横向的左右键反过来(右边是起点)\n const { forward, backward } = inlineArrows(rtl());\n const [lower, upper] = bounds(index);\n const next: Record<string, number> = {\n [forward]: current + step,\n ArrowUp: current + step,\n [backward]: current - step,\n ArrowDown: current - step,\n PageUp: current + big,\n PageDown: current - big,\n Home: lower,\n End: upper,\n };\n if (!(event.key in next)) return;\n event.preventDefault();\n set(index, next[event.key]!);\n onValueCommit?.(value);\n }\n\n const percentOf = (number: number) =>\n max > min ? ((clamp(number, min, max) - min) / (max - min)) * 100 : 0;\n\n return () => {\n const vertical = orientation === 'vertical';\n const field = control();\n const range = isRange();\n // 父级传入超出范围的值时按范围内显示(不改父级的值),滑块不会跑出轨道\n const shown = values().map((number) => clamp(number, min, max));\n const [start, end] = range\n ? [percentOf(shown[0]!), percentOf(shown[1]!)]\n : [0, percentOf(shown[0]!)];\n const normalized = (marks ?? []).map((mark) =>\n typeof mark === 'number' ? { value: mark } : mark,\n );\n const labelled = normalized.some((mark) => mark.label != null);\n const position = (percent: number) =>\n vertical\n ? sliderPositionStyles.bottom(`${percent}%`)\n : sliderPositionStyles.inline(`${percent}%`);\n\n const renderThumb = (number: number, index: number) => {\n const [lower, upper] = bounds(index);\n const part = range ? (index === 0 ? lang.sliderMin : lang.sliderMax) : undefined;\n const ownLabel = rest['aria-label'];\n // 范围时每个滑块的名称后面加“最小值 / 最大值”:有 aria-label 时拼在一起,用 Field 的标签时连上隐藏的文字\n const labelledBy = defaultLabelledBy(rest, field.labelledBy);\n return (\n <div\n key={index}\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.thumb,\n focusRingStyles.visible,\n vertical ? sliderStyles.thumbVertical : sliderStyles.thumbHorizontal,\n position(percentOf(number)),\n ],\n },\n rest,\n {\n ref: (element: unknown) => (thumbs[index] = element as HTMLElement | null),\n role: 'slider',\n id: index === 0 ? field.id : undefined,\n tabindex: field.disabled ? undefined : 0,\n 'aria-valuemin': lower,\n 'aria-valuemax': upper,\n 'aria-valuenow': number,\n 'aria-valuetext': valueText?.(number),\n 'aria-orientation': orientation,\n 'aria-disabled': field.disabled || undefined,\n 'aria-readonly': field.readonly || undefined,\n 'aria-label': part && ownLabel != null ? `${ownLabel} ${part}` : ownLabel,\n 'aria-labelledby':\n part && labelledBy ? `${labelledBy} ${labelId}-${index}` : labelledBy,\n 'aria-describedby': field.describedBy,\n 'aria-invalid': field.invalid || undefined,\n onKeydown: (event: KeyboardEvent) => onKeydown(index, event),\n },\n )}\n data-index={range ? index : undefined}\n >\n {part && labelledBy && (\n <VisuallyHidden id={`${labelId}-${index}`}>{part}</VisuallyHidden>\n )}\n </div>\n );\n };\n\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.root,\n vertical ? sliderStyles.vertical : sliderStyles.horizontal,\n labelled &&\n (vertical ? sliderStyles.labelledVertical : sliderStyles.labelledHorizontal),\n toneFillStyles[tone],\n size && fontSizeStyles[size],\n ],\n },\n propsRoot,\n {\n sx: [\n field.readonly && sliderStyles.readonly,\n field.disabled && sliderStyles.disabled,\n ],\n onPointerdown: grab,\n },\n )}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readonly || undefined}\n data-orientation={orientation}\n data-range={range || undefined}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.track,\n vertical ? sliderStyles.trackVertical : sliderStyles.trackHorizontal,\n ],\n },\n propsTrack,\n { ref: _toRef(track) },\n )}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.range,\n vertical ? sliderStyles.rangeVertical : sliderStyles.rangeHorizontal,\n ],\n },\n propsRange,\n {\n sx: [\n position(start),\n vertical\n ? sliderPositionStyles.height(`${end - start}%`)\n : sliderPositionStyles.width(`${end - start}%`),\n ],\n },\n )}\n />\n {normalized.map((mark) => {\n const percent = percentOf(mark.value);\n const own = typeof propsMark === 'function' ? propsMark(mark) : propsMark;\n return (\n <span\n key={mark.value}\n {...mergeAttrs<'span'>(\n {\n sx: [\n sliderStyles.mark,\n vertical ? sliderStyles.markVertical : sliderStyles.markHorizontal,\n percent >= start && percent <= end && sliderStyles.markActive,\n ],\n },\n own,\n { sx: position(percent) },\n )}\n />\n );\n })}\n </div>\n {shown.map(renderThumb)}\n {normalized.map((mark) => {\n if (mark.label == null) return null;\n const own =\n typeof propsMarkLabel === 'function' ? propsMarkLabel(mark) : propsMarkLabel;\n return (\n <span\n key={mark.value}\n {...mergeAttrs<'span'>(\n {\n sx: [\n sliderStyles.markLabel,\n vertical ? sliderStyles.markLabelVertical : sliderStyles.markLabelHorizontal,\n ],\n },\n own,\n { sx: position(percentOf(mark.value)), 'aria-hidden': true },\n )}\n >\n {mark.label}\n </span>\n );\n })}\n <FormValue name={name} value={range ? shown : shown[0]} disabled={control().disabled} />\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Slider.js","names":["_isVNode","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/input/Slider.tsx"],"sourcesContent":["/**\n * 滑块:在一个范围里拖动选值(音量、进度、价格)。WAI-ARIA 的 Slider 模式:滑块是 role=\"slider\",\n * 方向键 ±step,Page Up / Page Down ±bigStep,Home / End 到两端;从右到左排版时横向的方向键反过来。\n * 点击轨道任意位置直接跳过去并接着拖动。参考 Radix Slider、React Aria useSlider。\n *\n * <Slider _value={volume} aria-label=\"音量\" />\n * <Slider _value={price} min={0} max={1000} step={50} valueText={(v) => `${v} 元`} />\n * <Slider _value={range} aria-label=\"价格\" marks={[0, { value: 500, label: '500' }, 1000]} /> 范围:[低, 高]\n *\n * value 是数组 [低, 高] 时是范围选择:两个滑块各自可聚焦、可拖动,不能交叉;点击轨道移动离得近的那个。\n * 两个滑块的名称在 aria-label(或 Field 的标签)后面加上“最小值”“最大值”,取值范围互相限制(同 WAI-ARIA 多滑块)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { startMove } from '../utils/dom/move';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport { toneFillStyles, type StatusTone } from '../utils/style/tone-styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { clamp, snapToStep } from '../utils/data/number';\nimport { inlineArrows, isRtl } from '../utils/dom/direction';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { t } from '../config/theme/tokens';\n\n/** 滑块方向 */\nexport interface SliderOrientations {\n /** 横向(默认):起始端是最小值 */\n horizontal: unknown;\n /** 纵向:底端是最小值;高度由使用方给,默认 10em */\n vertical: unknown;\n}\n\n/** 单值,或范围 [低, 高] */\nexport type SliderValue = number | readonly [number, number];\n\n/** 轨道上的一个刻度 */\nexport interface SliderMark {\n /** 刻度所在的值 */\n value: number;\n /** 刻度下方(纵向时右侧)的文字 */\n label?: VNodeChild;\n}\n\n/** 角色、取值与可聚焦由组件管理 */\nexport type SliderManaged =\n | 'role'\n | 'tabindex'\n | 'aria-valuemin'\n | 'aria-valuemax'\n | 'aria-valuenow'\n | 'aria-valuetext'\n | 'aria-orientation'\n | 'aria-disabled';\n\n/** 未声明的属性落到滑块(role=\"slider\" 的主元素,范围时两个都有)上,名称写 aria-label;外层用 propsRoot */\nexport interface SliderProps<V extends SliderValue = number> extends PartProps<\n 'div',\n SliderManaged\n> {\n /** 当前值:父级写 _value={x} 双向绑定,拖动中实时写回;数组 [低, 高] 时是范围选择 */\n _value?: V;\n /** 最小值,默认 0 */\n min?: number;\n /** 最大值,默认 100 */\n max?: number;\n /** 步长,默认 1;取值总是对齐到 min + n × step */\n step?: number;\n /** Page Up / Page Down 的步长,默认为范围的十分之一(至少一个 step) */\n bigStep?: number;\n /** 方向,默认 horizontal */\n orientation?: keyof SliderOrientations;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:滑块能聚焦、读屏念“只读”,拖动与方向键不改值(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 字号档位,滑块与轨道随之缩放;不写时继承 */\n size?: TextSize;\n /** 已选范围与滑块描边的色调(与 Button、Badge 等同一套),默认 accent */\n tone?: StatusTone;\n /** 刻度:数字或带文字的 { value, label };有文字时滑块下方(纵向时右侧)留出位置 */\n marks?: readonly (number | SliderMark)[];\n /** 读屏念的取值文字(aria-valuetext),如 `(v) => \\`${v}%\\``;不写时念数字 */\n valueText?: (value: number) => string;\n /** 表单字段名:给了就带隐藏的 input(范围时两个同名),随表单提交 */\n name?: string;\n /** 一次操作结束(松开、按键)时的值:保存、发请求放在这里,不必每次移动都发 */\n onValueCommit?: (value: V) => void;\n /** 外层(轨道与滑块的容器)的部件属性 */\n propsRoot?: PartProps<'div'>;\n /** 轨道的部件属性 */\n propsTrack?: PartProps<'div'>;\n /** 已选范围(轨道上着色的部分)的部件属性;位置与长度由组件写 */\n propsRange?: PartProps<'div'>;\n /** 刻度点的部件属性 */\n propsMark?: PartProps<'span'> | ((mark: SliderMark) => PartProps<'span'>);\n /** 刻度文字的部件属性 */\n propsMarkLabel?: PartProps<'span'> | ((mark: SliderMark) => PartProps<'span'>);\n}\n\n/** Slider 的样式:root、horizontal、vertical、disabled、readonly、track、range、thumb、mark、markLabel 等 */\nexport const sliderStyles = css.create({\n root: {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n // 触摸拖动不触发页面滚动\n touchAction: 'none',\n userSelect: 'none',\n cursor: 'pointer',\n },\n // 点击区域至少 24px(WCAG 2.5.8)。滑块的中心对准取值,两端各留半个滑块的外边距:\n // 滑块在最小、最大值时不伸出组件的盒子,不压到旁边的控件\n horizontal: {\n width: `calc(100% - ${t.space.lg} - ${t.space.xs})`,\n marginInline: `calc((${t.space.lg} + ${t.space.xs}) / 2)`,\n minHeight: '_minTarget',\n },\n vertical: {\n flexDirection: 'column',\n height: '10em',\n marginBlock: `calc((${t.space.lg} + ${t.space.xs}) / 2)`,\n minWidth: '_minTarget',\n },\n // 刻度文字放在轨道下方(纵向时右侧),给它留出位置\n labelledHorizontal: { paddingBlockEnd: '1.5em' },\n labelledVertical: { paddingInlineEnd: '3em' },\n disabled: { opacity: '_disabled', cursor: 'not-allowed' },\n readonly: { cursor: 'default' },\n track: {\n position: 'relative',\n flexGrow: 1,\n borderRadius: '_full',\n backgroundColor: '_fill',\n overflow: 'hidden',\n },\n trackHorizontal: { height: `calc(${t.space.xs} * 1.5)` },\n trackVertical: { width: `calc(${t.space.xs} * 1.5)` },\n range: { position: 'absolute', backgroundColor: 'var(--tone-fill)' },\n rangeHorizontal: { insetBlock: 0 },\n rangeVertical: { insetInline: 0 },\n thumb: {\n position: 'absolute',\n boxSizing: 'border-box',\n width: `calc(${t.space.lg} + ${t.space.xs})`,\n height: `calc(${t.space.lg} + ${t.space.xs})`,\n borderWidth: '_sm',\n borderStyle: 'solid',\n borderColor: 'var(--tone-fill)',\n borderRadius: '_full',\n backgroundColor: '_surface',\n boxShadow: '_sm',\n cursor: 'grab',\n },\n // 用逻辑方向的外边距把滑块的中心对准取值位置:从右到左排版时也对\n thumbHorizontal: { marginInlineStart: `calc((${t.space.lg} + ${t.space.xs}) / -2)` },\n thumbVertical: { marginBottom: `calc((${t.space.lg} + ${t.space.xs}) / -2)` },\n // 轨道里的小圆点;在已选范围里时换成反色\n mark: {\n position: 'absolute',\n width: '_space.xs',\n height: '_space.xs',\n borderRadius: '_full',\n backgroundColor: '_borderStrong',\n pointerEvents: 'none',\n },\n markHorizontal: { top: '50%', translate: { default: '-50% -50%', ':dir(rtl)': '50% -50%' } },\n markVertical: { left: '50%', translate: '-50% 50%' },\n markActive: { backgroundColor: 'var(--tone-on-fill)' },\n markLabel: {\n position: 'absolute',\n fontSize: '_sm',\n lineHeight: '_tight',\n color: '_textMuted',\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n },\n markLabelHorizontal: {\n top: `calc(50% + ${t.space.sm})`,\n translate: { default: '-50% -0.75em', ':dir(rtl)': '50% -0.75em' },\n },\n markLabelVertical: { left: `calc(50% + ${t.space.md})`, translate: '0 50%' },\n});\n\n// 位置是任意值,用动态样式(编译为 CSS 变量);单独一个 create,见 COMPONENTS.md §4\n/** Slider 的样式:inline(横向的起点)、size(横向的长度)、bottom、height(纵向) */\nexport const sliderPositionStyles = css.create({\n inline: (percent: string) => ({ insetInlineStart: percent }),\n width: (percent: string) => ({ width: percent }),\n bottom: (percent: string) => ({ bottom: percent }),\n height: (percent: string) => ({ height: percent }),\n});\n\n/** 滑块:在 min–max 之间按 step 拖动或用键盘选值;value 为 [低, 高] 时选一个范围 */\nexport const Slider = _component(\n <V extends SliderValue = number>({\n _value: value = _bindable<V>(0 as V),\n min = 0,\n max = 100,\n step = 1,\n bigStep,\n orientation = 'horizontal',\n disabled,\n readonly,\n size,\n tone = 'accent',\n marks,\n valueText,\n name,\n onValueCommit,\n propsRoot,\n propsTrack,\n propsRange,\n propsMark,\n propsMarkLabel,\n id,\n ...rest\n }: SliderProps<V>) => {\n const lang = useLang();\n // 在 Field 里时:标签作为名称、关联说明与错误、沿用不可用与只读\n const control = useFieldControl(() => ({ id, disabled, readonly }));\n /** 不接受改值:不可用或只读 */\n const off = () => control().disabled || control().readonly;\n const labelId = useId();\n let track = _state.raw<HTMLElement | null>(null);\n const thumbs: (HTMLElement | null)[] = [null, null];\n\n const isRange = () => Array.isArray(value);\n /** 各滑块的值(单值时只有一个) */\n const values = (): number[] => (Array.isArray(value) ? [...value] : [value as number]);\n /** 夹在范围内并对齐到步长 */\n const snap = (raw: number) => snapToStep(raw, step, min, max);\n const rtl = () => orientation === 'horizontal' && !!track && isRtl(track);\n\n /** 第 index 个滑块能取的范围:范围选择时不能越过另一个 */\n function bounds(index: number): [number, number] {\n if (!isRange()) return [min, max];\n const [low, high] = values() as [number, number];\n return index === 0 ? [min, high] : [low, max];\n }\n\n /** 改第 index 个滑块的值 */\n function set(index: number, raw: number) {\n const [lower, upper] = bounds(index);\n const next = clamp(snap(raw), lower, upper);\n if (!isRange()) {\n value = next as V;\n return;\n }\n const pair = values() as [number, number];\n pair[index] = next;\n value = pair as unknown as V;\n }\n\n /** 指针位置对应的值 */\n function valueAt(clientX: number, clientY: number) {\n const rect = track!.getBoundingClientRect();\n let ratio =\n orientation === 'vertical'\n ? (rect.bottom - clientY) / rect.height\n : (clientX - rect.left) / rect.width;\n if (rtl()) ratio = 1 - ratio;\n return snap(min + clamp(ratio, 0, 1) * (max - min));\n }\n\n /** 离 target 最近的滑块;两个重合时按方向选(往高处去的拿高的那个) */\n function nearest(target: number) {\n if (!isRange()) return 0;\n const [low, high] = values() as [number, number];\n if (low === high) return target > high ? 1 : 0;\n return Math.abs(target - low) <= Math.abs(target - high) ? 0 : 1;\n }\n\n function grab(event: PointerEvent) {\n if (off() || event.button !== 0 || !track) return;\n // 不让浏览器把焦点放到别处、开始选中文字;焦点交给滑块,键盘接着可以微调\n event.preventDefault();\n const target = valueAt(event.clientX, event.clientY);\n const index = nearest(target);\n thumbs[index]?.focus();\n set(index, target);\n startMove(event, {\n onMove: ({ clientX, clientY }) => set(index, valueAt(clientX, clientY)),\n onEnd: () => onValueCommit?.(value),\n });\n }\n\n function onKeydown(index: number, event: KeyboardEvent) {\n if (off()) return;\n const current = values()[index]!;\n const big = bigStep ?? Math.max(step, (max - min) / 10);\n // 从右到左排版时,横向的左右键反过来(右边是起点)\n const { forward, backward } = inlineArrows(rtl());\n const [lower, upper] = bounds(index);\n const next: Record<string, number> = {\n [forward]: current + step,\n ArrowUp: current + step,\n [backward]: current - step,\n ArrowDown: current - step,\n PageUp: current + big,\n PageDown: current - big,\n Home: lower,\n End: upper,\n };\n if (!(event.key in next)) return;\n event.preventDefault();\n set(index, next[event.key]!);\n onValueCommit?.(value);\n }\n\n const percentOf = (number: number) =>\n max > min ? ((clamp(number, min, max) - min) / (max - min)) * 100 : 0;\n\n return () => {\n const vertical = orientation === 'vertical';\n const field = control();\n const range = isRange();\n // 父级传入超出范围的值时按范围内显示(不改父级的值),滑块不会跑出轨道\n const shown = values().map((number) => clamp(number, min, max));\n const [start, end] = range\n ? [percentOf(shown[0]!), percentOf(shown[1]!)]\n : [0, percentOf(shown[0]!)];\n const normalized = (marks ?? []).map((mark) =>\n typeof mark === 'number' ? { value: mark } : mark,\n );\n const labelled = normalized.some((mark) => mark.label != null);\n const position = (percent: number) =>\n vertical\n ? sliderPositionStyles.bottom(`${percent}%`)\n : sliderPositionStyles.inline(`${percent}%`);\n\n const renderThumb = (number: number, index: number) => {\n const [lower, upper] = bounds(index);\n const part = range ? (index === 0 ? lang.sliderMin : lang.sliderMax) : undefined;\n const ownLabel = rest['aria-label'];\n // 范围时每个滑块的名称后面加“最小值 / 最大值”:有 aria-label 时拼在一起,用 Field 的标签时连上隐藏的文字\n const labelledBy = defaultLabelledBy(rest, field.labelledBy);\n return (\n <div\n key={index}\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.thumb,\n focusRingStyles.visible,\n vertical ? sliderStyles.thumbVertical : sliderStyles.thumbHorizontal,\n position(percentOf(number)),\n ],\n },\n rest,\n {\n ref: (element: unknown) => (thumbs[index] = element as HTMLElement | null),\n role: 'slider',\n id: index === 0 ? field.id : undefined,\n tabindex: field.disabled ? undefined : 0,\n 'aria-valuemin': lower,\n 'aria-valuemax': upper,\n 'aria-valuenow': number,\n 'aria-valuetext': valueText?.(number),\n 'aria-orientation': orientation,\n 'aria-disabled': field.disabled || undefined,\n 'aria-readonly': field.readonly || undefined,\n 'aria-label': part && ownLabel != null ? `${ownLabel} ${part}` : ownLabel,\n 'aria-labelledby':\n part && labelledBy ? `${labelledBy} ${labelId}-${index}` : labelledBy,\n 'aria-describedby': field.describedBy,\n 'aria-invalid': field.invalid || undefined,\n onKeydown: (event: KeyboardEvent) => onKeydown(index, event),\n },\n )}\n data-index={range ? index : undefined}\n >\n {part && labelledBy && (\n <VisuallyHidden id={`${labelId}-${index}`}>{part}</VisuallyHidden>\n )}\n </div>\n );\n };\n\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.root,\n vertical ? sliderStyles.vertical : sliderStyles.horizontal,\n labelled &&\n (vertical ? sliderStyles.labelledVertical : sliderStyles.labelledHorizontal),\n toneFillStyles[tone],\n size && fontSizeStyles[size],\n ],\n },\n propsRoot,\n {\n sx: [\n field.readonly && sliderStyles.readonly,\n field.disabled && sliderStyles.disabled,\n ],\n onPointerdown: grab,\n },\n )}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readonly || undefined}\n data-orientation={orientation}\n data-range={range || undefined}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.track,\n vertical ? sliderStyles.trackVertical : sliderStyles.trackHorizontal,\n ],\n },\n propsTrack,\n { ref: _toRef(track) },\n )}\n >\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n sliderStyles.range,\n vertical ? sliderStyles.rangeVertical : sliderStyles.rangeHorizontal,\n ],\n },\n propsRange,\n {\n sx: [\n position(start),\n vertical\n ? sliderPositionStyles.height(`${end - start}%`)\n : sliderPositionStyles.width(`${end - start}%`),\n ],\n },\n )}\n />\n {normalized.map((mark) => {\n const percent = percentOf(mark.value);\n const own = typeof propsMark === 'function' ? propsMark(mark) : propsMark;\n return (\n <span\n key={mark.value}\n {...mergeAttrs<'span'>(\n {\n sx: [\n sliderStyles.mark,\n vertical ? sliderStyles.markVertical : sliderStyles.markHorizontal,\n percent >= start && percent <= end && sliderStyles.markActive,\n ],\n },\n own,\n { sx: position(percent) },\n )}\n />\n );\n })}\n </div>\n {shown.map(renderThumb)}\n {normalized.map((mark) => {\n if (mark.label == null) return null;\n const own =\n typeof propsMarkLabel === 'function' ? propsMarkLabel(mark) : propsMarkLabel;\n return (\n <span\n key={mark.value}\n {...mergeAttrs<'span'>(\n {\n sx: [\n sliderStyles.markLabel,\n vertical ? sliderStyles.markLabelVertical : sliderStyles.markLabelHorizontal,\n ],\n },\n own,\n { sx: position(percentOf(mark.value)), 'aria-hidden': true },\n )}\n >\n {mark.label}\n </span>\n );\n })}\n <FormValue name={name} value={range ? shown : shown[0]} disabled={control().disabled} />\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
package/dist/input/Switch.d.ts
CHANGED
package/dist/input/Switch.js
CHANGED
|
@@ -7,7 +7,7 @@ import { useFieldControl } from "../form/Field.js";
|
|
|
7
7
|
import { choiceInputStyles, choiceParts, syncChecked, useChoiceAppearance } from "./choice-styles.js";
|
|
8
8
|
import { createVNode } from "vue";
|
|
9
9
|
import { _component, bindable, childrenProp, 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/input/Switch.tsx
|
|
12
12
|
/** 角色、勾选状态与可用性由组件管理;原生的 size 属性让给字号档位 */
|
|
13
13
|
/** 未声明的属性落到 input 上;外层 label 用 propsRoot */
|
package/dist/input/Switch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/input/Switch.tsx"],"sourcesContent":["/**\n * 开关(原生 input type=\"checkbox\" + role=\"switch\"):立即生效的开 / 关设置,如“接收通知”。\n * 需要提交才生效的选项用 Checkbox。结构与样式见 choice-styles.ts:input 画成轨道,滑块叠在上面。\n *\n * <Switch _checked={notify}>接收通知</Switch>\n *\n * 读屏念“开关,开 / 关”;空格切换(原生)。在 Field 里时关联说明与错误、沿用其状态。\n * 切换要等接口时用 loading:滑块里转圈、点击无效。轨道里可以放文字或图标(checkedContent / uncheckedContent),对读屏隐藏。\n * 部件:Root(label)、Control(叠放层)、Thumb(滑块)、Content(轨道里的文字)、ContentText(文字的字号层)、Spinner、Label(文字);未声明的属性落到 input 上。\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 { useFieldControl } from '../form/Field';\nimport { Spinner, type SpinnerProps } from '../base/Spinner';\nimport { useDelayedLoading } from '../utils/motion/delayed-loading';\nimport { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport type { TextSize } from '../utils/style/typography';\nimport { choiceInputStyles, choiceParts, syncChecked, useChoiceAppearance } from './choice-styles';\nimport { t } from '../config/theme/tokens';\n\n/** 角色、勾选状态与可用性由组件管理;原生的 size 属性让给字号档位 */\nexport type SwitchManaged =\n | 'type'\n | 'role'\n | 'checked'\n | 'disabled'\n | 'required'\n | 'size'\n | 'aria-invalid'\n | 'aria-describedby'\n | 'aria-busy';\n\n/** 未声明的属性落到 input 上;外层 label 用 propsRoot */\nexport interface SwitchProps extends PartProps<'input', SwitchManaged> {\n /** 是否打开:父级写 _checked={x} */\n _checked?: boolean;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、读屏念“只读”,不能切换(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 切换中(如等接口返回):滑块里显示加载指示,点击无效,带 aria-busy */\n loading?: boolean;\n /** 打开时轨道里的文字或图标(如“开”、对勾);给了它或 uncheckedContent 时轨道随内容加宽 */\n checkedContent?: VNodeChild;\n /** 关闭时轨道里的文字或图标 */\n uncheckedContent?: VNodeChild;\n /** 字号档位;不写时继承上下文字号 */\n size?: TextSize;\n /** 打开时轨道的色调(与 Button、Badge 等同一套),默认 accent;可以用 defaults.Choice 统一改 */\n tone?: StatusTone;\n /** 外层 label 的部件属性 */\n propsRoot?: PartProps<'label'>;\n /** 叠放层的部件属性 */\n propsControl?: PartProps<'span'>;\n /** 滑块的部件属性 */\n propsThumb?: PartProps<'span'>;\n /** 轨道里文字(开、关两份)的部件属性 */\n propsContent?: PartProps<'span'>;\n /** 轨道里文字的内层(定字号、字重)的部件属性;改字号写这里,外层的内边距才仍按开关的字号算 */\n propsContentText?: PartProps<'span'>;\n /** 加载指示的部件属性 */\n propsSpinner?: Partial<SpinnerProps>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 文字 */\n children?: VNodeChild;\n}\n\n/** Switch 的样式:track、trackWide、trackOff、thumb、thumbOn、content、contentOn、contentOff、contentHidden、contentText、spinner */\nexport const switchStyles = css.create({\n track: { width: '2.25em', height: '1.25em', borderRadius: '_full', borderColor: 'transparent' },\n // 轨道里有文字:宽度随文字(两份文字叠在同一格里,取较宽的,切换时宽度不跳)\n trackWide: { width: '_full', minWidth: '2.25em' },\n trackOff: { backgroundColor: '_borderStrong' },\n // 滑块靠起始边,打开后移到结束边:用逻辑方向的外边距,从右到左排版自动反过来\n thumb: {\n display: 'grid',\n placeItems: 'center',\n justifySelf: 'start',\n width: '0.875em',\n height: '0.875em',\n marginInlineStart: '0.1875em',\n borderRadius: '_full',\n backgroundColor: '_background',\n boxShadow: '_sm',\n transition: `margin-inline-start ${t.durations.sm} ${t.easings.standard}`,\n },\n // 移到结束边:百分比相对整条轨道,轨道随文字加宽时同样贴边\n thumbOn: { marginInlineStart: 'calc(100% - 1.0625em)', backgroundColor: 'var(--tone-on-fill)' },\n // 用 flex 居中:按行内文字排时随外层的行高落在基线上,图标会比轨道中线偏下\n content: {\n gridArea: '1 / 1',\n justifySelf: 'stretch',\n alignSelf: 'center',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n },\n // 文字在滑块的另一侧\n contentOn: {\n paddingInlineStart: '0.5em',\n paddingInlineEnd: '1.375em',\n color: 'var(--tone-on-fill)',\n },\n contentOff: { paddingInlineStart: '1.375em', paddingInlineEnd: '0.5em', color: '_text' },\n contentHidden: { visibility: 'hidden' },\n // 字号缩在里层:外层的内边距按开关的字号算,给滑块留的位置才够\n contentText: {\n display: 'flex',\n alignItems: 'center',\n fontSize: '_xs',\n fontWeight: '_semibold',\n lineHeight: 1,\n },\n spinner: { width: '0.75em', height: '0.75em', color: 'var(--tone-fill)' },\n});\n\n/** 开关:立即生效的开 / 关 */\nexport const Switch = _component(\n ({\n _checked: checked = _bindable(false),\n disabled,\n readonly,\n required,\n invalid,\n size,\n tone,\n loading = false,\n checkedContent,\n uncheckedContent,\n id,\n propsRoot,\n propsControl,\n propsThumb,\n propsContent,\n propsContentText,\n propsSpinner,\n propsLabel,\n children,\n ...rest\n }: SwitchProps) => {\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const appearance = useChoiceAppearance(() => ({ size, tone }));\n // 很快完成的切换不闪加载指示;点击拦截、aria-busy 按真实的 loading\n const spinner = useDelayedLoading(() => loading);\n return () => {\n const state = control();\n const s = choiceParts(appearance(), { disabled: state.disabled, readonly: state.readonly });\n const wide = checkedContent != null || uncheckedContent != null;\n const content = (on: boolean, child: VNodeChild) => (\n <span\n {...mergeAttrs<'span'>(\n {\n sx: [\n switchStyles.content,\n on ? switchStyles.contentOn : switchStyles.contentOff,\n on !== checked && switchStyles.contentHidden,\n ],\n },\n propsContent,\n { 'aria-hidden': true },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: switchStyles.contentText }, propsContentText)}>\n {child}\n </span>\n </span>\n );\n return (\n <label\n {...mergeAttrs<'label'>(s.root, propsRoot)}\n data-state={checked ? 'checked' : 'unchecked'}\n data-disabled={state.disabled || undefined}\n data-readonly={state.readonly || undefined}\n data-loading={loading || undefined}\n >\n <span {...mergeAttrs<'span'>(s.control, propsControl)}>\n <input\n {...mergeAttrs<'input'>(\n {\n ...s.input,\n sx: [\n s.input.sx,\n focusRingStyles.tight,\n switchStyles.track,\n wide && switchStyles.trackWide,\n checked ? choiceInputStyles.checked : switchStyles.trackOff,\n state.invalid && choiceInputStyles.invalid,\n ],\n },\n rest,\n {\n type: 'checkbox',\n role: 'switch',\n id: state.id,\n checked,\n disabled: state.disabled,\n required: state.required,\n 'aria-invalid': state.invalid || undefined,\n 'aria-readonly': state.readonly || undefined,\n 'aria-describedby': state.describedBy,\n 'aria-busy': loading || undefined,\n // 切换中、只读时不接受切换:拦下 click,勾选状态就不变\n onClick: (event: MouseEvent) => {\n if (loading || state.readonly) event.preventDefault();\n },\n onChange: (event: Event) => {\n const target = event.target as HTMLInputElement;\n checked = target.checked;\n syncChecked([target], () => checked);\n },\n },\n )}\n />\n {wide && content(true, checkedContent)}\n {wide && content(false, uncheckedContent)}\n <span\n {...mergeAttrs<'span'>(\n {\n ...s.indicator,\n sx: [s.indicator.sx, switchStyles.thumb, checked && switchStyles.thumbOn],\n },\n propsThumb,\n )}\n >\n {spinner.value && (\n <Spinner\n {...mergePartProps<SpinnerProps>(\n { propsIcon: { sx: switchStyles.spinner } },\n propsSpinner,\n )}\n />\n )}\n </span>\n </span>\n {hasContent(children) && (\n <span {...mergeAttrs<'span'>(s.label, propsLabel)}>{children}</span>\n )}\n </label>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Switch.js","names":["_vtp_bindable","_vtp_readonlyProp","_vtp_childrenProp","_vtp_restProps","_createVNode","_mergeProps"],"sources":["../../src/input/Switch.tsx"],"sourcesContent":["/**\n * 开关(原生 input type=\"checkbox\" + role=\"switch\"):立即生效的开 / 关设置,如“接收通知”。\n * 需要提交才生效的选项用 Checkbox。结构与样式见 choice-styles.ts:input 画成轨道,滑块叠在上面。\n *\n * <Switch _checked={notify}>接收通知</Switch>\n *\n * 读屏念“开关,开 / 关”;空格切换(原生)。在 Field 里时关联说明与错误、沿用其状态。\n * 切换要等接口时用 loading:滑块里转圈、点击无效。轨道里可以放文字或图标(checkedContent / uncheckedContent),对读屏隐藏。\n * 部件:Root(label)、Control(叠放层)、Thumb(滑块)、Content(轨道里的文字)、ContentText(文字的字号层)、Spinner、Label(文字);未声明的属性落到 input 上。\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 { useFieldControl } from '../form/Field';\nimport { Spinner, type SpinnerProps } from '../base/Spinner';\nimport { useDelayedLoading } from '../utils/motion/delayed-loading';\nimport { hasContent, mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { focusRingStyles } from '../utils/style/styles';\nimport type { StatusTone } from '../utils/style/tone-styles';\nimport type { TextSize } from '../utils/style/typography';\nimport { choiceInputStyles, choiceParts, syncChecked, useChoiceAppearance } from './choice-styles';\nimport { t } from '../config/theme/tokens';\n\n/** 角色、勾选状态与可用性由组件管理;原生的 size 属性让给字号档位 */\nexport type SwitchManaged =\n | 'type'\n | 'role'\n | 'checked'\n | 'disabled'\n | 'required'\n | 'size'\n | 'aria-invalid'\n | 'aria-describedby'\n | 'aria-busy';\n\n/** 未声明的属性落到 input 上;外层 label 用 propsRoot */\nexport interface SwitchProps extends PartProps<'input', SwitchManaged> {\n /** 是否打开:父级写 _checked={x} */\n _checked?: boolean;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、读屏念“只读”,不能切换(查看详情、审批时);外观照常 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 切换中(如等接口返回):滑块里显示加载指示,点击无效,带 aria-busy */\n loading?: boolean;\n /** 打开时轨道里的文字或图标(如“开”、对勾);给了它或 uncheckedContent 时轨道随内容加宽 */\n checkedContent?: VNodeChild;\n /** 关闭时轨道里的文字或图标 */\n uncheckedContent?: VNodeChild;\n /** 字号档位;不写时继承上下文字号 */\n size?: TextSize;\n /** 打开时轨道的色调(与 Button、Badge 等同一套),默认 accent;可以用 defaults.Choice 统一改 */\n tone?: StatusTone;\n /** 外层 label 的部件属性 */\n propsRoot?: PartProps<'label'>;\n /** 叠放层的部件属性 */\n propsControl?: PartProps<'span'>;\n /** 滑块的部件属性 */\n propsThumb?: PartProps<'span'>;\n /** 轨道里文字(开、关两份)的部件属性 */\n propsContent?: PartProps<'span'>;\n /** 轨道里文字的内层(定字号、字重)的部件属性;改字号写这里,外层的内边距才仍按开关的字号算 */\n propsContentText?: PartProps<'span'>;\n /** 加载指示的部件属性 */\n propsSpinner?: Partial<SpinnerProps>;\n /** 文字的部件属性 */\n propsLabel?: PartProps<'span'>;\n /** 文字 */\n children?: VNodeChild;\n}\n\n/** Switch 的样式:track、trackWide、trackOff、thumb、thumbOn、content、contentOn、contentOff、contentHidden、contentText、spinner */\nexport const switchStyles = css.create({\n track: { width: '2.25em', height: '1.25em', borderRadius: '_full', borderColor: 'transparent' },\n // 轨道里有文字:宽度随文字(两份文字叠在同一格里,取较宽的,切换时宽度不跳)\n trackWide: { width: '_full', minWidth: '2.25em' },\n trackOff: { backgroundColor: '_borderStrong' },\n // 滑块靠起始边,打开后移到结束边:用逻辑方向的外边距,从右到左排版自动反过来\n thumb: {\n display: 'grid',\n placeItems: 'center',\n justifySelf: 'start',\n width: '0.875em',\n height: '0.875em',\n marginInlineStart: '0.1875em',\n borderRadius: '_full',\n backgroundColor: '_background',\n boxShadow: '_sm',\n transition: `margin-inline-start ${t.durations.sm} ${t.easings.standard}`,\n },\n // 移到结束边:百分比相对整条轨道,轨道随文字加宽时同样贴边\n thumbOn: { marginInlineStart: 'calc(100% - 1.0625em)', backgroundColor: 'var(--tone-on-fill)' },\n // 用 flex 居中:按行内文字排时随外层的行高落在基线上,图标会比轨道中线偏下\n content: {\n gridArea: '1 / 1',\n justifySelf: 'stretch',\n alignSelf: 'center',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n },\n // 文字在滑块的另一侧\n contentOn: {\n paddingInlineStart: '0.5em',\n paddingInlineEnd: '1.375em',\n color: 'var(--tone-on-fill)',\n },\n contentOff: { paddingInlineStart: '1.375em', paddingInlineEnd: '0.5em', color: '_text' },\n contentHidden: { visibility: 'hidden' },\n // 字号缩在里层:外层的内边距按开关的字号算,给滑块留的位置才够\n contentText: {\n display: 'flex',\n alignItems: 'center',\n fontSize: '_xs',\n fontWeight: '_semibold',\n lineHeight: 1,\n },\n spinner: { width: '0.75em', height: '0.75em', color: 'var(--tone-fill)' },\n});\n\n/** 开关:立即生效的开 / 关 */\nexport const Switch = _component(\n ({\n _checked: checked = _bindable(false),\n disabled,\n readonly,\n required,\n invalid,\n size,\n tone,\n loading = false,\n checkedContent,\n uncheckedContent,\n id,\n propsRoot,\n propsControl,\n propsThumb,\n propsContent,\n propsContentText,\n propsSpinner,\n propsLabel,\n children,\n ...rest\n }: SwitchProps) => {\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const appearance = useChoiceAppearance(() => ({ size, tone }));\n // 很快完成的切换不闪加载指示;点击拦截、aria-busy 按真实的 loading\n const spinner = useDelayedLoading(() => loading);\n return () => {\n const state = control();\n const s = choiceParts(appearance(), { disabled: state.disabled, readonly: state.readonly });\n const wide = checkedContent != null || uncheckedContent != null;\n const content = (on: boolean, child: VNodeChild) => (\n <span\n {...mergeAttrs<'span'>(\n {\n sx: [\n switchStyles.content,\n on ? switchStyles.contentOn : switchStyles.contentOff,\n on !== checked && switchStyles.contentHidden,\n ],\n },\n propsContent,\n { 'aria-hidden': true },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: switchStyles.contentText }, propsContentText)}>\n {child}\n </span>\n </span>\n );\n return (\n <label\n {...mergeAttrs<'label'>(s.root, propsRoot)}\n data-state={checked ? 'checked' : 'unchecked'}\n data-disabled={state.disabled || undefined}\n data-readonly={state.readonly || undefined}\n data-loading={loading || undefined}\n >\n <span {...mergeAttrs<'span'>(s.control, propsControl)}>\n <input\n {...mergeAttrs<'input'>(\n {\n ...s.input,\n sx: [\n s.input.sx,\n focusRingStyles.tight,\n switchStyles.track,\n wide && switchStyles.trackWide,\n checked ? choiceInputStyles.checked : switchStyles.trackOff,\n state.invalid && choiceInputStyles.invalid,\n ],\n },\n rest,\n {\n type: 'checkbox',\n role: 'switch',\n id: state.id,\n checked,\n disabled: state.disabled,\n required: state.required,\n 'aria-invalid': state.invalid || undefined,\n 'aria-readonly': state.readonly || undefined,\n 'aria-describedby': state.describedBy,\n 'aria-busy': loading || undefined,\n // 切换中、只读时不接受切换:拦下 click,勾选状态就不变\n onClick: (event: MouseEvent) => {\n if (loading || state.readonly) event.preventDefault();\n },\n onChange: (event: Event) => {\n const target = event.target as HTMLInputElement;\n checked = target.checked;\n syncChecked([target], () => checked);\n },\n },\n )}\n />\n {wide && content(true, checkedContent)}\n {wide && content(false, uncheckedContent)}\n <span\n {...mergeAttrs<'span'>(\n {\n ...s.indicator,\n sx: [s.indicator.sx, switchStyles.thumb, checked && switchStyles.thumbOn],\n },\n propsThumb,\n )}\n >\n {spinner.value && (\n <Spinner\n {...mergePartProps<SpinnerProps>(\n { propsIcon: { sx: switchStyles.spinner } },\n propsSpinner,\n )}\n />\n )}\n </span>\n </span>\n {hasContent(children) && (\n <span {...mergeAttrs<'span'>(s.label, propsLabel)}>{children}</span>\n )}\n </label>\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 { PresetIconButtonProps } from '../base/CloseButton';
|
|
4
4
|
import { type TagProps } from '../base/Tag';
|