@zerodep-dev/vue-tsx-pro-ui 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base/Blockquote.d.ts +1 -1
- package/dist/base/Blockquote.js +1 -1
- package/dist/base/Blockquote.js.map +1 -1
- package/dist/base/ButtonGroup.d.ts +1 -1
- package/dist/base/ButtonGroup.js +1 -1
- package/dist/base/ButtonGroup.js.map +1 -1
- package/dist/base/Code.d.ts +1 -1
- package/dist/base/Code.js +1 -1
- package/dist/base/Code.js.map +1 -1
- package/dist/base/CodeBlock.d.ts +1 -1
- package/dist/base/CodeBlock.js +1 -1
- package/dist/base/CodeBlock.js.map +1 -1
- package/dist/base/CopyButton.d.ts +1 -1
- package/dist/base/CopyButton.js +1 -1
- package/dist/base/CopyButton.js.map +1 -1
- package/dist/base/Heading.d.ts +1 -1
- package/dist/base/Heading.js +1 -1
- package/dist/base/Heading.js.map +1 -1
- package/dist/base/Icon.d.ts +1 -1
- package/dist/base/Icon.js +1 -1
- package/dist/base/Icon.js.map +1 -1
- package/dist/base/Indicator.d.ts +1 -1
- package/dist/base/Indicator.js +1 -1
- package/dist/base/Indicator.js.map +1 -1
- package/dist/base/Kbd.d.ts +1 -1
- package/dist/base/Kbd.js +1 -1
- package/dist/base/Kbd.js.map +1 -1
- package/dist/base/Link.d.ts +1 -1
- package/dist/base/Link.js +1 -1
- package/dist/base/Link.js.map +1 -1
- package/dist/base/List.d.ts +1 -1
- package/dist/base/List.js +1 -1
- package/dist/base/List.js.map +1 -1
- package/dist/base/Mark.d.ts +1 -1
- package/dist/base/Mark.js +1 -1
- package/dist/base/Mark.js.map +1 -1
- package/dist/base/Spinner.d.ts +1 -1
- package/dist/base/Spinner.js +1 -1
- package/dist/base/Spinner.js.map +1 -1
- package/dist/base/StatusDot.d.ts +1 -1
- package/dist/base/StatusDot.js +1 -1
- package/dist/base/StatusDot.js.map +1 -1
- package/dist/base/Tag.d.ts +1 -1
- package/dist/base/Tag.js +1 -1
- package/dist/base/Tag.js.map +1 -1
- package/dist/base/Text.d.ts +1 -1
- package/dist/base/Text.js +1 -1
- package/dist/base/Text.js.map +1 -1
- package/dist/base/VisuallyHidden.d.ts +1 -1
- package/dist/base/VisuallyHidden.js +1 -1
- package/dist/base/VisuallyHidden.js.map +1 -1
- package/dist/base/badge-styles.d.ts +1 -1
- package/dist/base/badge-styles.js +1 -1
- package/dist/base/badge-styles.js.map +1 -1
- package/dist/base/button-core.d.ts +1 -1
- package/dist/base/button-core.js +1 -1
- package/dist/base/button-core.js.map +1 -1
- package/dist/charts/ChordChart.d.ts +1 -1
- package/dist/charts/ChordChart.js +1 -1
- package/dist/charts/ChordChart.js.map +1 -1
- package/dist/charts/DonutChart.d.ts +1 -1
- package/dist/charts/DonutChart.js +1 -1
- package/dist/charts/DonutChart.js.map +1 -1
- package/dist/charts/FunnelChart.d.ts +1 -1
- package/dist/charts/FunnelChart.js +1 -1
- package/dist/charts/FunnelChart.js.map +1 -1
- package/dist/charts/GraphChart.d.ts +1 -1
- package/dist/charts/GraphChart.js +1 -1
- package/dist/charts/GraphChart.js.map +1 -1
- package/dist/charts/MapChart.d.ts +1 -1
- package/dist/charts/MapChart.js +1 -1
- package/dist/charts/MapChart.js.map +1 -1
- package/dist/charts/RadarChart.d.ts +1 -1
- package/dist/charts/RadarChart.js +1 -1
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/SankeyChart.d.ts +1 -1
- package/dist/charts/SankeyChart.js +1 -1
- package/dist/charts/SankeyChart.js.map +1 -1
- package/dist/charts/TreemapChart.d.ts +1 -1
- package/dist/charts/TreemapChart.js +1 -1
- package/dist/charts/TreemapChart.js.map +1 -1
- package/dist/charts/XYChart.d.ts +1 -1
- package/dist/charts/XYChart.js +1 -1
- package/dist/charts/XYChart.js.map +1 -1
- package/dist/charts/frame.d.ts +1 -1
- package/dist/charts/frame.js +1 -1
- package/dist/charts/frame.js.map +1 -1
- package/dist/code-editor/CodeEditor.js +1 -1
- package/dist/code-editor/CodeEditor.js.map +1 -1
- package/dist/config/Provider.d.ts +1 -1
- package/dist/config/Provider.js +1 -1
- package/dist/config/Provider.js.map +1 -1
- package/dist/config/createUi.d.ts +1 -1
- package/dist/config/createUi.js +1 -1
- package/dist/config/createUi.js.map +1 -1
- package/dist/config/theme/coffee.d.ts +1 -1
- package/dist/config/theme/coffee.js +1 -1
- package/dist/config/theme/coffee.js.map +1 -1
- package/dist/config/theme/cyberpunk.d.ts +1 -1
- package/dist/config/theme/cyberpunk.js +1 -1
- package/dist/config/theme/cyberpunk.js.map +1 -1
- package/dist/config/theme/dark.d.ts +1 -1
- package/dist/config/theme/dark.js +1 -1
- package/dist/config/theme/dark.js.map +1 -1
- package/dist/config/theme/festive.d.ts +1 -1
- package/dist/config/theme/festive.js +1 -1
- package/dist/config/theme/festive.js.map +1 -1
- package/dist/config/theme/forest.d.ts +1 -1
- package/dist/config/theme/forest.js +1 -1
- package/dist/config/theme/forest.js.map +1 -1
- package/dist/config/theme/high-contrast.d.ts +1 -1
- package/dist/config/theme/high-contrast.js +1 -1
- package/dist/config/theme/high-contrast.js.map +1 -1
- package/dist/config/theme/lemon.d.ts +1 -1
- package/dist/config/theme/lemon.js +1 -1
- package/dist/config/theme/lemon.js.map +1 -1
- package/dist/config/theme/light.d.ts +1 -1
- package/dist/config/theme/light.js +1 -1
- package/dist/config/theme/light.js.map +1 -1
- package/dist/config/theme/midnight.d.ts +1 -1
- package/dist/config/theme/midnight.js +1 -1
- package/dist/config/theme/midnight.js.map +1 -1
- package/dist/config/theme/ocean.d.ts +1 -1
- package/dist/config/theme/ocean.js +1 -1
- package/dist/config/theme/ocean.js.map +1 -1
- package/dist/config/theme/paper.d.ts +1 -1
- package/dist/config/theme/paper.js +1 -1
- package/dist/config/theme/paper.js.map +1 -1
- package/dist/config/theme/sakura.d.ts +1 -1
- package/dist/config/theme/sakura.js +1 -1
- package/dist/config/theme/sakura.js.map +1 -1
- package/dist/config/theme/theme.js +1 -1
- package/dist/config/theme/theme.js.map +1 -1
- package/dist/config/theme/tokens.d.ts +1 -1
- package/dist/config/theme/tokens.js +1 -1
- package/dist/config/theme/tokens.js.map +1 -1
- package/dist/date/CalendarBoard.d.ts +1 -1
- package/dist/date/CalendarBoard.js +1 -1
- package/dist/date/CalendarBoard.js.map +1 -1
- package/dist/date/CalendarView.d.ts +1 -1
- package/dist/date/CalendarView.js +1 -1
- package/dist/date/CalendarView.js.map +1 -1
- package/dist/date/Countdown.d.ts +1 -1
- package/dist/date/Countdown.js +1 -1
- package/dist/date/Countdown.js.map +1 -1
- package/dist/date/DatePicker.d.ts +1 -1
- package/dist/date/DatePicker.js +1 -1
- package/dist/date/DatePicker.js.map +1 -1
- package/dist/date/DateRangePicker.d.ts +1 -1
- package/dist/date/DateRangePicker.js +1 -1
- package/dist/date/DateRangePicker.js.map +1 -1
- package/dist/date/DateSegmentGroup.d.ts +1 -1
- package/dist/date/DateSegmentGroup.js +1 -1
- package/dist/date/DateSegmentGroup.js.map +1 -1
- package/dist/date/QuarterCalendar.js +1 -1
- package/dist/date/QuarterCalendar.js.map +1 -1
- package/dist/date/SegmentedField.d.ts +1 -1
- package/dist/date/SegmentedField.js +1 -1
- package/dist/date/SegmentedField.js.map +1 -1
- package/dist/date/TimePicker.d.ts +1 -1
- package/dist/date/TimePicker.js +1 -1
- package/dist/date/TimePicker.js.map +1 -1
- package/dist/date/picker-popover.d.ts +1 -1
- package/dist/date/picker-popover.js +1 -1
- package/dist/date/picker-popover.js.map +1 -1
- package/dist/diagram/Diagram.d.ts +1 -1
- package/dist/diagram/Diagram.js +1 -1
- package/dist/diagram/Diagram.js.map +1 -1
- package/dist/diagram/DiagramControls.d.ts +1 -1
- package/dist/diagram/DiagramControls.js +1 -1
- package/dist/diagram/DiagramControls.js.map +1 -1
- package/dist/diagram/DiagramLanes.d.ts +1 -1
- package/dist/diagram/DiagramLanes.js +1 -1
- package/dist/diagram/DiagramLanes.js.map +1 -1
- package/dist/diagram/DiagramMinimap.d.ts +1 -1
- package/dist/diagram/DiagramMinimap.js +1 -1
- package/dist/diagram/DiagramMinimap.js.map +1 -1
- package/dist/diagram/DiagramNode.d.ts +1 -1
- package/dist/diagram/DiagramNode.js +1 -1
- package/dist/diagram/DiagramNode.js.map +1 -1
- package/dist/display/Accordion.d.ts +1 -1
- package/dist/display/Accordion.js +1 -1
- package/dist/display/Accordion.js.map +1 -1
- package/dist/display/AnimatedNumber.d.ts +1 -1
- package/dist/display/AnimatedNumber.js +1 -1
- package/dist/display/AnimatedNumber.js.map +1 -1
- package/dist/display/Avatar.d.ts +1 -1
- package/dist/display/Avatar.js +1 -1
- package/dist/display/Avatar.js.map +1 -1
- package/dist/display/AvatarGroup.d.ts +1 -1
- package/dist/display/AvatarGroup.js +1 -1
- package/dist/display/AvatarGroup.js.map +1 -1
- package/dist/display/Card.d.ts +1 -1
- package/dist/display/Card.js +1 -1
- package/dist/display/Card.js.map +1 -1
- package/dist/display/Checklist.d.ts +1 -1
- package/dist/display/Checklist.js +1 -1
- package/dist/display/Checklist.js.map +1 -1
- package/dist/display/Collapse.d.ts +1 -1
- package/dist/display/Collapse.js +1 -1
- package/dist/display/Collapse.js.map +1 -1
- package/dist/display/Descriptions.d.ts +1 -1
- package/dist/display/Descriptions.js +1 -1
- package/dist/display/Descriptions.js.map +1 -1
- package/dist/display/Ellipsis.d.ts +1 -1
- package/dist/display/Ellipsis.js +1 -1
- package/dist/display/Ellipsis.js.map +1 -1
- package/dist/display/FieldCompare.d.ts +1 -1
- package/dist/display/FieldCompare.js +1 -1
- package/dist/display/FieldCompare.js.map +1 -1
- package/dist/display/Gauge.d.ts +1 -1
- package/dist/display/Gauge.js +1 -1
- package/dist/display/Gauge.js.map +1 -1
- package/dist/display/Image.d.ts +1 -1
- package/dist/display/Image.js +1 -1
- package/dist/display/Image.js.map +1 -1
- package/dist/display/ItemList.d.ts +1 -1
- package/dist/display/ItemList.js +1 -1
- package/dist/display/ItemList.js.map +1 -1
- package/dist/display/Marquee.d.ts +1 -1
- package/dist/display/Marquee.js +1 -1
- package/dist/display/Marquee.js.map +1 -1
- package/dist/display/ProportionBar.d.ts +1 -1
- package/dist/display/ProportionBar.js +1 -1
- package/dist/display/ProportionBar.js.map +1 -1
- package/dist/display/Sortable.d.ts +1 -1
- package/dist/display/Sortable.js +1 -1
- package/dist/display/Sortable.js.map +1 -1
- package/dist/display/Sparkline.d.ts +1 -1
- package/dist/display/Sparkline.js +1 -1
- package/dist/display/Sparkline.js.map +1 -1
- package/dist/display/Stat.d.ts +1 -1
- package/dist/display/Stat.js +1 -1
- package/dist/display/Stat.js.map +1 -1
- package/dist/display/Timeline.d.ts +1 -1
- package/dist/display/Timeline.js +1 -1
- package/dist/display/Timeline.js.map +1 -1
- package/dist/display/Tree.d.ts +1 -1
- package/dist/display/Tree.js +1 -1
- package/dist/display/Tree.js.map +1 -1
- package/dist/display/VirtualList.d.ts +1 -1
- package/dist/display/VirtualList.js +1 -1
- package/dist/display/VirtualList.js.map +1 -1
- package/dist/display/Watermark.d.ts +1 -1
- package/dist/display/Watermark.js +1 -1
- package/dist/display/Watermark.js.map +1 -1
- package/dist/docs-kit/CodeGroup.d.ts +1 -1
- package/dist/docs-kit/CodeGroup.js +1 -1
- package/dist/docs-kit/CodeGroup.js.map +1 -1
- package/dist/docs-kit/CodePreview.d.ts +1 -1
- package/dist/docs-kit/CodePreview.js +1 -1
- package/dist/docs-kit/CodePreview.js.map +1 -1
- package/dist/docs-kit/ColorSwatch.d.ts +1 -1
- package/dist/docs-kit/ColorSwatch.js +1 -1
- package/dist/docs-kit/ColorSwatch.js.map +1 -1
- package/dist/docs-kit/PropsTable.d.ts +1 -1
- package/dist/docs-kit/PropsTable.js +1 -1
- package/dist/docs-kit/PropsTable.js.map +1 -1
- package/dist/feedback/Alert.d.ts +1 -1
- package/dist/feedback/Alert.js +1 -1
- package/dist/feedback/Alert.js.map +1 -1
- package/dist/feedback/Banner.d.ts +1 -1
- package/dist/feedback/Banner.js +1 -1
- package/dist/feedback/Banner.js.map +1 -1
- package/dist/feedback/Empty.d.ts +1 -1
- package/dist/feedback/Empty.js +1 -1
- package/dist/feedback/Empty.js.map +1 -1
- package/dist/feedback/LoadingBar.d.ts +1 -1
- package/dist/feedback/LoadingBar.js +1 -1
- package/dist/feedback/LoadingBar.js.map +1 -1
- package/dist/feedback/LoadingOverlay.d.ts +1 -1
- package/dist/feedback/LoadingOverlay.js +1 -1
- package/dist/feedback/LoadingOverlay.js.map +1 -1
- package/dist/feedback/Progress.d.ts +1 -1
- package/dist/feedback/Progress.js +1 -1
- package/dist/feedback/Progress.js.map +1 -1
- package/dist/feedback/Result.d.ts +1 -1
- package/dist/feedback/Result.js +1 -1
- package/dist/feedback/Result.js.map +1 -1
- package/dist/feedback/Skeleton.d.ts +1 -1
- package/dist/feedback/Skeleton.js +1 -1
- package/dist/feedback/Skeleton.js.map +1 -1
- package/dist/feedback/SkeletonText.d.ts +1 -1
- package/dist/feedback/SkeletonText.js +1 -1
- package/dist/feedback/SkeletonText.js.map +1 -1
- package/dist/feedback/Toast.d.ts +1 -1
- package/dist/feedback/Toast.js +1 -1
- package/dist/feedback/Toast.js.map +1 -1
- package/dist/form/Field.d.ts +1 -1
- package/dist/form/Field.js +1 -1
- package/dist/form/Field.js.map +1 -1
- package/dist/form/FormErrorSummary.d.ts +1 -1
- package/dist/form/FormErrorSummary.js +1 -1
- package/dist/form/FormErrorSummary.js.map +1 -1
- package/dist/form/FormSection.d.ts +1 -1
- package/dist/form/FormSection.js +1 -1
- package/dist/form/FormSection.js.map +1 -1
- package/dist/form/schemas.d.ts +1 -1
- package/dist/form/schemas.js +1 -1
- package/dist/form/schemas.js.map +1 -1
- package/dist/input/Cascader.d.ts +1 -1
- package/dist/input/Cascader.js +1 -1
- package/dist/input/Cascader.js.map +1 -1
- package/dist/input/CharacterCount.d.ts +1 -1
- package/dist/input/CharacterCount.js +1 -1
- package/dist/input/CharacterCount.js.map +1 -1
- package/dist/input/Checkbox.d.ts +1 -1
- package/dist/input/Checkbox.js +1 -1
- package/dist/input/Checkbox.js.map +1 -1
- package/dist/input/ColorField.d.ts +1 -1
- package/dist/input/ColorField.js +1 -1
- package/dist/input/ColorField.js.map +1 -1
- package/dist/input/Combobox.d.ts +1 -1
- package/dist/input/Combobox.js +1 -1
- package/dist/input/Combobox.js.map +1 -1
- package/dist/input/ConditionBuilder.d.ts +1 -1
- package/dist/input/ConditionBuilder.js +1 -1
- package/dist/input/ConditionBuilder.js.map +1 -1
- package/dist/input/ControlGroup.d.ts +1 -1
- package/dist/input/ControlGroup.js +1 -1
- package/dist/input/ControlGroup.js.map +1 -1
- package/dist/input/FileDrop.d.ts +1 -1
- package/dist/input/FileDrop.js +1 -1
- package/dist/input/FileDrop.js.map +1 -1
- package/dist/input/ListPopover.d.ts +1 -1
- package/dist/input/ListPopover.js +1 -1
- package/dist/input/ListPopover.js.map +1 -1
- package/dist/input/Listbox.d.ts +1 -1
- package/dist/input/Listbox.js +1 -1
- package/dist/input/Listbox.js.map +1 -1
- package/dist/input/Mentions.d.ts +1 -1
- package/dist/input/Mentions.js +1 -1
- package/dist/input/Mentions.js.map +1 -1
- package/dist/input/NumberRangeField.d.ts +1 -1
- package/dist/input/NumberRangeField.js +1 -1
- package/dist/input/NumberRangeField.js.map +1 -1
- package/dist/input/OtpField.d.ts +1 -1
- package/dist/input/OtpField.js +1 -1
- package/dist/input/OtpField.js.map +1 -1
- package/dist/input/PeoplePicker.js +1 -1
- package/dist/input/PeoplePicker.js.map +1 -1
- package/dist/input/PeoplePickerPanel.d.ts +1 -1
- package/dist/input/PeoplePickerPanel.js +1 -1
- package/dist/input/PeoplePickerPanel.js.map +1 -1
- package/dist/input/Radio.d.ts +1 -1
- package/dist/input/Radio.js +1 -1
- package/dist/input/Radio.js.map +1 -1
- package/dist/input/Rating.d.ts +1 -1
- package/dist/input/Rating.js +1 -1
- package/dist/input/Rating.js.map +1 -1
- package/dist/input/Select.d.ts +1 -1
- package/dist/input/Select.js +1 -1
- package/dist/input/Select.js.map +1 -1
- package/dist/input/SelectedTags.d.ts +1 -1
- package/dist/input/SelectedTags.js +1 -1
- package/dist/input/SelectedTags.js.map +1 -1
- package/dist/input/Slider.d.ts +1 -1
- package/dist/input/Slider.js +1 -1
- package/dist/input/Slider.js.map +1 -1
- package/dist/input/Switch.d.ts +1 -1
- package/dist/input/Switch.js +1 -1
- package/dist/input/Switch.js.map +1 -1
- package/dist/input/TagsInput.d.ts +1 -1
- package/dist/input/TagsInput.js +1 -1
- package/dist/input/TagsInput.js.map +1 -1
- package/dist/input/Textarea.d.ts +1 -1
- package/dist/input/Textarea.js +1 -1
- package/dist/input/Textarea.js.map +1 -1
- package/dist/input/ToggleGroup.d.ts +1 -1
- package/dist/input/ToggleGroup.js +1 -1
- package/dist/input/ToggleGroup.js.map +1 -1
- package/dist/input/Transfer.d.ts +1 -1
- package/dist/input/Transfer.js +1 -1
- package/dist/input/Transfer.js.map +1 -1
- package/dist/input/TreeSelect.d.ts +1 -1
- package/dist/input/TreeSelect.js +1 -1
- package/dist/input/TreeSelect.js.map +1 -1
- package/dist/input/Upload.d.ts +1 -1
- package/dist/input/Upload.js +1 -1
- package/dist/input/Upload.js.map +1 -1
- package/dist/input/choice-styles.d.ts +1 -1
- package/dist/input/choice-styles.js +1 -1
- package/dist/input/choice-styles.js.map +1 -1
- package/dist/input/control.d.ts +1 -1
- package/dist/input/control.js +1 -1
- package/dist/input/control.js.map +1 -1
- package/dist/layout/Affix.d.ts +1 -1
- package/dist/layout/Affix.js +1 -1
- package/dist/layout/Affix.js.map +1 -1
- package/dist/layout/AsideLayout.d.ts +1 -1
- package/dist/layout/AsideLayout.js +1 -1
- package/dist/layout/AsideLayout.js.map +1 -1
- package/dist/layout/BackTop.d.ts +1 -1
- package/dist/layout/BackTop.js +1 -1
- package/dist/layout/BackTop.js.map +1 -1
- package/dist/layout/Container.d.ts +1 -1
- package/dist/layout/Container.js +1 -1
- package/dist/layout/Container.js.map +1 -1
- package/dist/layout/Flex.d.ts +1 -1
- package/dist/layout/Flex.js +1 -1
- package/dist/layout/Flex.js.map +1 -1
- package/dist/layout/Grid.d.ts +1 -1
- package/dist/layout/Grid.js +1 -1
- package/dist/layout/Grid.js.map +1 -1
- package/dist/layout/PageScrollbar.d.ts +1 -1
- package/dist/layout/PageScrollbar.js +1 -1
- package/dist/layout/PageScrollbar.js.map +1 -1
- package/dist/layout/Prose.d.ts +1 -1
- package/dist/layout/Prose.js +1 -1
- package/dist/layout/Prose.js.map +1 -1
- package/dist/layout/ResizeHandle.d.ts +1 -1
- package/dist/layout/ResizeHandle.js +1 -1
- package/dist/layout/ResizeHandle.js.map +1 -1
- package/dist/layout/ScrollArea.d.ts +1 -1
- package/dist/layout/ScrollArea.js +1 -1
- package/dist/layout/ScrollArea.js.map +1 -1
- package/dist/layout/Separator.d.ts +1 -1
- package/dist/layout/Separator.js +1 -1
- package/dist/layout/Separator.js.map +1 -1
- package/dist/layout/Splitter.d.ts +1 -1
- package/dist/layout/Splitter.js +1 -1
- package/dist/layout/Splitter.js.map +1 -1
- package/dist/layout/ViewportFill.d.ts +1 -1
- package/dist/layout/ViewportFill.js +1 -1
- package/dist/layout/ViewportFill.js.map +1 -1
- package/dist/navigation/Breadcrumbs.d.ts +1 -1
- package/dist/navigation/Breadcrumbs.js +1 -1
- package/dist/navigation/Breadcrumbs.js.map +1 -1
- package/dist/navigation/NavBar.d.ts +1 -1
- package/dist/navigation/NavBar.js +1 -1
- package/dist/navigation/NavBar.js.map +1 -1
- package/dist/navigation/NavList.d.ts +1 -1
- package/dist/navigation/NavList.js +1 -1
- package/dist/navigation/NavList.js.map +1 -1
- package/dist/navigation/PageJump.d.ts +1 -1
- package/dist/navigation/PageJump.js +1 -1
- package/dist/navigation/PageJump.js.map +1 -1
- package/dist/navigation/PageSizeSelect.d.ts +1 -1
- package/dist/navigation/PageSizeSelect.js +1 -1
- package/dist/navigation/PageSizeSelect.js.map +1 -1
- package/dist/navigation/Pager.d.ts +1 -1
- package/dist/navigation/Pager.js +1 -1
- package/dist/navigation/Pager.js.map +1 -1
- package/dist/navigation/Pagination.d.ts +1 -1
- package/dist/navigation/Pagination.js +1 -1
- package/dist/navigation/Pagination.js.map +1 -1
- package/dist/navigation/PaginationBar.d.ts +1 -1
- package/dist/navigation/PaginationBar.js +1 -1
- package/dist/navigation/PaginationBar.js.map +1 -1
- package/dist/navigation/SkipLink.d.ts +1 -1
- package/dist/navigation/SkipLink.js +1 -1
- package/dist/navigation/SkipLink.js.map +1 -1
- package/dist/navigation/Steps.d.ts +1 -1
- package/dist/navigation/Steps.js +1 -1
- package/dist/navigation/Steps.js.map +1 -1
- package/dist/navigation/TableOfContents.d.ts +1 -1
- package/dist/navigation/TableOfContents.js +1 -1
- package/dist/navigation/TableOfContents.js.map +1 -1
- package/dist/navigation/Tabs.d.ts +1 -1
- package/dist/navigation/Tabs.js +1 -1
- package/dist/navigation/Tabs.js.map +1 -1
- package/dist/navigation/Toolbar.d.ts +1 -1
- package/dist/navigation/Toolbar.js +1 -1
- package/dist/navigation/Toolbar.js.map +1 -1
- package/dist/overlay/CommandPalette.d.ts +1 -1
- package/dist/overlay/CommandPalette.js +1 -1
- package/dist/overlay/CommandPalette.js.map +1 -1
- package/dist/overlay/Dialog.d.ts +1 -1
- package/dist/overlay/Dialog.js +1 -1
- package/dist/overlay/Dialog.js.map +1 -1
- package/dist/overlay/Drawer.d.ts +1 -1
- package/dist/overlay/Drawer.js +1 -1
- package/dist/overlay/Drawer.js.map +1 -1
- package/dist/overlay/HoverCard.d.ts +1 -1
- package/dist/overlay/HoverCard.js +1 -1
- package/dist/overlay/HoverCard.js.map +1 -1
- package/dist/overlay/Lightbox.d.ts +1 -1
- package/dist/overlay/Lightbox.js +1 -1
- package/dist/overlay/Lightbox.js.map +1 -1
- package/dist/overlay/Menu.d.ts +1 -1
- package/dist/overlay/Menu.js +1 -1
- package/dist/overlay/Menu.js.map +1 -1
- package/dist/overlay/Popconfirm.d.ts +1 -1
- package/dist/overlay/Popconfirm.js +1 -1
- package/dist/overlay/Popconfirm.js.map +1 -1
- package/dist/overlay/Popover.d.ts +1 -1
- package/dist/overlay/Popover.js +1 -1
- package/dist/overlay/Popover.js.map +1 -1
- package/dist/overlay/Tooltip.d.ts +1 -1
- package/dist/overlay/Tooltip.js +1 -1
- package/dist/overlay/Tooltip.js.map +1 -1
- package/dist/overlay/Tour.d.ts +1 -1
- package/dist/overlay/Tour.js +1 -1
- package/dist/overlay/Tour.js.map +1 -1
- package/dist/patterns/ActionBar.d.ts +1 -1
- package/dist/patterns/ActionBar.js +1 -1
- package/dist/patterns/ActionBar.js.map +1 -1
- package/dist/patterns/AppShell.d.ts +1 -1
- package/dist/patterns/AppShell.js +1 -1
- package/dist/patterns/AppShell.js.map +1 -1
- package/dist/patterns/AuthLayout.d.ts +2 -2
- package/dist/patterns/AuthLayout.js +2 -2
- package/dist/patterns/AuthLayout.js.map +1 -1
- package/dist/patterns/CommentThread.d.ts +1 -1
- package/dist/patterns/CommentThread.js +1 -1
- package/dist/patterns/CommentThread.js.map +1 -1
- package/dist/patterns/DataImport.d.ts +1 -1
- package/dist/patterns/DataImport.js +1 -1
- package/dist/patterns/DataImport.js.map +1 -1
- package/dist/patterns/FilterBar.d.ts +1 -1
- package/dist/patterns/FilterBar.js +1 -1
- package/dist/patterns/FilterBar.js.map +1 -1
- package/dist/patterns/KanbanBoard.d.ts +1 -1
- package/dist/patterns/KanbanBoard.js +1 -1
- package/dist/patterns/KanbanBoard.js.map +1 -1
- package/dist/patterns/NotificationCenter.d.ts +1 -1
- package/dist/patterns/NotificationCenter.js +1 -1
- package/dist/patterns/NotificationCenter.js.map +1 -1
- package/dist/patterns/QueryTable.d.ts +1 -1
- package/dist/patterns/QueryTable.js +1 -1
- package/dist/patterns/QueryTable.js.map +1 -1
- package/dist/patterns/SlideCaptcha.d.ts +1 -1
- package/dist/patterns/SlideCaptcha.js +1 -1
- package/dist/patterns/SlideCaptcha.js.map +1 -1
- package/dist/patterns/StepsForm.d.ts +1 -1
- package/dist/patterns/StepsForm.js +1 -1
- package/dist/patterns/StepsForm.js.map +1 -1
- package/dist/table/ColumnHeaderActions.d.ts +1 -1
- package/dist/table/ColumnHeaderActions.js +1 -1
- package/dist/table/ColumnHeaderActions.js.map +1 -1
- package/dist/table/ColumnSettings.d.ts +1 -1
- package/dist/table/ColumnSettings.js +1 -1
- package/dist/table/ColumnSettings.js.map +1 -1
- package/dist/table/ColumnTable.d.ts +1 -1
- package/dist/table/ColumnTable.js +1 -1
- package/dist/table/ColumnTable.js.map +1 -1
- package/dist/table/DataTableView.d.ts +1 -1
- package/dist/table/DataTableView.js +1 -1
- package/dist/table/DataTableView.js.map +1 -1
- package/dist/table/PivotTable.d.ts +1 -1
- package/dist/table/PivotTable.js +1 -1
- package/dist/table/PivotTable.js.map +1 -1
- package/dist/table/SelectionBar.d.ts +1 -1
- package/dist/table/SelectionBar.js +1 -1
- package/dist/table/SelectionBar.js.map +1 -1
- package/dist/table/Table.d.ts +1 -1
- package/dist/table/Table.js +1 -1
- package/dist/table/Table.js.map +1 -1
- package/dist/table/TreeDataTable.d.ts +1 -1
- package/dist/table/TreeDataTable.js +1 -1
- package/dist/table/TreeDataTable.js.map +1 -1
- package/dist/table/table-styles.d.ts +1 -1
- package/dist/table/table-styles.js +1 -1
- package/dist/table/table-styles.js.map +1 -1
- package/dist/theme-customize/ThemeCustomizer.d.ts +1 -1
- package/dist/theme-customize/ThemeCustomizer.js +1 -1
- package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
- package/dist/theme-customize/ThemeThumbnail.d.ts +1 -1
- package/dist/theme-customize/ThemeThumbnail.js +1 -1
- package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
- package/dist/theme-customize/design-tokens.js +1 -1
- package/dist/theme-customize/design-tokens.js.map +1 -1
- package/dist/three/core/EffectSurface.d.ts +1 -1
- package/dist/three/core/EffectSurface.js +1 -1
- package/dist/three/core/EffectSurface.js.map +1 -1
- package/dist/three/core/ThreeCanvas.d.ts +1 -1
- package/dist/three/core/ThreeCanvas.js +1 -1
- package/dist/three/core/ThreeCanvas.js.map +1 -1
- package/dist/three/effects/Confetti.d.ts +1 -1
- package/dist/three/effects/Confetti.js +1 -1
- package/dist/three/effects/Confetti.js.map +1 -1
- package/dist/three/globe/Globe.d.ts +1 -1
- package/dist/three/globe/Globe.js +1 -1
- package/dist/three/globe/Globe.js.map +1 -1
- package/dist/three/model/ModelViewer.d.ts +1 -1
- package/dist/three/model/ModelViewer.js +1 -1
- package/dist/three/model/ModelViewer.js.map +1 -1
- package/dist/utils/dom/floating.d.ts +1 -1
- package/dist/utils/dom/floating.js +1 -1
- package/dist/utils/dom/floating.js.map +1 -1
- package/dist/utils/dom/ripple.d.ts +1 -1
- package/dist/utils/dom/ripple.js +1 -1
- package/dist/utils/dom/ripple.js.map +1 -1
- package/dist/utils/props.js +1 -1
- package/dist/utils/props.js.map +1 -1
- package/dist/utils/style/attached.d.ts +1 -1
- package/dist/utils/style/attached.js +1 -1
- package/dist/utils/style/attached.js.map +1 -1
- package/dist/utils/style/item-styles.d.ts +1 -1
- package/dist/utils/style/item-styles.js +1 -1
- package/dist/utils/style/item-styles.js.map +1 -1
- package/dist/utils/style/markers.d.ts +1 -1
- package/dist/utils/style/markers.js +1 -1
- package/dist/utils/style/markers.js.map +1 -1
- package/dist/utils/style/shimmer.d.ts +1 -1
- package/dist/utils/style/shimmer.js +1 -1
- package/dist/utils/style/shimmer.js.map +1 -1
- package/dist/utils/style/styles.d.ts +1 -1
- package/dist/utils/style/styles.js +1 -1
- package/dist/utils/style/styles.js.map +1 -1
- package/dist/utils/style/swatch-styles.d.ts +1 -1
- package/dist/utils/style/swatch-styles.js +1 -1
- package/dist/utils/style/swatch-styles.js.map +1 -1
- package/dist/utils/style/tone-styles.d.ts +1 -1
- package/dist/utils/style/tone-styles.js +1 -1
- package/dist/utils/style/tone-styles.js.map +1 -1
- package/dist/utils/style/transitions.d.ts +1 -1
- package/dist/utils/style/transitions.js +1 -1
- package/dist/utils/style/transitions.js.map +1 -1
- package/dist/utils/style/typography.d.ts +1 -1
- package/dist/utils/style/typography.js +1 -1
- package/dist/utils/style/typography.js.map +1 -1
- package/dist/utils/style/vars.d.ts +1 -1
- package/dist/utils/style/vars.js +1 -1
- package/dist/utils/style/vars.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeSelect.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_ref","_vue_shallowRef","_vue_computed","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/input/TreeSelect.tsx"],"sourcesContent":["/**\n * 树形下拉选择:触发框同 Select,弹出的是一棵树(组织机构、产品结构、物料分类)。单选选一个节点,多选勾选(父子联动)。\n *\n * <TreeSelect\n * items={orgs}\n * getKey={(org) => org.id}\n * getLabel={(org) => org.name}\n * getChildren={(org) => org.children}\n * _value={orgId}\n * searchable\n * />\n * <TreeSelect … selectionMode=\"multiple\" _value={teamIds} /> 勾选:勾上父节点就是整枝\n * <TreeSelect … selectionMode=\"multiple\" checkedStrategy=\"child\" maxTagCount=\"responsive\" />\n *\n * - 单选:点节点或 Enter 选中并关闭;多选:空格或点勾选框,勾上父节点会勾上它的子孙,子节点全勾上时父节点也勾上。\n * value 按 checkedStrategy 放勾上的节点:全部(默认)、整枝时只放父节点、只放叶子(checkedByStrategy)。\n * - 多选的标签同 Select(SelectedTags):排在触发按钮前面,可移除(取消整枝),maxTagCount 收起,Backspace 移除最后一个。\n * 标签只列最上层的整枝(勾上了“研发中心”就不再列它下面的每个组);checkedStrategy=\"child\" 时列叶子。\n * - searchable:弹出层顶部的搜索框,按节点文字过滤,命中节点的祖先一起显示并展开;↓ 从搜索框进到树里。\n * 给 load 时由服务端搜索:打开时与输入停下 300 ms 后按搜索词请求,返回命中的节点连同祖先,结果全部展开\n * (remote-items.ts,同 Select);自己管请求时写 _search={keyword}、filter={false}。\n * - 打开后焦点在树上(或搜索框里),键盘同 Tree;Esc 关闭并把焦点还给触发按钮。懒加载同 Tree 的 loadChildren。\n * - 已选节点的文字从已加载的树里找,远程搜索换掉的按见过的文字显示;从没见过的(懒加载还没取回来)显示成 key。\n *\n * 部件:Root(外壳)、Tags(多选时的那排标签)、Tag、Trigger(button,主元素)、Value、Clear、Chevron、Popover、\n * Search(TextField)、Tree。\n */\nimport { ChevronDown, 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 } 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 } from '../config/context';\nimport { Tree, type TreeProps } from '../display/Tree';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { selectedValues, type SelectionModes } from '../utils/data/selection';\nimport {\n checkedByStrategy,\n indexTree,\n toggleChecked,\n type CheckStrategies,\n} from '../utils/data/tree';\nimport {\n anchoredPanelSx,\n floatingStyles,\n useAnchoredPopover,\n type FloatingPlacement,\n} from '../utils/dom/floating';\nimport { openSetter, type OpenChangeProps } from '../utils/dom/open-change';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { disclosureStyles } from '../utils/style/transitions';\nimport {\n controlClear,\n controlIcon,\n controlParts,\n clickOnShell,\n focusOnShell,\n useControlAppearance,\n type ControlIconOptions,\n type ControlOptions,\n} from './control';\nimport { listPopoverStyles } from './ListPopover';\nimport { useRemoteItems, type OptionsLoader } from './remote-items';\nimport { selectStyles, type SelectManaged } from './Select';\nimport { SelectedTags, type SelectedTagsProps } from './SelectedTags';\nimport { TextField, type TextFieldProps } from './TextField';\n\n/** 未声明的属性落到触发按钮(主元素)上,外壳用 propsRoot */\nexport interface TreeSelectProps<T>\n extends PartProps<'button', SelectManaged>, ControlOptions, ControlIconOptions, OpenChangeProps {\n /** 顶层节点;有 load 时是第一次加载之前的树(编辑页放上已选节点的那一枝) */\n items?: readonly T[];\n /** 节点的 key,整棵树里唯一:也是选中后写回的值 */\n getKey: (node: T) => string;\n /** 节点的文字 */\n getLabel: (node: T) => string;\n /** 子节点;叶子或还没加载时 undefined */\n getChildren: (node: T) => readonly T[] | undefined;\n /** 有没有子节点(懒加载时子节点还没取回来也算有) */\n hasChildren?: (node: T) => boolean;\n /** 展开还没有子节点的节点时取回来(返回 Promise 时显示加载中) */\n loadChildren?: (node: T) => Promise<unknown> | void;\n /** 不能选的节点(只能展开,如只能选到部门、不能选公司时) */\n isDisabled?: (node: T) => boolean;\n /** 单选(默认)或多选(勾选,父子联动) */\n selectionMode?: keyof SelectionModes;\n /** 单选时是选中节点的 key(没有时 null),多选时是勾上的节点(按 checkedStrategy):父级写 _value={x} */\n _value?: string | string[] | null;\n /**\n * 多选时 value 里放哪些勾上的节点(同 Ant Design 的 showCheckedStrategy):all 全部(默认);\n * parent 父节点全勾上时只放父节点(提交“整个部门”);child 只放叶子(提交“具体的人”)\n */\n checkedStrategy?: keyof CheckStrategies;\n /** 多选时触发框里最多显示几个标签,其余收进“+N”;'responsive' 时排成一行、按宽度放 */\n maxTagCount?: number | 'responsive';\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 | ((node: T, query: string) => boolean);\n /** 搜索框里的文字:打开时清空;父级写 _search={x} 拿到它(自己发请求时) */\n _search?: string;\n /** 远程搜索:打开时与搜索词停下 300 ms 后调用,返回命中的节点连同祖先(顶层节点),结果代替 items */\n load?: OptionsLoader<T>;\n /** 表单提交时的 name(用隐藏的 input) */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、能看到已选的内容,不能打开、不能清空 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\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 /** 搜索框的部件属性(searchable 时) */\n propsSearch?: Partial<TextFieldProps>;\n /** 树的部件属性 */\n propsTree?: Partial<TreeProps<T>>;\n}\n\n/** TreeSelect 的样式:tree */\nexport const treeSelectStyles = css.create({\n // 树的滚动区域占满弹出层剩下的高度(最大高度由定位写在弹出层上)\n tree: { flexGrow: 1, minHeight: 0 },\n // 弹出层比触发框窄时也放得下几层缩进\n panel: { minWidth: '16em' },\n});\n\n/** 树形下拉选择:触发框 + 弹出的树,单选或勾选,可搜索 */\nexport const TreeSelect = _component(\n <T,>({\n items = [],\n getKey,\n getLabel,\n getChildren,\n hasChildren,\n loadChildren,\n isDisabled,\n selectionMode = 'single',\n checkedStrategy = 'all',\n maxTagCount,\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 name,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n id,\n icon,\n propsRoot,\n propsIcon,\n propsValue,\n propsTag,\n propsTags,\n propsClear,\n propsChevron,\n propsPopover,\n propsSearch,\n propsTree,\n ...rest\n }: TreeSelectProps<T>) => {\n const lang = useLang();\n const treeId = useId();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const multiple = () => selectionMode === 'multiple';\n const remote = useRemoteItems({\n load: () => load,\n query: () => search,\n open: () => open,\n items: () => items,\n });\n let expanded = _state<string[]>([]);\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 // 已加载的整棵树:key → 节点与父节点,查已选的文字、搜索时找祖先都用它\n const nodes = _derived.by(() => {\n const map = new Map<string, { node: T; parent: string | undefined }>();\n const visit = (level: readonly T[], parent: string | undefined) => {\n for (const node of level) {\n const key = getKey(node);\n map.set(key, { node, parent });\n visit(getChildren(node) ?? [], key);\n }\n };\n visit(remote.items(), undefined);\n return map;\n });\n // 见过的节点文字:远程搜索换掉了已选的节点,触发框里仍显示它的文字\n const seenLabels = new Map<string, string>();\n watch(\n () => nodes,\n (map) => {\n for (const [key, { node }] of map) seenLabels.set(key, getLabel(node));\n },\n { immediate: true },\n );\n\n // 本地搜索交给 Tree 的 filter(命中的节点与祖先、展开祖先、命中的加粗);\n // 有 load 或 filter={false} 时结果已经是服务端筛好的,不再过滤\n const treeFilter = () => {\n const text = search.trim();\n if (!searchable || !text || load || filter === false) return undefined;\n return filter ? (node: T) => filter(node, text) : text;\n };\n // 服务端搜索的结果全部展开(只有命中的节点与它们的祖先);清空搜索回到自己展开的状态\n const remoteResults = () => !!load && !!search.trim();\n const shownExpanded = () => (remoteResults() ? [...nodes.keys()] : expanded);\n\n const values = () => selectedValues(value);\n // 勾选联动要看到折叠着的节点\n const index = _derived.by(() =>\n indexTree(remote.items(), { getKey: (node) => getKey(node), getChildren }),\n );\n /** 按取法整理勾上的节点:已加载的按树的顺序与父子关系,还没加载(或远程搜索换掉了)的原样跟在后面 */\n const byStrategy = (keys: readonly string[], strategy: keyof CheckStrategies) => [\n ...checkedByStrategy(index, keys, strategy),\n ...keys.filter((key) => !index.parents.has(key)),\n ];\n /** 勾选变了(树、移除标签):按 checkedStrategy 写回,还没加载的已选节点保留 */\n const setChecked = (checked: readonly string[]) => {\n const unknown = values().filter((key) => !index.parents.has(key));\n value = [...checkedByStrategy(index, checked, checkedStrategy), ...unknown];\n };\n /** 触发框里显示的节点:多选时只列最上层的整枝(父节点也勾上了的不重复列),child 时列叶子 */\n const displayKeys = () =>\n multiple()\n ? byStrategy(values(), checkedStrategy === 'child' ? 'child' : 'parent')\n : values();\n\n /** 移除一个标签:取消整枝 */\n function remove(key: string) {\n setChecked(toggleChecked(index, values(), key));\n }\n const labelOf = (key: string) => {\n const found = nodes.get(key);\n return found ? getLabel(found.node) : (seenLabels.get(key) ?? key);\n };\n\n function show(event?: Event) {\n search = '';\n // 打开时展开已选节点的祖先:已选的看得见\n const ancestors = new Set(expanded);\n for (const key of values()) {\n for (let at = nodes.get(key)?.parent; at !== undefined; at = nodes.get(at)?.parent) {\n ancestors.add(at);\n }\n }\n expanded = [...ancestors];\n setOpen(true, 'trigger', event);\n }\n\n function clear() {\n value = multiple() ? [] : null;\n trigger?.focus();\n }\n\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 // 打开后焦点进搜索框或树;关闭时焦点还在弹层里(Esc、选中、点外面)就还给触发按钮\n function onPanelToggle(event: ToggleEvent) {\n onToggle(event);\n if (event.newState === 'open') {\n const target = searchable\n ? panel?.querySelector<HTMLElement>('input[type=\"search\"]')\n : panel?.querySelector<HTMLElement>('[role=\"tree\"]');\n target?.focus();\n return;\n }\n const active = document.activeElement;\n if (!active || active === document.body || panel?.contains(active)) trigger?.focus();\n }\n\n function onTriggerKeydown(event: KeyboardEvent) {\n const state = control();\n if (state.disabled || state.readonly) return;\n // 多选:Backspace 移除最后一个标签(同 Select)\n if (event.key === 'Backspace' && multiple()) {\n event.preventDefault();\n const last = displayKeys().at(-1);\n if (last !== undefined) remove(last);\n return;\n }\n if (!open && (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n show(event);\n }\n }\n\n // 搜索框里 ↓ 进到树;Tab 关闭后照常移到下一个\n function onSearchKeydown(event: KeyboardEvent) {\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n panel?.querySelector<HTMLElement>('[role=\"tree\"]')?.focus();\n }\n }\n\n /** 树的属性(单选、多选共用):本地搜索时带上 filter */\n const treeProps = (labelledBy: string | undefined) =>\n mergePartProps<TreeProps<T>>(\n {\n items: remote.items(),\n getKey,\n getLabel,\n getChildren,\n hasChildren,\n filter: treeFilter(),\n loadChildren,\n loading: remote.loading(),\n empty: remote.failure() ?? (search.trim() ? lang.selectNoMatch : undefined),\n isDisabled,\n propsScrollArea: { sx: treeSelectStyles.tree },\n 'aria-labelledby': labelledBy,\n 'aria-label': labelledBy ? undefined : rest['aria-label'],\n },\n propsTree,\n { id: treeId },\n );\n\n // 单选:选中就关闭(树的 selected 里已按 select 关过;父级改 value 时也关,不通知)\n watch(\n () => value,\n () => {\n if (!multiple() && open) open = false;\n },\n );\n\n return () => {\n const state = control();\n const s = controlParts(appearance(), state);\n const off = state.disabled;\n const locked = off || state.readonly;\n const shownKeys = displayKeys();\n // 多选:触发按钮前面一排标签,按钮里只留给读屏的文字(同 Select)\n const tagged = multiple() && shownKeys.length > 0;\n const shown =\n shownKeys.length === 0 ? (\n <span {...css.attrs(selectStyles.placeholder)}>\n {placeholder ?? lang.selectPlaceholder}\n </span>\n ) : tagged ? (\n <span {...css.attrs(visuallyHiddenStyles.hidden)}>\n {lang.selectSummary(shownKeys.map(labelOf))}\n </span>\n ) : (\n labelOf(shownKeys[0]!)\n );\n return (\n <>\n <div\n {...mergeAttrs<'div'>({ ...s.root, sx: [s.root.sx, selectStyles.root] }, propsRoot, {\n ref: _toRef(shell),\n onPointerdown: off ? undefined : focusOnShell(() => trigger),\n onClick:\n off || state.readonly\n ? undefined\n : clickOnShell(\n () => trigger,\n (event) => (open ? setOpen(false, 'trigger', event) : show(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 {tagged && (\n <SelectedTags\n {...mergePartProps<SelectedTagsProps>(\n {\n tags: shownKeys.map((key) => ({ value: key, label: labelOf(key) })),\n maxTagCount,\n onRemove: locked ? undefined : remove,\n propsTag,\n },\n propsTags,\n )}\n />\n )}\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': 'tree',\n 'aria-expanded': open,\n 'aria-controls': treeId,\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 trigger?.focus();\n if (locked) return;\n if (open) setOpen(false, 'trigger', event);\n else show(event);\n },\n onKeydown: onTriggerKeydown,\n },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: selectStyles.value }, propsValue)}>{shown}</span>\n </button>\n {clearable && shownKeys.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 <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n anchoredPanelSx(appearance().size),\n floatingStyles.scrollPanel,\n listPopoverStyles.panel,\n treeSelectStyles.panel,\n ],\n },\n propsPopover,\n { ref: _toRef(panel), popover: 'auto', onToggle: onPanelToggle },\n )}\n >\n {searchable && (\n <div {...css.attrs(listPopoverStyles.header)}>\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={treeId}\n onKeydown={onSearchKeydown}\n />\n </div>\n )}\n {open &&\n (multiple() ? (\n <Tree\n {...treeProps(state.labelledBy)}\n checkable\n _checked={[...values()]}\n onUpdate:_checked={(next: string[]) => setChecked(next)}\n _expanded={shownExpanded()}\n onUpdate:_expanded={(next: string[]) =>\n (expanded = remoteResults() ? expanded : next)\n }\n />\n ) : (\n <Tree\n {...treeProps(state.labelledBy)}\n selectionMode=\"single\"\n _selected={[...values()]}\n onUpdate:_selected={(next: string[]) => {\n if (next.length) value = next[0];\n setOpen(false, 'select');\n }}\n _expanded={shownExpanded()}\n onUpdate:_expanded={(next: string[]) =>\n (expanded = remoteResults() ? expanded : next)\n }\n />\n ))}\n </div>\n </>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TreeSelect.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_ref","_vue_shallowRef","_vue_computed","_createVNode","_Fragment","_mergeProps"],"sources":["../../src/input/TreeSelect.tsx"],"sourcesContent":["/**\n * 树形下拉选择:触发框同 Select,弹出的是一棵树(组织机构、产品结构、物料分类)。单选选一个节点,多选勾选(父子联动)。\n *\n * <TreeSelect\n * items={orgs}\n * getKey={(org) => org.id}\n * getLabel={(org) => org.name}\n * getChildren={(org) => org.children}\n * _value={orgId}\n * searchable\n * />\n * <TreeSelect … selectionMode=\"multiple\" _value={teamIds} /> 勾选:勾上父节点就是整枝\n * <TreeSelect … selectionMode=\"multiple\" checkedStrategy=\"child\" maxTagCount=\"responsive\" />\n *\n * - 单选:点节点或 Enter 选中并关闭;多选:空格或点勾选框,勾上父节点会勾上它的子孙,子节点全勾上时父节点也勾上。\n * value 按 checkedStrategy 放勾上的节点:全部(默认)、整枝时只放父节点、只放叶子(checkedByStrategy)。\n * - 多选的标签同 Select(SelectedTags):排在触发按钮前面,可移除(取消整枝),maxTagCount 收起,Backspace 移除最后一个。\n * 标签只列最上层的整枝(勾上了“研发中心”就不再列它下面的每个组);checkedStrategy=\"child\" 时列叶子。\n * - searchable:弹出层顶部的搜索框,按节点文字过滤,命中节点的祖先一起显示并展开;↓ 从搜索框进到树里。\n * 给 load 时由服务端搜索:打开时与输入停下 300 ms 后按搜索词请求,返回命中的节点连同祖先,结果全部展开\n * (remote-items.ts,同 Select);自己管请求时写 _search={keyword}、filter={false}。\n * - 打开后焦点在树上(或搜索框里),键盘同 Tree;Esc 关闭并把焦点还给触发按钮。懒加载同 Tree 的 loadChildren。\n * - 已选节点的文字从已加载的树里找,远程搜索换掉的按见过的文字显示;从没见过的(懒加载还没取回来)显示成 key。\n *\n * 部件:Root(外壳)、Tags(多选时的那排标签)、Tag、Trigger(button,主元素)、Value、Clear、Chevron、Popover、\n * Search(TextField)、Tree。\n */\nimport { ChevronDown, 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 } 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 } from '../config/context';\nimport { Tree, type TreeProps } from '../display/Tree';\nimport { useFieldControl } from '../form/Field';\nimport { FormValue } from '../form/FormValue';\nimport { selectedValues, type SelectionModes } from '../utils/data/selection';\nimport {\n checkedByStrategy,\n indexTree,\n toggleChecked,\n type CheckStrategies,\n} from '../utils/data/tree';\nimport {\n anchoredPanelSx,\n floatingStyles,\n useAnchoredPopover,\n type FloatingPlacement,\n} from '../utils/dom/floating';\nimport { openSetter, type OpenChangeProps } from '../utils/dom/open-change';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { disclosureStyles } from '../utils/style/transitions';\nimport {\n controlClear,\n controlIcon,\n controlParts,\n clickOnShell,\n focusOnShell,\n useControlAppearance,\n type ControlIconOptions,\n type ControlOptions,\n} from './control';\nimport { listPopoverStyles } from './ListPopover';\nimport { useRemoteItems, type OptionsLoader } from './remote-items';\nimport { selectStyles, type SelectManaged } from './Select';\nimport { SelectedTags, type SelectedTagsProps } from './SelectedTags';\nimport { TextField, type TextFieldProps } from './TextField';\n\n/** 未声明的属性落到触发按钮(主元素)上,外壳用 propsRoot */\nexport interface TreeSelectProps<T>\n extends PartProps<'button', SelectManaged>, ControlOptions, ControlIconOptions, OpenChangeProps {\n /** 顶层节点;有 load 时是第一次加载之前的树(编辑页放上已选节点的那一枝) */\n items?: readonly T[];\n /** 节点的 key,整棵树里唯一:也是选中后写回的值 */\n getKey: (node: T) => string;\n /** 节点的文字 */\n getLabel: (node: T) => string;\n /** 子节点;叶子或还没加载时 undefined */\n getChildren: (node: T) => readonly T[] | undefined;\n /** 有没有子节点(懒加载时子节点还没取回来也算有) */\n hasChildren?: (node: T) => boolean;\n /** 展开还没有子节点的节点时取回来(返回 Promise 时显示加载中) */\n loadChildren?: (node: T) => Promise<unknown> | void;\n /** 不能选的节点(只能展开,如只能选到部门、不能选公司时) */\n isDisabled?: (node: T) => boolean;\n /** 单选(默认)或多选(勾选,父子联动) */\n selectionMode?: keyof SelectionModes;\n /** 单选时是选中节点的 key(没有时 null),多选时是勾上的节点(按 checkedStrategy):父级写 _value={x} */\n _value?: string | string[] | null;\n /**\n * 多选时 value 里放哪些勾上的节点(同 Ant Design 的 showCheckedStrategy):all 全部(默认);\n * parent 父节点全勾上时只放父节点(提交“整个部门”);child 只放叶子(提交“具体的人”)\n */\n checkedStrategy?: keyof CheckStrategies;\n /** 多选时触发框里最多显示几个标签,其余收进“+N”;'responsive' 时排成一行、按宽度放 */\n maxTagCount?: number | 'responsive';\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 | ((node: T, query: string) => boolean);\n /** 搜索框里的文字:打开时清空;父级写 _search={x} 拿到它(自己发请求时) */\n _search?: string;\n /** 远程搜索:打开时与搜索词停下 300 ms 后调用,返回命中的节点连同祖先(顶层节点),结果代替 items */\n load?: OptionsLoader<T>;\n /** 表单提交时的 name(用隐藏的 input) */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:能聚焦、能看到已选的内容,不能打开、不能清空 */\n readonly?: boolean;\n /** 必填 */\n required?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\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 /** 搜索框的部件属性(searchable 时) */\n propsSearch?: Partial<TextFieldProps>;\n /** 树的部件属性 */\n propsTree?: Partial<TreeProps<T>>;\n}\n\n/** TreeSelect 的样式:tree */\nexport const treeSelectStyles = css.create({\n // 树的滚动区域占满弹出层剩下的高度(最大高度由定位写在弹出层上)\n tree: { flexGrow: 1, minHeight: 0 },\n // 弹出层比触发框窄时也放得下几层缩进\n panel: { minWidth: '16em' },\n});\n\n/** 树形下拉选择:触发框 + 弹出的树,单选或勾选,可搜索 */\nexport const TreeSelect = _component(\n <T,>({\n items = [],\n getKey,\n getLabel,\n getChildren,\n hasChildren,\n loadChildren,\n isDisabled,\n selectionMode = 'single',\n checkedStrategy = 'all',\n maxTagCount,\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 name,\n variant,\n size,\n radius,\n disabled,\n readonly,\n required,\n invalid,\n id,\n icon,\n propsRoot,\n propsIcon,\n propsValue,\n propsTag,\n propsTags,\n propsClear,\n propsChevron,\n propsPopover,\n propsSearch,\n propsTree,\n ...rest\n }: TreeSelectProps<T>) => {\n const lang = useLang();\n const treeId = useId();\n const appearance = useControlAppearance(() => ({ variant, size, radius }));\n const control = useFieldControl(() => ({ id, invalid, required, disabled, readonly }));\n const multiple = () => selectionMode === 'multiple';\n const remote = useRemoteItems({\n load: () => load,\n query: () => search,\n open: () => open,\n items: () => items,\n });\n let expanded = _state<string[]>([]);\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 // 已加载的整棵树:key → 节点与父节点,查已选的文字、搜索时找祖先都用它\n const nodes = _derived.by(() => {\n const map = new Map<string, { node: T; parent: string | undefined }>();\n const visit = (level: readonly T[], parent: string | undefined) => {\n for (const node of level) {\n const key = getKey(node);\n map.set(key, { node, parent });\n visit(getChildren(node) ?? [], key);\n }\n };\n visit(remote.items(), undefined);\n return map;\n });\n // 见过的节点文字:远程搜索换掉了已选的节点,触发框里仍显示它的文字\n const seenLabels = new Map<string, string>();\n watch(\n () => nodes,\n (map) => {\n for (const [key, { node }] of map) seenLabels.set(key, getLabel(node));\n },\n { immediate: true },\n );\n\n // 本地搜索交给 Tree 的 filter(命中的节点与祖先、展开祖先、命中的加粗);\n // 有 load 或 filter={false} 时结果已经是服务端筛好的,不再过滤\n const treeFilter = () => {\n const text = search.trim();\n if (!searchable || !text || load || filter === false) return undefined;\n return filter ? (node: T) => filter(node, text) : text;\n };\n // 服务端搜索的结果全部展开(只有命中的节点与它们的祖先);清空搜索回到自己展开的状态\n const remoteResults = () => !!load && !!search.trim();\n const shownExpanded = () => (remoteResults() ? [...nodes.keys()] : expanded);\n\n const values = () => selectedValues(value);\n // 勾选联动要看到折叠着的节点\n const index = _derived.by(() =>\n indexTree(remote.items(), { getKey: (node) => getKey(node), getChildren }),\n );\n /** 按取法整理勾上的节点:已加载的按树的顺序与父子关系,还没加载(或远程搜索换掉了)的原样跟在后面 */\n const byStrategy = (keys: readonly string[], strategy: keyof CheckStrategies) => [\n ...checkedByStrategy(index, keys, strategy),\n ...keys.filter((key) => !index.parents.has(key)),\n ];\n /** 勾选变了(树、移除标签):按 checkedStrategy 写回,还没加载的已选节点保留 */\n const setChecked = (checked: readonly string[]) => {\n const unknown = values().filter((key) => !index.parents.has(key));\n value = [...checkedByStrategy(index, checked, checkedStrategy), ...unknown];\n };\n /** 触发框里显示的节点:多选时只列最上层的整枝(父节点也勾上了的不重复列),child 时列叶子 */\n const displayKeys = () =>\n multiple()\n ? byStrategy(values(), checkedStrategy === 'child' ? 'child' : 'parent')\n : values();\n\n /** 移除一个标签:取消整枝 */\n function remove(key: string) {\n setChecked(toggleChecked(index, values(), key));\n }\n const labelOf = (key: string) => {\n const found = nodes.get(key);\n return found ? getLabel(found.node) : (seenLabels.get(key) ?? key);\n };\n\n function show(event?: Event) {\n search = '';\n // 打开时展开已选节点的祖先:已选的看得见\n const ancestors = new Set(expanded);\n for (const key of values()) {\n for (let at = nodes.get(key)?.parent; at !== undefined; at = nodes.get(at)?.parent) {\n ancestors.add(at);\n }\n }\n expanded = [...ancestors];\n setOpen(true, 'trigger', event);\n }\n\n function clear() {\n value = multiple() ? [] : null;\n trigger?.focus();\n }\n\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 // 打开后焦点进搜索框或树;关闭时焦点还在弹层里(Esc、选中、点外面)就还给触发按钮\n function onPanelToggle(event: ToggleEvent) {\n onToggle(event);\n if (event.newState === 'open') {\n const target = searchable\n ? panel?.querySelector<HTMLElement>('input[type=\"search\"]')\n : panel?.querySelector<HTMLElement>('[role=\"tree\"]');\n target?.focus();\n return;\n }\n const active = document.activeElement;\n if (!active || active === document.body || panel?.contains(active)) trigger?.focus();\n }\n\n function onTriggerKeydown(event: KeyboardEvent) {\n const state = control();\n if (state.disabled || state.readonly) return;\n // 多选:Backspace 移除最后一个标签(同 Select)\n if (event.key === 'Backspace' && multiple()) {\n event.preventDefault();\n const last = displayKeys().at(-1);\n if (last !== undefined) remove(last);\n return;\n }\n if (!open && (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n show(event);\n }\n }\n\n // 搜索框里 ↓ 进到树;Tab 关闭后照常移到下一个\n function onSearchKeydown(event: KeyboardEvent) {\n if (event.key === 'Tab') {\n setOpen(false, 'focus', event);\n return;\n }\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n panel?.querySelector<HTMLElement>('[role=\"tree\"]')?.focus();\n }\n }\n\n /** 树的属性(单选、多选共用):本地搜索时带上 filter */\n const treeProps = (labelledBy: string | undefined) =>\n mergePartProps<TreeProps<T>>(\n {\n items: remote.items(),\n getKey,\n getLabel,\n getChildren,\n hasChildren,\n filter: treeFilter(),\n loadChildren,\n loading: remote.loading(),\n empty: remote.failure() ?? (search.trim() ? lang.selectNoMatch : undefined),\n isDisabled,\n propsScrollArea: { sx: treeSelectStyles.tree },\n 'aria-labelledby': labelledBy,\n 'aria-label': labelledBy ? undefined : rest['aria-label'],\n },\n propsTree,\n { id: treeId },\n );\n\n // 单选:选中就关闭(树的 selected 里已按 select 关过;父级改 value 时也关,不通知)\n watch(\n () => value,\n () => {\n if (!multiple() && open) open = false;\n },\n );\n\n return () => {\n const state = control();\n const s = controlParts(appearance(), state);\n const off = state.disabled;\n const locked = off || state.readonly;\n const shownKeys = displayKeys();\n // 多选:触发按钮前面一排标签,按钮里只留给读屏的文字(同 Select)\n const tagged = multiple() && shownKeys.length > 0;\n const shown =\n shownKeys.length === 0 ? (\n <span {...css.attrs(selectStyles.placeholder)}>\n {placeholder ?? lang.selectPlaceholder}\n </span>\n ) : tagged ? (\n <span {...css.attrs(visuallyHiddenStyles.hidden)}>\n {lang.selectSummary(shownKeys.map(labelOf))}\n </span>\n ) : (\n labelOf(shownKeys[0]!)\n );\n return (\n <>\n <div\n {...mergeAttrs<'div'>({ ...s.root, sx: [s.root.sx, selectStyles.root] }, propsRoot, {\n ref: _toRef(shell),\n onPointerdown: off ? undefined : focusOnShell(() => trigger),\n onClick:\n off || state.readonly\n ? undefined\n : clickOnShell(\n () => trigger,\n (event) => (open ? setOpen(false, 'trigger', event) : show(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 {tagged && (\n <SelectedTags\n {...mergePartProps<SelectedTagsProps>(\n {\n tags: shownKeys.map((key) => ({ value: key, label: labelOf(key) })),\n maxTagCount,\n onRemove: locked ? undefined : remove,\n propsTag,\n },\n propsTags,\n )}\n />\n )}\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': 'tree',\n 'aria-expanded': open,\n 'aria-controls': treeId,\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 trigger?.focus();\n if (locked) return;\n if (open) setOpen(false, 'trigger', event);\n else show(event);\n },\n onKeydown: onTriggerKeydown,\n },\n )}\n >\n <span {...mergeAttrs<'span'>({ sx: selectStyles.value }, propsValue)}>{shown}</span>\n </button>\n {clearable && shownKeys.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 <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n anchoredPanelSx(appearance().size),\n floatingStyles.scrollPanel,\n listPopoverStyles.panel,\n treeSelectStyles.panel,\n ],\n },\n propsPopover,\n { ref: _toRef(panel), popover: 'auto', onToggle: onPanelToggle },\n )}\n >\n {searchable && (\n <div {...css.attrs(listPopoverStyles.header)}>\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={treeId}\n onKeydown={onSearchKeydown}\n />\n </div>\n )}\n {open &&\n (multiple() ? (\n <Tree\n {...treeProps(state.labelledBy)}\n checkable\n _checked={[...values()]}\n onUpdate:_checked={(next: string[]) => setChecked(next)}\n _expanded={shownExpanded()}\n onUpdate:_expanded={(next: string[]) =>\n (expanded = remoteResults() ? expanded : next)\n }\n />\n ) : (\n <Tree\n {...treeProps(state.labelledBy)}\n selectionMode=\"single\"\n _selected={[...values()]}\n onUpdate:_selected={(next: string[]) => {\n if (next.length) value = next[0];\n setOpen(false, 'select');\n }}\n _expanded={shownExpanded()}\n onUpdate:_expanded={(next: string[]) =>\n (expanded = remoteResults() ? expanded : next)\n }\n />\n ))}\n </div>\n </>\n );\n };\n },\n);\n"],"mappings":"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"}
|
package/dist/input/Upload.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
2
|
import { type IconProps } from '../base/Icon';
|
|
3
3
|
import { type IconButtonProps } from '../base/IconButton';
|
|
4
4
|
import { type ProgressProps } from '../feedback/Progress';
|
package/dist/input/Upload.js
CHANGED
|
@@ -17,7 +17,7 @@ import { errorCodeText } from "../utils/request/error-message.js";
|
|
|
17
17
|
import { FileDrop, matchesAccept } from "./FileDrop.js";
|
|
18
18
|
import { Fragment, createVNode, isVNode, onBeforeUnmount, shallowRef, watch } from "vue";
|
|
19
19
|
import { _component, bindable, effect, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
20
|
-
import
|
|
20
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
21
21
|
import { CircleAlert, CircleCheck, File, GripVertical, ImagePlus, RotateCw, X } from "@lucide/icons";
|
|
22
22
|
//#region src/input/Upload.tsx
|
|
23
23
|
/**
|
package/dist/input/Upload.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Upload.js","names":["_isVNode","Upload","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps","FileIcon","_Fragment"],"sources":["../../src/input/Upload.tsx"],"sourcesContent":["/**\n * 上传(div):FileDrop 选文件,下面列出文件、上传进度、失败重试与移除。只负责界面与状态,怎样上传由 upload 决定:\n *\n * <Upload\n * _value={files}\n * multiple\n * accept=\"image/*\"\n * maxSize={5_000_000}\n * upload={(file, { onProgress, signal }) => api.upload(file, { onProgress, signal })}\n * />\n * <Upload _value={files} action=\"/files\" /> 用应用配置的请求客户端(http)上传\n *\n * - value 是 UploadFile 的数组(文件、状态、进度、错误、upload 的结果),父级写 _value={list};\n * - 给了 upload 或 action 时选到文件就开始上传,否则停在 selected(等提交时一起上传);移除正在上传的文件会中止(signal);\n * - action:经 createUi / Provider 的 http 把文件 POST 过去(multipart,字段名 fieldName),与其他请求共用 baseURL、令牌与拆包;\n * fetch 拿不到上传的字节进度,进度条是不确定的,要进度时写 upload(XMLHttpRequest 的 upload.onprogress);\n * - 超过 maxSize、不在 accept 里的文件也列出来,带错误、不上传;单选(不写 multiple)时新文件替换旧的;\n * - 已有文件(之前上传过、从后端读回来的)用 existingUploadFile 放进 value:状态是 done,没有 File,\n * 给了 url 时文件名链到它(预览、下载),可以移除;\n *\n * let files = _state([existingUploadFile({ name: '验证报告.pdf', url: '/files/123' })]);\n * - 在 Field 里时关联标签与错误;写了 name 时有一个隐藏的 file input 带着全部文件,原生提交(FormData)也拿得到。\n *\n * - 图片墙(listType=\"picture\"):方形缩略图(选的文件用本地地址显示,不等上传),点开看大图(整面墙是一个 ImageGroup,\n * 大图里左右切换);上传中盖一层进度,失败标红;选文件的区域是墙上最后一格。sortable 时拖动把手(或聚焦后用键盘)调整顺序,\n * pasteable 时焦点在组件里按 Ctrl + V 把剪贴板里的图片加进来(截图、从别处复制的图)。\n *\n * 部件:Root(div)、Drop(FileDrop)、List(ul)、Item(li)、Icon(文件图标)、Body(文件名与下一行)、Name、Meta(大小或错误)、\n * Progress、Retry(重试按钮)、Remove(移除按钮)。\n */\nimport {\n CircleAlert,\n CircleCheck,\n File as FileIcon,\n GripVertical,\n ImagePlus,\n RotateCw,\n X,\n} from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onBeforeUnmount, watch } from 'vue';\nimport { ButtonBase } from '../base/ButtonBase';\nimport { Image, ImageGroup } from '../display/Image';\nimport { useSortable } from '../utils/dom/sortable';\nimport { Icon, type IconProps } from '../base/Icon';\nimport { Link } from '../base/Link';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFormat } from '../config/lang/format';\nimport { useFieldControl } from '../form/Field';\nimport { useHttp } from '../utils/request/http';\nimport { errorCodeText } from '../utils/request/error-message';\nimport { Progress, type ProgressProps } from '../feedback/Progress';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { itemStyles } from '../utils/style/item-styles';\nimport { FileDrop, matchesAccept, type FileDropProps } from './FileDrop';\nimport { GridList, type GridProps } from '../layout/Grid';\n\n/** 列表里的一个文件 */\nexport interface UploadFile {\n /** 组件给的 id,同一个列表里唯一 */\n readonly id: string;\n /** 文件名 */\n readonly name: string;\n /** 大小(字节);已有文件不知道时为 undefined */\n readonly size?: number;\n /** 选的文件;已有文件没有 */\n readonly file?: File;\n /** 已有文件的地址:文件名链到它 */\n readonly url?: string;\n /** selected:选了、还没上传;uploading:上传中;done:完成;error:失败或没通过检查 */\n readonly status: 'selected' | 'uploading' | 'done' | 'error';\n /** 上传进度 0–1;upload 没报告进度时为 undefined(不确定进度) */\n readonly progress?: number;\n /** 错误信息 */\n readonly error?: string;\n /** 没通过大小或类型检查:不会上传,也不能重试 */\n readonly rejected?: boolean;\n /** upload 的返回值(如文件地址) */\n readonly response?: unknown;\n}\n\n/** 上传一个文件:报告进度、响应中止;成功时 resolve(值记在 response 上),失败时 reject */\nexport type UploadHandler = (\n file: File,\n context: { onProgress: (fraction: number) => void; signal: AbortSignal },\n) => Promise<unknown>;\n\n/** 列表的样子 */\nexport interface UploadListTypes {\n /** 一行一个文件:图标、文件名、大小或进度(默认) */\n text: unknown;\n /** 图片墙:方形缩略图,点开看大图 */\n picture: unknown;\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface UploadProps extends PartProps<'div'> {\n /** 文件列表:父级写 _value={list} */\n _value?: UploadFile[];\n /** 怎样上传一个文件;不写时用 action,都没有时只选文件、不上传 */\n upload?: UploadHandler;\n /** 上传地址:没写 upload 时用应用配置的请求客户端(useHttp)POST 过去,响应体记在 response 上 */\n action?: string;\n /** action 上传时文件在表单里的字段名,默认 file */\n fieldName?: string;\n /** 接受的文件类型(同原生 accept) */\n accept?: string;\n /** 可以选多个;不写时新文件替换旧的 */\n multiple?: boolean;\n /** 单个文件的大小上限(字节) */\n maxSize?: number;\n /** 最多几个文件,超出的不加进来 */\n maxFiles?: number;\n /** 原生表单提交时的字段名:写了才有隐藏的 file input */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:只列出文件,不能再选、不能移除或重试 */\n readonly?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 必填 */\n required?: boolean;\n /** 选择区域里提示文字下面的说明(大小、类型限制) */\n description?: FileDropProps['description'];\n /** 列表的样子:text 一行一个文件(默认),picture 是图片墙 */\n listType?: keyof UploadListTypes;\n /** 图片墙里缩略图的边长(px),默认 104 */\n thumbnailSize?: number;\n /** 拖动把手(或聚焦后用键盘)调整文件的顺序(图片墙) */\n sortable?: boolean;\n /** 焦点在组件里时 Ctrl + V 把剪贴板里的图片、文件加进来 */\n pasteable?: boolean;\n /** 选择区域(FileDrop)的部件属性 */\n propsDrop?: Partial<FileDropProps>;\n /** 列表的部件属性 */\n propsList?: Partial<GridProps<'ul'>>;\n /** 每一项的部件属性,可以按文件计算 */\n propsItem?: PartProps<'li'> | ((file: UploadFile) => PartProps<'li'>);\n /** 每一项的文件图标(按状态是文件、对勾或警告)的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 每一项里文件名与下一行(大小、错误或进度)的外层的部件属性 */\n propsBody?: PartProps<'div'>;\n /** 每一项里文件名的部件属性 */\n propsName?: PartProps<'span'>;\n /** 每一项里文件大小或错误信息的部件属性 */\n propsMeta?: PartProps<'span'>;\n /** 每一项上传中的进度条的部件属性;进度与名称(文件名)由组件管理 */\n propsProgress?: Omit<Partial<ProgressProps>, 'value' | 'aria-label'>;\n /**\n * 每一项失败后的重试按钮的部件属性。名称(重新上传 文件名)每项不同,由组件按语言包生成,\n * 改文案请改语言包的 uploadRetry;点击由组件管理\n */\n propsRetry?: Omit<Partial<IconButtonProps>, 'aria-label' | 'onClick'>;\n /** 每一项的移除按钮的部件属性;名称(语言包的 uploadRemove)、点击与不可用由组件管理 */\n propsRemove?: Omit<Partial<IconButtonProps>, 'aria-label' | 'onClick' | 'disabled'>;\n}\n\n/** Upload 的样式:root、list、item、icon、body、name、meta、error、progress */\nexport const uploadStyles = css.create({\n root: { display: 'grid', gap: '_sm' },\n item: {\n cursor: 'default',\n gap: '_sm',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n },\n icon: { flexShrink: 0, color: '_textMuted' },\n body: { display: 'grid', gap: '_xs', flexGrow: 1, minWidth: 0 },\n name: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },\n meta: { fontSize: '_sm', color: '_textMuted' },\n error: { color: '_dangerText' },\n done: { color: '_successText' },\n progress: { width: '_full' },\n // 图片墙:缩略图与“添加图片”一样大,排成一行、放不下换行\n wall: { display: 'flex', flexWrap: 'wrap', gap: '_sm' },\n wallList: { display: 'contents' },\n card: {\n position: 'relative',\n boxSizing: 'border-box',\n flexShrink: 0,\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n overflow: 'hidden',\n backgroundColor: '_fill',\n },\n cardError: { borderColor: '_danger' },\n // 选文件的那一格:同样大小,图标与文字居中\n addCard: { padding: '_xs', gap: '_xs', textAlign: 'center', fontSize: '_sm' },\n // 上传中、失败:盖在缩略图上\n overlay: {\n position: 'absolute',\n insetInline: 0,\n bottom: 0,\n display: 'flex',\n flexDirection: 'column',\n gap: '_xs',\n padding: '_xs',\n backgroundColor: 'rgb(0 0 0 / 0.55)',\n color: 'white',\n fontSize: '_xs',\n },\n placeholder: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '_xs',\n width: '_full',\n height: '_full',\n padding: '_xs',\n boxSizing: 'border-box',\n color: '_textMuted',\n fontSize: '_xs',\n textAlign: 'center',\n overflowWrap: 'anywhere',\n },\n // 右上角的把手、重试、移除:浅色底上的小按钮\n actions: {\n position: 'absolute',\n top: '_xs',\n insetInlineEnd: '_xs',\n display: 'flex',\n gap: '2px',\n },\n action: { backgroundColor: { default: 'rgb(255 255 255 / 0.85)', ':hover': 'white' } },\n handle: {\n display: 'grid',\n placeItems: 'center',\n width: '1.75em',\n height: '1.75em',\n borderRadius: '_sm',\n color: '_text',\n backgroundColor: 'rgb(255 255 255 / 0.85)',\n cursor: { default: 'grab', ':active': 'grabbing' },\n touchAction: 'none',\n },\n});\n\n/** Upload 的动态样式:缩略图的边长 */\nexport const uploadDynamicStyles = css.create({\n square: (size: number) => ({ width: `${size}px`, height: `${size}px` }),\n});\n\nlet nextId = 0;\n\n/** 已有文件(之前上传过、从后端读回来的):放进 Upload 的 value,状态是 done */\nexport function existingUploadFile(file: {\n /** 标识;不写时生成一个 */\n id?: string;\n /** 文件名 */\n name: string;\n /** 大小(字节) */\n size?: number;\n /** 地址:文件名链到它 */\n url?: string;\n}): UploadFile {\n return { ...file, id: file.id ?? `upload-${++nextId}`, status: 'done', response: file.url };\n}\n\n/** 上传:选文件、列出文件与进度、失败重试、移除 */\nexport const Upload = _component(\n ({\n _value: value = _bindable<UploadFile[]>([]),\n upload,\n action,\n fieldName = 'file',\n accept,\n multiple = false,\n maxSize,\n maxFiles,\n name,\n disabled,\n readonly,\n invalid,\n required,\n description,\n listType = 'text',\n thumbnailSize = 104,\n sortable = false,\n pasteable = false,\n propsDrop,\n propsList,\n propsItem,\n propsIcon,\n propsBody,\n propsName,\n propsMeta,\n propsProgress,\n propsRetry,\n propsRemove,\n ...rest\n }: UploadProps) => {\n const lang = useLang();\n const format = useFormat();\n // delegate:里面的 FileDrop 照常从 Field 拿 id、说明与标签\n const control = useFieldControl(() => ({ invalid, required, disabled, readonly }), {\n delegate: true,\n });\n const http = useHttp();\n /** 实际用的上传函数:upload 优先,其次按 action 用请求客户端发 */\n const uploader = (): UploadHandler | undefined =>\n upload ??\n (action\n ? (file, { signal }) => {\n const body = new FormData();\n body.append(fieldName, file);\n return http.request({ method: 'POST', url: action, body, signal });\n }\n : undefined);\n let hidden = _state.raw<HTMLInputElement | null>(null);\n // 每个正在上传的文件一个:移除、重试、卸载时中止\n const controllers = new Map<string, AbortController>();\n onBeforeUnmount(() => controllers.forEach((controller) => controller.abort()));\n\n const patch = (id: string, changes: Partial<UploadFile>) =>\n (value = value.map((item) => (item.id === id ? { ...item, ...changes } : item)));\n\n async function start(item: UploadFile) {\n const send = uploader();\n if (!send || !item.file) return;\n controllers.get(item.id)?.abort();\n const controller = new AbortController();\n controllers.set(item.id, controller);\n patch(item.id, { status: 'uploading', progress: undefined, error: undefined });\n try {\n const response = await send(item.file!, {\n onProgress: (fraction) => {\n if (!controller.signal.aborted) patch(item.id, { progress: fraction });\n },\n signal: controller.signal,\n });\n if (!controller.signal.aborted) patch(item.id, { status: 'done', progress: 1, response });\n } catch (error) {\n if (controller.signal.aborted) return;\n // 码有文案时按码(网络断了、后端拒绝),否则是上传函数自己的说明,再没有是笼统的“上传失败”\n const message =\n errorCodeText(error, lang) ??\n (error instanceof Error && error.message ? error.message : lang.uploadFailed);\n patch(item.id, { status: 'error', error: message });\n } finally {\n if (controllers.get(item.id) === controller) controllers.delete(item.id);\n }\n }\n\n function remove(id: string) {\n controllers.get(id)?.abort();\n controllers.delete(id);\n value = value.filter((item) => item.id !== id);\n }\n\n function add(files: File[], rejectedType = false) {\n const entries = files.map((file): UploadFile => {\n const base = { id: `upload-${++nextId}`, name: file.name, size: file.size, file };\n if (rejectedType) {\n return { ...base, status: 'error', error: lang.fileTypeRejected, rejected: true };\n }\n if (maxSize != null && file.size > maxSize) {\n const error = lang.fileTooLarge(format.fileSize(maxSize));\n return { ...base, status: 'error', error, rejected: true };\n }\n return { ...base, status: 'selected' };\n });\n if (!multiple) value.forEach((item) => controllers.get(item.id)?.abort());\n const kept = multiple ? value : [];\n const room = maxFiles == null ? entries.length : Math.max(0, maxFiles - kept.length);\n const added = (multiple ? entries : entries.slice(-1)).slice(0, room);\n value = [...kept, ...added];\n added.filter((item) => item.status === 'selected').forEach((item) => void start(item));\n }\n\n // 图片墙里选的文件的本地地址:用完(移除、卸载)回收\n const previews = new Map<string, string>();\n const previewOf = (item: UploadFile) => {\n if (item.url) return item.url;\n if (!item.file || !item.file.type.startsWith('image/')) return undefined;\n let url = previews.get(item.id);\n if (!url) previews.set(item.id, (url = URL.createObjectURL(item.file)));\n return url;\n };\n watch(\n () => value,\n (list) => {\n const kept = new Set(list.map((item) => item.id));\n for (const [id, url] of previews)\n if (!kept.has(id)) {\n URL.revokeObjectURL(url);\n previews.delete(id);\n }\n },\n );\n onBeforeUnmount(() => previews.forEach((url) => URL.revokeObjectURL(url)));\n\n let wall = _state.raw<HTMLElement | null>(null);\n const sortableWall = useSortable<UploadFile>({\n items: () => value,\n getKey: (item) => item.id,\n getLabel: (item) => item.name,\n onChange: (next) => (value = next),\n container: () => wall,\n orientation: () => 'horizontal',\n disabled: () => !sortable || control().readonly || control().disabled,\n });\n\n /** 粘贴:剪贴板里的文件(截图是 image/png)按 accept 分开,不符合的照常列出、带错误 */\n function onPaste(event: ClipboardEvent) {\n const state = control();\n if (!pasteable || state.disabled || state.readonly) return;\n const files = [...(event.clipboardData?.files ?? [])];\n if (files.length === 0) return;\n event.preventDefault();\n const accepted = files.filter((file) => matchesAccept(file, accept));\n const rejected = files.filter((file) => !matchesAccept(file, accept));\n if (accepted.length) add(accepted);\n if (rejected.length) add(rejected, true);\n }\n\n // 隐藏的 file input 带着全部可提交的文件:原生提交、FormData 拿得到\n _effect(() => {\n if (!hidden || typeof DataTransfer === 'undefined') return;\n const transfer = new DataTransfer();\n for (const item of value) if (item.file && !item.rejected) transfer.items.add(item.file);\n hidden.files = transfer.files;\n });\n\n function renderItem(item: UploadFile) {\n const state = control();\n const own = typeof propsItem === 'function' ? propsItem(item) : propsItem;\n const fileName = item.name;\n const failed = item.status === 'error';\n return (\n <li\n key={item.id}\n {...mergeAttrs<'li'>({ sx: [itemStyles.row, uploadStyles.item] }, own)}\n data-state={item.status}\n >\n <Icon\n {...mergePartProps<IconProps>(\n {\n icon: failed ? CircleAlert : item.status === 'done' ? CircleCheck : FileIcon,\n sx: [\n uploadStyles.icon,\n failed && uploadStyles.error,\n item.status === 'done' && uploadStyles.done,\n ],\n },\n propsIcon,\n )}\n />\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.body }, propsBody)}>\n <span {...mergeAttrs<'span'>({ sx: uploadStyles.name }, propsName)}>\n {item.url ? (\n <Link href={item.url} target=\"_blank\">\n {fileName}\n </Link>\n ) : (\n fileName\n )}\n </span>\n {item.status === 'uploading' ? (\n <Progress\n {...mergePartProps<ProgressProps>(\n { size: 'xs', sx: uploadStyles.progress },\n propsProgress,\n {\n value: item.progress == null ? null : Math.round(item.progress * 100),\n 'aria-label': fileName,\n },\n )}\n />\n ) : (\n <span\n {...mergeAttrs<'span'>(\n { sx: [uploadStyles.meta, failed && uploadStyles.error] },\n propsMeta,\n )}\n >\n {failed ? item.error : item.size != null && format.fileSize(item.size)}\n {item.status === 'done' && <VisuallyHidden> {lang.uploadDone}</VisuallyHidden>}\n </span>\n )}\n </div>\n {failed && uploader() && !item.rejected && !state.readonly && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: RotateCw,\n variant: 'ghost',\n size: 'sm',\n // 名称带文件名、每项不同:类型里不让使用方覆盖(同一个值会让各项的按钮同名)\n 'aria-label': lang.uploadRetry(fileName),\n },\n propsRetry,\n { onClick: () => void start(item) },\n )}\n />\n )}\n {!state.readonly && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: X,\n variant: 'ghost',\n size: 'sm',\n 'aria-label': lang.uploadRemove(fileName),\n },\n propsRemove,\n { disabled: state.disabled, onClick: () => remove(item.id) },\n )}\n />\n )}\n </li>\n );\n }\n\n /** 图片墙的一格:缩略图(点开看大图)、上传进度或错误、把手、重试与移除 */\n function renderCard(item: UploadFile) {\n const state = control();\n const failed = item.status === 'error';\n const src = previewOf(item);\n return (\n <div\n key={item.id}\n {...mergeAttrs<'div'>(\n {\n sx: [\n uploadStyles.card,\n uploadDynamicStyles.square(thumbnailSize),\n failed && uploadStyles.cardError,\n ],\n },\n sortableWall.itemProps(item.id),\n { role: 'listitem' },\n )}\n data-state={item.status}\n >\n {src && !item.rejected ? (\n <Image\n src={src}\n alt={item.name}\n width={thumbnailSize - 2}\n height={thumbnailSize - 2}\n radius=\"none\"\n preview={{ caption: item.name, download: item.name }}\n />\n ) : (\n <div {...css.attrs(uploadStyles.placeholder)}>\n <Icon icon={failed ? CircleAlert : FileIcon} sx={failed && uploadStyles.error} />\n {item.name}\n </div>\n )}\n {item.status === 'uploading' && (\n <div {...css.attrs(uploadStyles.overlay)}>\n <Progress\n {...mergePartProps<ProgressProps>({ size: 'xs' }, propsProgress, {\n value: item.progress == null ? null : Math.round(item.progress * 100),\n 'aria-label': item.name,\n })}\n />\n </div>\n )}\n {failed && src && !item.rejected && (\n <div {...css.attrs(uploadStyles.overlay)} title={item.error}>\n {item.error}\n </div>\n )}\n {item.status === 'done' && <VisuallyHidden>{lang.uploadDone}</VisuallyHidden>}\n {!state.readonly && (\n <div {...css.attrs(uploadStyles.actions)}>\n {sortable && (\n <ButtonBase\n sx={uploadStyles.handle}\n ripple={false}\n disabled={state.disabled}\n aria-label={lang.sortableHandle(item.name)}\n {...sortableWall.handleProps(item.id)}\n >\n <Icon icon={GripVertical} />\n </ButtonBase>\n )}\n {failed && uploader() && !item.rejected && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: RotateCw,\n variant: 'ghost',\n size: 'xs',\n sx: uploadStyles.action,\n 'aria-label': lang.uploadRetry(item.name),\n },\n propsRetry,\n { onClick: () => void start(item) },\n )}\n />\n )}\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: X,\n variant: 'ghost',\n size: 'xs',\n sx: uploadStyles.action,\n 'aria-label': lang.uploadRemove(item.name),\n },\n propsRemove,\n { disabled: state.disabled, onClick: () => remove(item.id) },\n )}\n />\n </div>\n )}\n </div>\n );\n }\n\n /** 选文件的区域:列表模式在上方,图片墙模式是最后一格 */\n function renderDrop(picture: boolean) {\n const state = control();\n const full = maxFiles != null && multiple && value.length >= maxFiles;\n if (state.readonly || (picture && full)) return null;\n const hint = pasteable ? lang.uploadPasteHint : undefined;\n const props = mergePartProps<FileDropProps>(\n {\n accept,\n multiple,\n disabled: state.disabled,\n invalid: state.invalid,\n // 选好的文件不在这个输入框里(它选完就清空):已有文件时不再原生必填,免得表单交不了\n required: state.required && value.length === 0,\n description: picture\n ? undefined\n : hint\n ? [description, description != null && ' · ', hint]\n : description,\n propsRoot: picture\n ? { sx: [uploadStyles.addCard, uploadDynamicStyles.square(thumbnailSize)] }\n : undefined,\n },\n propsDrop,\n {\n onFiles: (files: File[]) => add(files),\n onReject: (files: File[]) => add(files, true),\n },\n );\n // 列表模式不传子元素:FileDrop 用默认的图标、提示与说明(写了 undefined 也算传了,会把默认内容换掉)\n if (!picture) return <FileDrop {...props} />;\n return (\n <FileDrop {...props}>\n <Icon icon={ImagePlus} />\n {lang.uploadAddImage}\n </FileDrop>\n );\n }\n\n return () => {\n const state = control();\n if (listType === 'picture')\n return (\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.root }, rest, { onPaste })}>\n <ImageGroup sx={uploadStyles.wall}>\n {/* 列表里只有缩略图(“添加图片”与预览不是列表项);display: contents,缩略图仍和“添加图片”排在一行 */}\n <div\n ref={_toRef(wall)}\n role=\"list\"\n // 状态变化(失败、完成)由读屏播报\n aria-live=\"polite\"\n {...css.attrs(uploadStyles.wallList)}\n >\n {value.map(renderCard)}\n </div>\n {renderDrop(true)}\n </ImageGroup>\n {pasteable && !state.readonly && (\n <span {...css.attrs(uploadStyles.meta)}>\n {[description, description != null && ' · ', lang.uploadPasteHint]}\n </span>\n )}\n {sortable && (\n <>\n <VisuallyHidden id={sortableWall.instructionsId}>\n {lang.sortableInstructions}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{sortableWall.announcement}</VisuallyHidden>\n </>\n )}\n {name != null && (\n <input\n ref={_toRef(hidden)}\n type=\"file\"\n name={name}\n multiple\n hidden\n tabindex={-1}\n aria-hidden=\"true\"\n />\n )}\n </div>\n );\n return (\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.root }, rest, { onPaste })}>\n {renderDrop(false)}\n {name != null && (\n <input\n ref={_toRef(hidden)}\n type=\"file\"\n name={name}\n multiple\n hidden\n tabindex={-1}\n aria-hidden=\"true\"\n />\n )}\n {value.length > 0 && (\n // 状态变化(失败、完成)由读屏播报\n <GridList\n {...mergePartProps<GridProps<'ul'>>({ gap: 'xs' }, propsList)}\n aria-live=\"polite\"\n >\n {value.map(renderItem)}\n </GridList>\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Upload.js","names":["_isVNode","Upload","_vtp_bindable","_vtp_readonlyProp","_vtp_restProps","_vue_shallowRef","_createVNode","_mergeProps","FileIcon","_Fragment"],"sources":["../../src/input/Upload.tsx"],"sourcesContent":["/**\n * 上传(div):FileDrop 选文件,下面列出文件、上传进度、失败重试与移除。只负责界面与状态,怎样上传由 upload 决定:\n *\n * <Upload\n * _value={files}\n * multiple\n * accept=\"image/*\"\n * maxSize={5_000_000}\n * upload={(file, { onProgress, signal }) => api.upload(file, { onProgress, signal })}\n * />\n * <Upload _value={files} action=\"/files\" /> 用应用配置的请求客户端(http)上传\n *\n * - value 是 UploadFile 的数组(文件、状态、进度、错误、upload 的结果),父级写 _value={list};\n * - 给了 upload 或 action 时选到文件就开始上传,否则停在 selected(等提交时一起上传);移除正在上传的文件会中止(signal);\n * - action:经 createUi / Provider 的 http 把文件 POST 过去(multipart,字段名 fieldName),与其他请求共用 baseURL、令牌与拆包;\n * fetch 拿不到上传的字节进度,进度条是不确定的,要进度时写 upload(XMLHttpRequest 的 upload.onprogress);\n * - 超过 maxSize、不在 accept 里的文件也列出来,带错误、不上传;单选(不写 multiple)时新文件替换旧的;\n * - 已有文件(之前上传过、从后端读回来的)用 existingUploadFile 放进 value:状态是 done,没有 File,\n * 给了 url 时文件名链到它(预览、下载),可以移除;\n *\n * let files = _state([existingUploadFile({ name: '验证报告.pdf', url: '/files/123' })]);\n * - 在 Field 里时关联标签与错误;写了 name 时有一个隐藏的 file input 带着全部文件,原生提交(FormData)也拿得到。\n *\n * - 图片墙(listType=\"picture\"):方形缩略图(选的文件用本地地址显示,不等上传),点开看大图(整面墙是一个 ImageGroup,\n * 大图里左右切换);上传中盖一层进度,失败标红;选文件的区域是墙上最后一格。sortable 时拖动把手(或聚焦后用键盘)调整顺序,\n * pasteable 时焦点在组件里按 Ctrl + V 把剪贴板里的图片加进来(截图、从别处复制的图)。\n *\n * 部件:Root(div)、Drop(FileDrop)、List(ul)、Item(li)、Icon(文件图标)、Body(文件名与下一行)、Name、Meta(大小或错误)、\n * Progress、Retry(重试按钮)、Remove(移除按钮)。\n */\nimport {\n CircleAlert,\n CircleCheck,\n File as FileIcon,\n GripVertical,\n ImagePlus,\n RotateCw,\n X,\n} from '@lucide/icons';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { onBeforeUnmount, watch } from 'vue';\nimport { ButtonBase } from '../base/ButtonBase';\nimport { Image, ImageGroup } from '../display/Image';\nimport { useSortable } from '../utils/dom/sortable';\nimport { Icon, type IconProps } from '../base/Icon';\nimport { Link } from '../base/Link';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { VisuallyHidden } from '../base/VisuallyHidden';\nimport { useLang } from '../config/context';\nimport { useFormat } from '../config/lang/format';\nimport { useFieldControl } from '../form/Field';\nimport { useHttp } from '../utils/request/http';\nimport { errorCodeText } from '../utils/request/error-message';\nimport { Progress, type ProgressProps } from '../feedback/Progress';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { itemStyles } from '../utils/style/item-styles';\nimport { FileDrop, matchesAccept, type FileDropProps } from './FileDrop';\nimport { GridList, type GridProps } from '../layout/Grid';\n\n/** 列表里的一个文件 */\nexport interface UploadFile {\n /** 组件给的 id,同一个列表里唯一 */\n readonly id: string;\n /** 文件名 */\n readonly name: string;\n /** 大小(字节);已有文件不知道时为 undefined */\n readonly size?: number;\n /** 选的文件;已有文件没有 */\n readonly file?: File;\n /** 已有文件的地址:文件名链到它 */\n readonly url?: string;\n /** selected:选了、还没上传;uploading:上传中;done:完成;error:失败或没通过检查 */\n readonly status: 'selected' | 'uploading' | 'done' | 'error';\n /** 上传进度 0–1;upload 没报告进度时为 undefined(不确定进度) */\n readonly progress?: number;\n /** 错误信息 */\n readonly error?: string;\n /** 没通过大小或类型检查:不会上传,也不能重试 */\n readonly rejected?: boolean;\n /** upload 的返回值(如文件地址) */\n readonly response?: unknown;\n}\n\n/** 上传一个文件:报告进度、响应中止;成功时 resolve(值记在 response 上),失败时 reject */\nexport type UploadHandler = (\n file: File,\n context: { onProgress: (fraction: number) => void; signal: AbortSignal },\n) => Promise<unknown>;\n\n/** 列表的样子 */\nexport interface UploadListTypes {\n /** 一行一个文件:图标、文件名、大小或进度(默认) */\n text: unknown;\n /** 图片墙:方形缩略图,点开看大图 */\n picture: unknown;\n}\n\n/** 未声明的属性落到外层 div 上 */\nexport interface UploadProps extends PartProps<'div'> {\n /** 文件列表:父级写 _value={list} */\n _value?: UploadFile[];\n /** 怎样上传一个文件;不写时用 action,都没有时只选文件、不上传 */\n upload?: UploadHandler;\n /** 上传地址:没写 upload 时用应用配置的请求客户端(useHttp)POST 过去,响应体记在 response 上 */\n action?: string;\n /** action 上传时文件在表单里的字段名,默认 file */\n fieldName?: string;\n /** 接受的文件类型(同原生 accept) */\n accept?: string;\n /** 可以选多个;不写时新文件替换旧的 */\n multiple?: boolean;\n /** 单个文件的大小上限(字节) */\n maxSize?: number;\n /** 最多几个文件,超出的不加进来 */\n maxFiles?: number;\n /** 原生表单提交时的字段名:写了才有隐藏的 file input */\n name?: string;\n /** 不可用 */\n disabled?: boolean;\n /** 只读:只列出文件,不能再选、不能移除或重试 */\n readonly?: boolean;\n /** 校验未通过 */\n invalid?: boolean;\n /** 必填 */\n required?: boolean;\n /** 选择区域里提示文字下面的说明(大小、类型限制) */\n description?: FileDropProps['description'];\n /** 列表的样子:text 一行一个文件(默认),picture 是图片墙 */\n listType?: keyof UploadListTypes;\n /** 图片墙里缩略图的边长(px),默认 104 */\n thumbnailSize?: number;\n /** 拖动把手(或聚焦后用键盘)调整文件的顺序(图片墙) */\n sortable?: boolean;\n /** 焦点在组件里时 Ctrl + V 把剪贴板里的图片、文件加进来 */\n pasteable?: boolean;\n /** 选择区域(FileDrop)的部件属性 */\n propsDrop?: Partial<FileDropProps>;\n /** 列表的部件属性 */\n propsList?: Partial<GridProps<'ul'>>;\n /** 每一项的部件属性,可以按文件计算 */\n propsItem?: PartProps<'li'> | ((file: UploadFile) => PartProps<'li'>);\n /** 每一项的文件图标(按状态是文件、对勾或警告)的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 每一项里文件名与下一行(大小、错误或进度)的外层的部件属性 */\n propsBody?: PartProps<'div'>;\n /** 每一项里文件名的部件属性 */\n propsName?: PartProps<'span'>;\n /** 每一项里文件大小或错误信息的部件属性 */\n propsMeta?: PartProps<'span'>;\n /** 每一项上传中的进度条的部件属性;进度与名称(文件名)由组件管理 */\n propsProgress?: Omit<Partial<ProgressProps>, 'value' | 'aria-label'>;\n /**\n * 每一项失败后的重试按钮的部件属性。名称(重新上传 文件名)每项不同,由组件按语言包生成,\n * 改文案请改语言包的 uploadRetry;点击由组件管理\n */\n propsRetry?: Omit<Partial<IconButtonProps>, 'aria-label' | 'onClick'>;\n /** 每一项的移除按钮的部件属性;名称(语言包的 uploadRemove)、点击与不可用由组件管理 */\n propsRemove?: Omit<Partial<IconButtonProps>, 'aria-label' | 'onClick' | 'disabled'>;\n}\n\n/** Upload 的样式:root、list、item、icon、body、name、meta、error、progress */\nexport const uploadStyles = css.create({\n root: { display: 'grid', gap: '_sm' },\n item: {\n cursor: 'default',\n gap: '_sm',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n },\n icon: { flexShrink: 0, color: '_textMuted' },\n body: { display: 'grid', gap: '_xs', flexGrow: 1, minWidth: 0 },\n name: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },\n meta: { fontSize: '_sm', color: '_textMuted' },\n error: { color: '_dangerText' },\n done: { color: '_successText' },\n progress: { width: '_full' },\n // 图片墙:缩略图与“添加图片”一样大,排成一行、放不下换行\n wall: { display: 'flex', flexWrap: 'wrap', gap: '_sm' },\n wallList: { display: 'contents' },\n card: {\n position: 'relative',\n boxSizing: 'border-box',\n flexShrink: 0,\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_borderMuted',\n borderRadius: '_md',\n overflow: 'hidden',\n backgroundColor: '_fill',\n },\n cardError: { borderColor: '_danger' },\n // 选文件的那一格:同样大小,图标与文字居中\n addCard: { padding: '_xs', gap: '_xs', textAlign: 'center', fontSize: '_sm' },\n // 上传中、失败:盖在缩略图上\n overlay: {\n position: 'absolute',\n insetInline: 0,\n bottom: 0,\n display: 'flex',\n flexDirection: 'column',\n gap: '_xs',\n padding: '_xs',\n backgroundColor: 'rgb(0 0 0 / 0.55)',\n color: 'white',\n fontSize: '_xs',\n },\n placeholder: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '_xs',\n width: '_full',\n height: '_full',\n padding: '_xs',\n boxSizing: 'border-box',\n color: '_textMuted',\n fontSize: '_xs',\n textAlign: 'center',\n overflowWrap: 'anywhere',\n },\n // 右上角的把手、重试、移除:浅色底上的小按钮\n actions: {\n position: 'absolute',\n top: '_xs',\n insetInlineEnd: '_xs',\n display: 'flex',\n gap: '2px',\n },\n action: { backgroundColor: { default: 'rgb(255 255 255 / 0.85)', ':hover': 'white' } },\n handle: {\n display: 'grid',\n placeItems: 'center',\n width: '1.75em',\n height: '1.75em',\n borderRadius: '_sm',\n color: '_text',\n backgroundColor: 'rgb(255 255 255 / 0.85)',\n cursor: { default: 'grab', ':active': 'grabbing' },\n touchAction: 'none',\n },\n});\n\n/** Upload 的动态样式:缩略图的边长 */\nexport const uploadDynamicStyles = css.create({\n square: (size: number) => ({ width: `${size}px`, height: `${size}px` }),\n});\n\nlet nextId = 0;\n\n/** 已有文件(之前上传过、从后端读回来的):放进 Upload 的 value,状态是 done */\nexport function existingUploadFile(file: {\n /** 标识;不写时生成一个 */\n id?: string;\n /** 文件名 */\n name: string;\n /** 大小(字节) */\n size?: number;\n /** 地址:文件名链到它 */\n url?: string;\n}): UploadFile {\n return { ...file, id: file.id ?? `upload-${++nextId}`, status: 'done', response: file.url };\n}\n\n/** 上传:选文件、列出文件与进度、失败重试、移除 */\nexport const Upload = _component(\n ({\n _value: value = _bindable<UploadFile[]>([]),\n upload,\n action,\n fieldName = 'file',\n accept,\n multiple = false,\n maxSize,\n maxFiles,\n name,\n disabled,\n readonly,\n invalid,\n required,\n description,\n listType = 'text',\n thumbnailSize = 104,\n sortable = false,\n pasteable = false,\n propsDrop,\n propsList,\n propsItem,\n propsIcon,\n propsBody,\n propsName,\n propsMeta,\n propsProgress,\n propsRetry,\n propsRemove,\n ...rest\n }: UploadProps) => {\n const lang = useLang();\n const format = useFormat();\n // delegate:里面的 FileDrop 照常从 Field 拿 id、说明与标签\n const control = useFieldControl(() => ({ invalid, required, disabled, readonly }), {\n delegate: true,\n });\n const http = useHttp();\n /** 实际用的上传函数:upload 优先,其次按 action 用请求客户端发 */\n const uploader = (): UploadHandler | undefined =>\n upload ??\n (action\n ? (file, { signal }) => {\n const body = new FormData();\n body.append(fieldName, file);\n return http.request({ method: 'POST', url: action, body, signal });\n }\n : undefined);\n let hidden = _state.raw<HTMLInputElement | null>(null);\n // 每个正在上传的文件一个:移除、重试、卸载时中止\n const controllers = new Map<string, AbortController>();\n onBeforeUnmount(() => controllers.forEach((controller) => controller.abort()));\n\n const patch = (id: string, changes: Partial<UploadFile>) =>\n (value = value.map((item) => (item.id === id ? { ...item, ...changes } : item)));\n\n async function start(item: UploadFile) {\n const send = uploader();\n if (!send || !item.file) return;\n controllers.get(item.id)?.abort();\n const controller = new AbortController();\n controllers.set(item.id, controller);\n patch(item.id, { status: 'uploading', progress: undefined, error: undefined });\n try {\n const response = await send(item.file!, {\n onProgress: (fraction) => {\n if (!controller.signal.aborted) patch(item.id, { progress: fraction });\n },\n signal: controller.signal,\n });\n if (!controller.signal.aborted) patch(item.id, { status: 'done', progress: 1, response });\n } catch (error) {\n if (controller.signal.aborted) return;\n // 码有文案时按码(网络断了、后端拒绝),否则是上传函数自己的说明,再没有是笼统的“上传失败”\n const message =\n errorCodeText(error, lang) ??\n (error instanceof Error && error.message ? error.message : lang.uploadFailed);\n patch(item.id, { status: 'error', error: message });\n } finally {\n if (controllers.get(item.id) === controller) controllers.delete(item.id);\n }\n }\n\n function remove(id: string) {\n controllers.get(id)?.abort();\n controllers.delete(id);\n value = value.filter((item) => item.id !== id);\n }\n\n function add(files: File[], rejectedType = false) {\n const entries = files.map((file): UploadFile => {\n const base = { id: `upload-${++nextId}`, name: file.name, size: file.size, file };\n if (rejectedType) {\n return { ...base, status: 'error', error: lang.fileTypeRejected, rejected: true };\n }\n if (maxSize != null && file.size > maxSize) {\n const error = lang.fileTooLarge(format.fileSize(maxSize));\n return { ...base, status: 'error', error, rejected: true };\n }\n return { ...base, status: 'selected' };\n });\n if (!multiple) value.forEach((item) => controllers.get(item.id)?.abort());\n const kept = multiple ? value : [];\n const room = maxFiles == null ? entries.length : Math.max(0, maxFiles - kept.length);\n const added = (multiple ? entries : entries.slice(-1)).slice(0, room);\n value = [...kept, ...added];\n added.filter((item) => item.status === 'selected').forEach((item) => void start(item));\n }\n\n // 图片墙里选的文件的本地地址:用完(移除、卸载)回收\n const previews = new Map<string, string>();\n const previewOf = (item: UploadFile) => {\n if (item.url) return item.url;\n if (!item.file || !item.file.type.startsWith('image/')) return undefined;\n let url = previews.get(item.id);\n if (!url) previews.set(item.id, (url = URL.createObjectURL(item.file)));\n return url;\n };\n watch(\n () => value,\n (list) => {\n const kept = new Set(list.map((item) => item.id));\n for (const [id, url] of previews)\n if (!kept.has(id)) {\n URL.revokeObjectURL(url);\n previews.delete(id);\n }\n },\n );\n onBeforeUnmount(() => previews.forEach((url) => URL.revokeObjectURL(url)));\n\n let wall = _state.raw<HTMLElement | null>(null);\n const sortableWall = useSortable<UploadFile>({\n items: () => value,\n getKey: (item) => item.id,\n getLabel: (item) => item.name,\n onChange: (next) => (value = next),\n container: () => wall,\n orientation: () => 'horizontal',\n disabled: () => !sortable || control().readonly || control().disabled,\n });\n\n /** 粘贴:剪贴板里的文件(截图是 image/png)按 accept 分开,不符合的照常列出、带错误 */\n function onPaste(event: ClipboardEvent) {\n const state = control();\n if (!pasteable || state.disabled || state.readonly) return;\n const files = [...(event.clipboardData?.files ?? [])];\n if (files.length === 0) return;\n event.preventDefault();\n const accepted = files.filter((file) => matchesAccept(file, accept));\n const rejected = files.filter((file) => !matchesAccept(file, accept));\n if (accepted.length) add(accepted);\n if (rejected.length) add(rejected, true);\n }\n\n // 隐藏的 file input 带着全部可提交的文件:原生提交、FormData 拿得到\n _effect(() => {\n if (!hidden || typeof DataTransfer === 'undefined') return;\n const transfer = new DataTransfer();\n for (const item of value) if (item.file && !item.rejected) transfer.items.add(item.file);\n hidden.files = transfer.files;\n });\n\n function renderItem(item: UploadFile) {\n const state = control();\n const own = typeof propsItem === 'function' ? propsItem(item) : propsItem;\n const fileName = item.name;\n const failed = item.status === 'error';\n return (\n <li\n key={item.id}\n {...mergeAttrs<'li'>({ sx: [itemStyles.row, uploadStyles.item] }, own)}\n data-state={item.status}\n >\n <Icon\n {...mergePartProps<IconProps>(\n {\n icon: failed ? CircleAlert : item.status === 'done' ? CircleCheck : FileIcon,\n sx: [\n uploadStyles.icon,\n failed && uploadStyles.error,\n item.status === 'done' && uploadStyles.done,\n ],\n },\n propsIcon,\n )}\n />\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.body }, propsBody)}>\n <span {...mergeAttrs<'span'>({ sx: uploadStyles.name }, propsName)}>\n {item.url ? (\n <Link href={item.url} target=\"_blank\">\n {fileName}\n </Link>\n ) : (\n fileName\n )}\n </span>\n {item.status === 'uploading' ? (\n <Progress\n {...mergePartProps<ProgressProps>(\n { size: 'xs', sx: uploadStyles.progress },\n propsProgress,\n {\n value: item.progress == null ? null : Math.round(item.progress * 100),\n 'aria-label': fileName,\n },\n )}\n />\n ) : (\n <span\n {...mergeAttrs<'span'>(\n { sx: [uploadStyles.meta, failed && uploadStyles.error] },\n propsMeta,\n )}\n >\n {failed ? item.error : item.size != null && format.fileSize(item.size)}\n {item.status === 'done' && <VisuallyHidden> {lang.uploadDone}</VisuallyHidden>}\n </span>\n )}\n </div>\n {failed && uploader() && !item.rejected && !state.readonly && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: RotateCw,\n variant: 'ghost',\n size: 'sm',\n // 名称带文件名、每项不同:类型里不让使用方覆盖(同一个值会让各项的按钮同名)\n 'aria-label': lang.uploadRetry(fileName),\n },\n propsRetry,\n { onClick: () => void start(item) },\n )}\n />\n )}\n {!state.readonly && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: X,\n variant: 'ghost',\n size: 'sm',\n 'aria-label': lang.uploadRemove(fileName),\n },\n propsRemove,\n { disabled: state.disabled, onClick: () => remove(item.id) },\n )}\n />\n )}\n </li>\n );\n }\n\n /** 图片墙的一格:缩略图(点开看大图)、上传进度或错误、把手、重试与移除 */\n function renderCard(item: UploadFile) {\n const state = control();\n const failed = item.status === 'error';\n const src = previewOf(item);\n return (\n <div\n key={item.id}\n {...mergeAttrs<'div'>(\n {\n sx: [\n uploadStyles.card,\n uploadDynamicStyles.square(thumbnailSize),\n failed && uploadStyles.cardError,\n ],\n },\n sortableWall.itemProps(item.id),\n { role: 'listitem' },\n )}\n data-state={item.status}\n >\n {src && !item.rejected ? (\n <Image\n src={src}\n alt={item.name}\n width={thumbnailSize - 2}\n height={thumbnailSize - 2}\n radius=\"none\"\n preview={{ caption: item.name, download: item.name }}\n />\n ) : (\n <div {...css.attrs(uploadStyles.placeholder)}>\n <Icon icon={failed ? CircleAlert : FileIcon} sx={failed && uploadStyles.error} />\n {item.name}\n </div>\n )}\n {item.status === 'uploading' && (\n <div {...css.attrs(uploadStyles.overlay)}>\n <Progress\n {...mergePartProps<ProgressProps>({ size: 'xs' }, propsProgress, {\n value: item.progress == null ? null : Math.round(item.progress * 100),\n 'aria-label': item.name,\n })}\n />\n </div>\n )}\n {failed && src && !item.rejected && (\n <div {...css.attrs(uploadStyles.overlay)} title={item.error}>\n {item.error}\n </div>\n )}\n {item.status === 'done' && <VisuallyHidden>{lang.uploadDone}</VisuallyHidden>}\n {!state.readonly && (\n <div {...css.attrs(uploadStyles.actions)}>\n {sortable && (\n <ButtonBase\n sx={uploadStyles.handle}\n ripple={false}\n disabled={state.disabled}\n aria-label={lang.sortableHandle(item.name)}\n {...sortableWall.handleProps(item.id)}\n >\n <Icon icon={GripVertical} />\n </ButtonBase>\n )}\n {failed && uploader() && !item.rejected && (\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: RotateCw,\n variant: 'ghost',\n size: 'xs',\n sx: uploadStyles.action,\n 'aria-label': lang.uploadRetry(item.name),\n },\n propsRetry,\n { onClick: () => void start(item) },\n )}\n />\n )}\n <IconButton\n {...mergePartProps<IconButtonProps>(\n {\n icon: X,\n variant: 'ghost',\n size: 'xs',\n sx: uploadStyles.action,\n 'aria-label': lang.uploadRemove(item.name),\n },\n propsRemove,\n { disabled: state.disabled, onClick: () => remove(item.id) },\n )}\n />\n </div>\n )}\n </div>\n );\n }\n\n /** 选文件的区域:列表模式在上方,图片墙模式是最后一格 */\n function renderDrop(picture: boolean) {\n const state = control();\n const full = maxFiles != null && multiple && value.length >= maxFiles;\n if (state.readonly || (picture && full)) return null;\n const hint = pasteable ? lang.uploadPasteHint : undefined;\n const props = mergePartProps<FileDropProps>(\n {\n accept,\n multiple,\n disabled: state.disabled,\n invalid: state.invalid,\n // 选好的文件不在这个输入框里(它选完就清空):已有文件时不再原生必填,免得表单交不了\n required: state.required && value.length === 0,\n description: picture\n ? undefined\n : hint\n ? [description, description != null && ' · ', hint]\n : description,\n propsRoot: picture\n ? { sx: [uploadStyles.addCard, uploadDynamicStyles.square(thumbnailSize)] }\n : undefined,\n },\n propsDrop,\n {\n onFiles: (files: File[]) => add(files),\n onReject: (files: File[]) => add(files, true),\n },\n );\n // 列表模式不传子元素:FileDrop 用默认的图标、提示与说明(写了 undefined 也算传了,会把默认内容换掉)\n if (!picture) return <FileDrop {...props} />;\n return (\n <FileDrop {...props}>\n <Icon icon={ImagePlus} />\n {lang.uploadAddImage}\n </FileDrop>\n );\n }\n\n return () => {\n const state = control();\n if (listType === 'picture')\n return (\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.root }, rest, { onPaste })}>\n <ImageGroup sx={uploadStyles.wall}>\n {/* 列表里只有缩略图(“添加图片”与预览不是列表项);display: contents,缩略图仍和“添加图片”排在一行 */}\n <div\n ref={_toRef(wall)}\n role=\"list\"\n // 状态变化(失败、完成)由读屏播报\n aria-live=\"polite\"\n {...css.attrs(uploadStyles.wallList)}\n >\n {value.map(renderCard)}\n </div>\n {renderDrop(true)}\n </ImageGroup>\n {pasteable && !state.readonly && (\n <span {...css.attrs(uploadStyles.meta)}>\n {[description, description != null && ' · ', lang.uploadPasteHint]}\n </span>\n )}\n {sortable && (\n <>\n <VisuallyHidden id={sortableWall.instructionsId}>\n {lang.sortableInstructions}\n </VisuallyHidden>\n <VisuallyHidden aria-live=\"assertive\">{sortableWall.announcement}</VisuallyHidden>\n </>\n )}\n {name != null && (\n <input\n ref={_toRef(hidden)}\n type=\"file\"\n name={name}\n multiple\n hidden\n tabindex={-1}\n aria-hidden=\"true\"\n />\n )}\n </div>\n );\n return (\n <div {...mergeAttrs<'div'>({ sx: uploadStyles.root }, rest, { onPaste })}>\n {renderDrop(false)}\n {name != null && (\n <input\n ref={_toRef(hidden)}\n type=\"file\"\n name={name}\n multiple\n hidden\n tabindex={-1}\n aria-hidden=\"true\"\n />\n )}\n {value.length > 0 && (\n // 状态变化(失败、完成)由读屏播报\n <GridList\n {...mergePartProps<GridProps<'ul'>>({ gap: 'xs' }, propsList)}\n aria-live=\"polite\"\n >\n {value.map(renderItem)}\n </GridList>\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* 组件只画外观。勾选状态的样式由组件按自己的状态加(样式里不写兄弟选择器)。尺寸用 em。
|
|
10
10
|
* 部件与样式见 choiceRecipe(createUi / Provider 的 styles.Choice 按它定制)。
|
|
11
11
|
*/
|
|
12
|
-
import
|
|
12
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
13
13
|
import type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
14
14
|
import { useRecipe, type PartLayer } from '../config/styles';
|
|
15
15
|
import { type StatusTone } from '../utils/style/tone-styles';
|
|
@@ -4,7 +4,7 @@ import { fontSizeStyles } from "../utils/style/typography.js";
|
|
|
4
4
|
import { useRecipe } from "../config/styles.js";
|
|
5
5
|
import { toneFillStyles } from "../utils/style/tone-styles.js";
|
|
6
6
|
import { nextTick } from "vue";
|
|
7
|
-
import
|
|
7
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
8
8
|
//#region src/input/choice-styles.ts
|
|
9
9
|
/**
|
|
10
10
|
* 勾选类控件(Checkbox、Radio、Switch)共用的样式与结构:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"choice-styles.js","names":[],"sources":["../../src/input/choice-styles.ts"],"sourcesContent":["/**\n * 勾选类控件(Checkbox、Radio、Switch)共用的样式与结构:\n *\n * label(Root,整块可点)> span(Control,叠放层)> input(原生,appearance: none 画成方框 / 圆 / 轨道)\n * + 标记(图标或滑块,叠在 input 上,不接收指针)\n * > span(Label,文字)\n *\n * 用原生 input:键盘(空格切换、单选组的方向键)、表单提交与重置、label 点击、读屏语义都是浏览器的;\n * 组件只画外观。勾选状态的样式由组件按自己的状态加(样式里不写兄弟选择器)。尺寸用 em。\n * 部件与样式见 choiceRecipe(createUi / Provider 的 styles.Choice 按它定制)。\n */\nimport
|
|
1
|
+
{"version":3,"file":"choice-styles.js","names":[],"sources":["../../src/input/choice-styles.ts"],"sourcesContent":["/**\n * 勾选类控件(Checkbox、Radio、Switch)共用的样式与结构:\n *\n * label(Root,整块可点)> span(Control,叠放层)> input(原生,appearance: none 画成方框 / 圆 / 轨道)\n * + 标记(图标或滑块,叠在 input 上,不接收指针)\n * > span(Label,文字)\n *\n * 用原生 input:键盘(空格切换、单选组的方向键)、表单提交与重置、label 点击、读屏语义都是浏览器的;\n * 组件只画外观。勾选状态的样式由组件按自己的状态加(样式里不写兄弟选择器)。尺寸用 em。\n * 部件与样式见 choiceRecipe(createUi / Provider 的 styles.Choice 按它定制)。\n */\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { nextTick } from 'vue';\nimport { useDefaults } from '../config/defaults';\nimport { useRecipe, type PartLayer } from '../config/styles';\nimport { toneFillStyles, type StatusTone } from '../utils/style/tone-styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { t } from '../config/theme/tokens';\n\n/** 勾选类控件的外观选项;可以用 createUi / Provider 的 defaults.Choice 统一改默认值 */\nexport interface ChoiceOptions {\n /** 字号档位(方框、圆、开关随之缩放);不写时继承上下文字号 */\n size?: TextSize;\n /**\n * 选中时的色调(与 Button、Badge 等同一套)\n * @default 'accent'\n */\n tone?: StatusTone;\n}\n\n/**\n * 勾选类控件的配方:部件 root(外层 label,整块可点)、control(叠放层)、input(原生 input)、\n * indicator(标记:对勾、圆点、开关滑块)、label(文字)、description(文字下方的说明)、group(复选组、单选组)。\n * 档位是外层的只读、不可用与组的排列方向;勾选、出错见 choiceInputStyles\n */\nexport const choiceRecipe = css.recipe({\n name: 'Choice',\n parts: ['root', 'control', 'input', 'indicator', 'label', 'description', 'group'],\n base: {\n // 控件与文字一行,整块可点;点击区域不小于 24px(WCAG 2.5.8)\n root: {\n display: 'inline-flex',\n alignItems: 'flex-start',\n gap: '_sm',\n minHeight: '_sizes.minTarget',\n lineHeight: '_normal',\n color: '_text',\n cursor: 'pointer',\n userSelect: 'none',\n },\n // input 与标记放在同一个网格格子里;与第一行文字垂直居中(行高 1.5em)\n control: {\n display: 'inline-grid',\n placeItems: 'center',\n flexShrink: 0,\n minHeight: '1.5em',\n },\n // 去掉浏览器外观,由各组件给出形状;焦点环用 focusRingStyles.tight(排在它后面)\n input: {\n gridArea: '1 / 1',\n appearance: 'none',\n boxSizing: 'border-box',\n margin: 0,\n borderWidth: '_sm',\n borderStyle: 'solid',\n borderColor: '_borderStrong',\n backgroundColor: '_surface',\n cursor: 'inherit',\n transition: `background-color ${t.durations.sm} ${t.easings.standard}, border-color ${t.durations.sm} ${t.easings.standard}`,\n },\n // 叠在 input 上,点击穿透到 input\n indicator: { gridArea: '1 / 1', pointerEvents: 'none' },\n // 有说明时文字在上、说明在下\n label: { minWidth: 0, display: 'grid' },\n // 次要颜色、小一号\n description: { color: '_textMuted', fontSize: '0.875em' },\n },\n variants: {\n // 只读:外观照常(看得清选了什么),只是不像能点\n readonly: { true: { root: { cursor: 'default' } } },\n disabled: { true: { root: { opacity: '_disabled', cursor: 'not-allowed' } } },\n orientation: {\n vertical: { group: { display: 'flex', flexDirection: 'column', gap: '_xs' } },\n horizontal: {\n group: { display: 'flex', flexWrap: 'wrap', columnGap: '_lg', rowGap: '_xs' },\n },\n },\n },\n});\n\n/** 勾选类控件的部件(createUi / Provider 的 styles.Choice 按它定制) */\nexport type ChoicePart = (typeof choiceRecipe.parts)[number];\n\n/**\n * 原生 input 的勾选、出错样式:排在各组件的形状(方框、圆、轨道)之后,所以不放进配方——\n * 开关的轨道把描边设成透明,出错的红色描边要盖过它\n */\nexport const choiceInputStyles = css.create({\n /** 已勾选(或部分勾选):色调的实底色,见 choiceParts */\n checked: { borderColor: 'var(--tone-fill)', backgroundColor: 'var(--tone-fill)' },\n invalid: { borderColor: '_danger', outlineColor: '_danger' },\n});\n\n/** 合并后的外观:tone 总有值,size 不写时继承字号 */\nexport type ChoiceAppearance = Pick<ChoiceOptions, 'size'> &\n Required<Pick<ChoiceOptions, 'tone'>> & {\n /** 勾选类控件的配方,带上 createUi / Provider 里 styles.Choice 的定制 */\n recipe: ReturnType<typeof useRecipe<ChoicePart, unknown>>;\n };\n\n/** 勾选类控件的外观:显式写的 > defaults.Choice > 默认。在 setup 里调用,返回的函数在渲染时调用 */\nexport function useChoiceAppearance(read: () => ChoiceOptions): () => ChoiceAppearance {\n const recipe = useRecipe(choiceRecipe);\n const appearance = useDefaults('Choice', read, { tone: 'accent' });\n return () => ({ ...appearance(), recipe });\n}\n\n/** 各部件交给 mergeAttrs / mergeProps 的默认层:样式与部件标记(data-scope=\"choice\") */\nexport type ChoiceParts = {\n readonly [Part in ChoicePart]: Omit<PartLayer, 'sx'> & { readonly sx: SxStyles };\n};\n\n/**\n * 外观与状态 → 各部件的默认层。外层 label 在配方之后叠上色调(经 toneFillStyles 的变量传给方框、圆点、轨道)\n * 与字号\n */\nexport function choiceParts(\n { size, tone, recipe }: ChoiceAppearance,\n { disabled, readonly }: { disabled: boolean; readonly: boolean },\n): ChoiceParts {\n const parts = recipe({ readonly, disabled });\n return {\n ...parts,\n root: {\n ...parts.root,\n sx: [parts.root.sx, toneFillStyles[tone], size && fontSizeStyles[size]],\n },\n };\n}\n\nconst ARROW_KEYS = new Set(['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']);\n\n/**\n * 只读的原生勾选框要拦住的事件:点击(空格键也是点击)不改勾选,单选组的方向键不换选中项。\n * 原生 checkbox 没有 readonly 属性;这样焦点照常能到,读屏经 aria-readonly 念“只读”,值也照常随表单提交\n */\nexport const readonlyChoiceHandlers = {\n onClick: (event: Event) => event.preventDefault(),\n onKeydown: (event: KeyboardEvent) => {\n if (ARROW_KEYS.has(event.key)) event.preventDefault();\n },\n};\n\n/**\n * 受控的勾选:改值之后,父级没接受(或改成了别的值)时把原生 input 的 checked 改回去。\n * 浏览器在点击时已经改了 checked(单选还取消了同组原来选中的那个),而 Vue 比较的是 prop:\n * 父级的值没变就不会去动 DOM,界面和值就对不上了(切换要等接口的开关、只能选几项的复选框)\n */\nexport function syncChecked(\n inputs: readonly HTMLInputElement[],\n isChecked: (input: HTMLInputElement) => boolean,\n): void {\n void nextTick(() => {\n for (const input of inputs) {\n const checked = isChecked(input);\n if (input.checked !== checked) input.checked = checked;\n }\n });\n}\n\n/** 复选组、单选组的排列方向 */\nexport interface ChoiceOrientations {\n /** 竖排(默认) */\n vertical: unknown;\n /** 横排,放不下时换行 */\n horizontal: unknown;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAoCA,IAAa,eAAe,IAAI,OAAO;CACrC,MAAM;CACN,OAAO;EAAC;EAAQ;EAAW;EAAS;EAAa;EAAS;EAAe;CAAO;CAChF,MAAM;EAEJ,MAAM;GACJ,SAAS;GACT,YAAY;GACZ,KAAK;GACL,WAAW;GACX,YAAY;GACZ,OAAO;GACP,QAAQ;GACR,YAAY;EACd;EAEA,SAAS;GACP,SAAS;GACT,YAAY;GACZ,YAAY;GACZ,WAAW;EACb;EAEA,OAAO;GACL,UAAU;GACV,YAAY;GACZ,WAAW;GACX,QAAQ;GACR,aAAa;GACb,aAAa;GACb,aAAa;GACb,iBAAiB;GACjB,QAAQ;GACR,YAAY,oBAAoB,EAAE,UAAU,GAAE,GAAI,EAAE,QAAQ,SAAQ,iBAAkB,EAAE,UAAU,GAAE,GAAI,EAAE,QAAQ;EACpH;EAEA,WAAW;GAAE,UAAU;GAAS,eAAe;EAAO;EAEtD,OAAO;GAAE,UAAU;GAAG,SAAS;EAAO;EAEtC,aAAa;GAAE,OAAO;GAAc,UAAU;EAAU;CAC1D;CACA,UAAU;EAER,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,UAAU,EAAE,EAAE;EAClD,UAAU,EAAE,MAAM,EAAE,MAAM;GAAE,SAAS;GAAa,QAAQ;EAAc,EAAE,EAAE;EAC5E,aAAa;GACX,UAAU,EAAE,OAAO;IAAE,SAAS;IAAQ,eAAe;IAAU,KAAK;GAAM,EAAE;GAC5E,YAAY,EACV,OAAO;IAAE,SAAS;IAAQ,UAAU;IAAQ,WAAW;IAAO,QAAQ;GAAM,EAC9E;EACF;CACF;AACF,CAAC;;;;;AASD,IAAa,oBAAoB,IAAI,OAAO;;CAE1C,SAAS;EAAE,aAAa;EAAoB,iBAAiB;CAAmB;CAChF,SAAS;EAAE,aAAa;EAAW,cAAc;CAAU;AAC7D,CAAC;;AAUD,SAAgB,oBAAoB,MAAmD;CACrF,MAAM,SAAS,UAAU,YAAY;CACrC,MAAM,aAAa,YAAY,UAAU,MAAM,EAAE,MAAM,SAAS,CAAC;CACjE,cAAc;EAAE,GAAG,WAAW;EAAG;CAAO;AAC1C;;;;;AAWA,SAAgB,YACd,EAAE,MAAM,MAAM,UACd,EAAE,UAAU,YACC;CACb,MAAM,QAAQ,OAAO;EAAE;EAAU;CAAS,CAAC;CAC3C,OAAO;EACL,GAAG;EACH,MAAM;GACJ,GAAG,MAAM;GACT,IAAI;IAAC,MAAM,KAAK;IAAI,eAAe;IAAO,QAAQ,eAAe;GAAK;EACxE;CACF;AACF;AAEA,IAAM,6BAAa,IAAI,IAAI;CAAC;CAAW;CAAa;CAAa;AAAY,CAAC;;;;;AAM9E,IAAa,yBAAyB;CACpC,UAAU,UAAiB,MAAM,eAAe;CAChD,YAAY,UAAyB;EACnC,IAAI,WAAW,IAAI,MAAM,GAAG,GAAG,MAAM,eAAe;CACtD;AACF;;;;;;AAOA,SAAgB,YACd,QACA,WACM;CACN,eAAoB;EAClB,KAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,UAAU,UAAU,KAAK;GAC/B,IAAI,MAAM,YAAY,SAAS,MAAM,UAAU;EACjD;CACF,CAAC;AACH"}
|
package/dist/input/control.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 外壳是包着原生 input 的 div:边框、悬停、焦点环(:focus-within)、出错、不可用、只读都画在外壳上,
|
|
5
5
|
* input 本身透明无边框,所以图标、清除按钮、步进按钮可以放进框里。尺寸用 em,随 size 缩放(COMPONENTS.md §3)。
|
|
6
6
|
*/
|
|
7
|
-
import
|
|
7
|
+
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
8
8
|
import type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
9
9
|
import type { VNodeChild } from 'vue';
|
|
10
10
|
import { type PresetIconButtonProps } from '../base/CloseButton';
|
package/dist/input/control.js
CHANGED
|
@@ -8,7 +8,7 @@ import { Icon } from "../base/Icon.js";
|
|
|
8
8
|
import { AttachedContext, attachedStyles } from "../utils/style/attached.js";
|
|
9
9
|
import { ClearButton } from "../base/CloseButton.js";
|
|
10
10
|
import { createVNode } from "vue";
|
|
11
|
-
import
|
|
11
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
12
12
|
//#region src/input/control.tsx
|
|
13
13
|
/**
|
|
14
14
|
* 输入框外壳:配方、外观选项、前置图标与交互小工具。TextField、Textarea、NumberField、Select、Combobox、
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.js","names":["_createVNode"],"sources":["../../src/input/control.tsx"],"sourcesContent":["/**\n * 输入框外壳:配方、外观选项、前置图标与交互小工具。TextField、Textarea、NumberField、Select、Combobox、\n * TagsInput 与日期输入框共用。\n * 外壳是包着原生 input 的 div:边框、悬停、焦点环(:focus-within)、出错、不可用、只读都画在外壳上,\n * input 本身透明无边框,所以图标、清除按钮、步进按钮可以放进框里。尺寸用 em,随 size 缩放(COMPONENTS.md §3)。\n */\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { ClearButton, type PresetIconButtonProps } from '../base/CloseButton';\nimport { Icon, type IconData, type IconProps } from '../base/Icon';\nimport { useDefaults } from '../config/defaults';\nimport { useRecipe, type PartLayer } from '../config/styles';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport {\n AttachedContext,\n attachedStyles,\n type AttachedOrientations,\n} from '../utils/style/attached';\nimport { focusRingStyles, radiusStyles, type Radius } from '../utils/style/styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { t } from '../config/theme/tokens';\n\n/** 输入框的样式 */\nexport interface ControlVariants {\n /** 表面色加描边(默认) */\n surface: unknown;\n /** 浅色底,没有描边:表单很密、或放在有底色的区域里 */\n soft: unknown;\n}\n\n/** 输入框的外观选项;可以用 createUi / Provider 的 defaults.Input 统一改默认值 */\nexport interface ControlOptions {\n /** 样式,默认 surface */\n variant?: keyof ControlVariants;\n /** 字号档位,内部尺寸随之缩放;不写时继承上下文字号 */\n size?: TextSize;\n /** 圆角,与按钮同一套档位,默认 md;搜索框常用 full(胶囊形) */\n radius?: Radius;\n}\n\n/** 框里最前面的图标(搜索、日历、地球……):各种输入框共有 */\nexport interface ControlIconOptions {\n /** 前置图标 */\n icon?: IconData;\n /** 前置图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n}\n\n/** 外壳的状态:出错、不可用、只读 */\nexport interface ControlState {\n /** 校验未通过:红色描边与焦点环 */\n invalid?: boolean;\n /** 不可用:变淡 */\n disabled?: boolean;\n /** 只读:底色变浅,不显示悬停 */\n readonly?: boolean;\n}\n\n/**\n * 输入框外壳的配方:部件 root(外壳 div)、input(原生 input / textarea)、icon(前后的图标)、\n * affix(前后缀文字)、button(框里的小按钮:清除、显示密码、步进)。\n * 档位是样式(variant)、在 ControlGroup 里的方向(attached)与外壳的状态;圆角、相连、字号用共用的样式表,\n * 由 controlParts 叠在配方之后\n */\nexport const inputRecipe = css.recipe({\n name: 'Input',\n parts: ['root', 'input', 'icon', 'affix', 'button'],\n base: {\n root: {\n boxSizing: 'border-box',\n display: 'inline-flex',\n alignItems: 'center',\n gap: '_sm',\n minWidth: 0,\n minHeight: `max(${t.sizes.control}, ${t.sizes.minTarget})`,\n paddingInline: '_md',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: { default: '_border', ':hover': '_borderStrong' },\n borderRadius: '_md',\n backgroundColor: '_surface',\n color: '_text',\n lineHeight: '_normal',\n cursor: 'text',\n transition: `border-color ${t.durations.sm} ${t.easings.standard}`,\n },\n // 原生 input / textarea:透明、无边框,占满剩余宽度,字体继承外壳。\n // 参与基线对齐、高度撑满外壳:外壳(flex)的基线取输入框文字的基线,而不是排在前面的图标的底边,\n // 左标签(按基线对齐)才与输入的文字在同一条线上;原生输入框自己把文字竖直居中\n input: {\n alignSelf: 'baseline',\n boxSizing: 'border-box',\n flexGrow: 1,\n minWidth: 0,\n minHeight: `calc(max(${t.sizes.control}, ${t.sizes.minTarget}) - 2 * ${t.borderWidths.xs})`,\n margin: 0,\n paddingBlock: '_xs',\n paddingInline: 0,\n borderWidth: 0,\n outlineStyle: 'none',\n backgroundColor: 'transparent',\n color: 'inherit',\n font: 'inherit',\n cursor: 'inherit',\n '::placeholder': { color: '_textPlaceholder', opacity: 1 },\n },\n // 前后的图标:次要颜色\n icon: { flexShrink: 0, color: '_textMuted' },\n // 前后缀文字(如 https://、元):次要颜色,不换行\n affix: { flexShrink: 0, color: '_textMuted', whiteSpace: 'nowrap' },\n // 框里的小按钮:比独立的图标按钮紧凑,仍不小于 24px 的点击区域\n button: {\n flexShrink: 0,\n width: `max(1.5em, ${t.sizes.minTarget})`,\n minHeight: `max(1.5em, ${t.sizes.minTarget})`,\n marginInline: `calc(-1 * ${t.space.xs})`,\n color: '_textMuted',\n },\n },\n // 档位的先后就是覆盖的先后:只读、出错依次盖过样式的描边与底色\n variants: {\n variant: {\n surface: {},\n soft: {\n root: {\n borderColor: { default: 'transparent', ':hover': 'transparent' },\n backgroundColor: '_fill',\n },\n },\n },\n // 在横排的 ControlGroup 里:输入框分掉剩余宽度(选择框按内容宽,见 selectStyles.root)\n attached: { horizontal: { root: { flexGrow: 1 } }, vertical: {} },\n readonly: {\n true: {\n root: {\n borderColor: { default: '_borderMuted', ':hover': '_borderMuted' },\n backgroundColor: '_fill',\n },\n },\n },\n invalid: {\n true: {\n root: {\n borderColor: { default: '_danger', ':hover': '_danger' },\n outlineColor: '_danger',\n },\n },\n },\n disabled: { true: { root: { opacity: '_disabled', cursor: 'not-allowed' } } },\n // 多行(Textarea):内容从顶部开始,上下也留内边距\n multiline: { true: { root: { alignItems: 'stretch', paddingBlock: '_xs' } } },\n },\n});\n\n/** 输入框外壳的部件(createUi / Provider 的 styles.Input 按它定制) */\nexport type InputPart = (typeof inputRecipe.parts)[number];\n\n/**\n * 外壳各部件交给 mergeAttrs / mergeProps 的默认层:样式与部件标记(data-scope=\"input\")。\n * 要加样式时写 `{ ...s.root, sx: [s.root.sx, 别的] }`\n */\nexport type ControlParts = {\n readonly [Part in InputPart]: Omit<PartLayer, 'sx'> & { readonly sx: SxStyles };\n};\n\n/** 外壳里的图标(前置、后置):次要颜色、不被挤压;没有图标时不渲染 */\nexport function controlIcon(\n parts: ControlParts,\n icon: IconData | undefined,\n props?: Partial<IconProps>,\n): VNodeChild {\n return icon ? <Icon {...mergePartProps<IconProps>({ ...parts.icon, icon }, props)} /> : null;\n}\n\n/** 外壳里的清空按钮:圆形、名称取语言包(清空);有值、可编辑时才渲染由调用方决定 */\nexport function controlClear(\n parts: ControlParts,\n props: Partial<PresetIconButtonProps> | undefined,\n onClick: () => void,\n): VNodeChild {\n return (\n <ClearButton\n {...mergePartProps<PresetIconButtonProps>({ ...parts.button, radius: 'full' }, props, {\n onClick,\n })}\n />\n );\n}\n\n/**\n * 外壳里的前缀、后缀文字(币种、单位):用指向输入框的 label,读屏把单位念进名称(“年度预算 万元”),\n * 不可用时也算作不可用控件的文字(不要求对比度);没有内容时不渲染\n */\nexport function controlAffix(\n parts: ControlParts,\n content: VNodeChild,\n inputId: string,\n props?: PartProps<'label'>,\n): VNodeChild {\n return content == null ? null : (\n <label {...mergeAttrs<'label'>(parts.affix, props, { for: inputId })}>{content}</label>\n );\n}\n\n/** 合并后的外观(默认值已填上);在 ControlGroup 里时带上相连的方向 */\nexport type ControlAppearance = Required<Pick<ControlOptions, 'variant' | 'radius'>> &\n Pick<ControlOptions, 'size'> & {\n attached?: keyof AttachedOrientations;\n /** 外壳的配方,带上 createUi / Provider 里 styles.Input 的定制 */\n recipe: ReturnType<typeof useRecipe<InputPart, unknown>>;\n };\n\n/**\n * 输入框的外观:显式写的 prop > createUi / Provider 的 defaults.Input > 默认(surface)。\n * 在 setup 里调用,返回的函数在渲染时调用\n */\nexport function useControlAppearance(read: () => ControlOptions): () => ControlAppearance {\n const group = AttachedContext.inject(null);\n const recipe = useRecipe(inputRecipe);\n const appearance = useDefaults('Input', read, { variant: 'surface', radius: 'md' });\n return () => ({ ...appearance(), attached: group?.orientation, recipe });\n}\n\n/**\n * 外观与状态 → 外壳各部件的默认层;multiline 给 Textarea。\n * 外壳在配方之后叠上圆角、相连、字号;焦点环排在配方之前,出错档位的红色焦点环才盖得过它\n */\nexport function controlParts(\n { variant, size, radius, attached, recipe }: ControlAppearance,\n { invalid, disabled, readonly }: ControlState,\n multiline = false,\n): ControlParts {\n const parts = recipe({ variant, attached, readonly, invalid, disabled, multiline });\n return {\n ...parts,\n root: {\n ...parts.root,\n sx: [\n focusRingStyles.within,\n parts.root.sx,\n radiusStyles[radius],\n attached && attachedStyles[attached],\n size && fontSizeStyles[size],\n ],\n },\n };\n}\n\n/** 点在外壳的空白处(内边距、图标、标签上):不是主元素本身,也不是框里的按钮 */\nfunction isShellBlank(target: Element, element: HTMLElement): boolean {\n return target !== element && !element.contains(target) && !target.closest('button');\n}\n\n/**\n * 外壳的 onPointerdown:点在外壳的空白处时把焦点交给主元素(input、触发按钮),不让浏览器把焦点放到别处;\n * 点在主元素或框里的按钮上时照常\n */\nexport function focusOnShell(main: () => HTMLElement | null): (event: PointerEvent) => void {\n return (event) => {\n const element = main();\n if (!element || !isShellBlank(event.target as Element, element)) return;\n event.preventDefault();\n element.focus();\n };\n}\n\n/**\n * 外壳的 onClick:点在外壳的空白处时调用 action(Select、TreeSelect 据此切换打开,与点触发按钮一样)。\n * 不在 pointerdown 里打开:原生 popover=\"auto\" 在 pointerup 时把“按下时还没打开”的浮层当作点在外面关掉\n */\nexport function clickOnShell(\n main: () => HTMLElement | null,\n action: (event: MouseEvent) => void,\n): (event: MouseEvent) => void {\n return (event) => {\n const element = main();\n if (element && isShellBlank(event.target as Element, element)) action(event);\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"control.js","names":["_createVNode"],"sources":["../../src/input/control.tsx"],"sourcesContent":["/**\n * 输入框外壳:配方、外观选项、前置图标与交互小工具。TextField、Textarea、NumberField、Select、Combobox、\n * TagsInput 与日期输入框共用。\n * 外壳是包着原生 input 的 div:边框、悬停、焦点环(:focus-within)、出错、不可用、只读都画在外壳上,\n * input 本身透明无边框,所以图标、清除按钮、步进按钮可以放进框里。尺寸用 em,随 size 缩放(COMPONENTS.md §3)。\n */\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { SxStyles } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { ClearButton, type PresetIconButtonProps } from '../base/CloseButton';\nimport { Icon, type IconData, type IconProps } from '../base/Icon';\nimport { useDefaults } from '../config/defaults';\nimport { useRecipe, type PartLayer } from '../config/styles';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport {\n AttachedContext,\n attachedStyles,\n type AttachedOrientations,\n} from '../utils/style/attached';\nimport { focusRingStyles, radiusStyles, type Radius } from '../utils/style/styles';\nimport { fontSizeStyles, type TextSize } from '../utils/style/typography';\nimport { t } from '../config/theme/tokens';\n\n/** 输入框的样式 */\nexport interface ControlVariants {\n /** 表面色加描边(默认) */\n surface: unknown;\n /** 浅色底,没有描边:表单很密、或放在有底色的区域里 */\n soft: unknown;\n}\n\n/** 输入框的外观选项;可以用 createUi / Provider 的 defaults.Input 统一改默认值 */\nexport interface ControlOptions {\n /** 样式,默认 surface */\n variant?: keyof ControlVariants;\n /** 字号档位,内部尺寸随之缩放;不写时继承上下文字号 */\n size?: TextSize;\n /** 圆角,与按钮同一套档位,默认 md;搜索框常用 full(胶囊形) */\n radius?: Radius;\n}\n\n/** 框里最前面的图标(搜索、日历、地球……):各种输入框共有 */\nexport interface ControlIconOptions {\n /** 前置图标 */\n icon?: IconData;\n /** 前置图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n}\n\n/** 外壳的状态:出错、不可用、只读 */\nexport interface ControlState {\n /** 校验未通过:红色描边与焦点环 */\n invalid?: boolean;\n /** 不可用:变淡 */\n disabled?: boolean;\n /** 只读:底色变浅,不显示悬停 */\n readonly?: boolean;\n}\n\n/**\n * 输入框外壳的配方:部件 root(外壳 div)、input(原生 input / textarea)、icon(前后的图标)、\n * affix(前后缀文字)、button(框里的小按钮:清除、显示密码、步进)。\n * 档位是样式(variant)、在 ControlGroup 里的方向(attached)与外壳的状态;圆角、相连、字号用共用的样式表,\n * 由 controlParts 叠在配方之后\n */\nexport const inputRecipe = css.recipe({\n name: 'Input',\n parts: ['root', 'input', 'icon', 'affix', 'button'],\n base: {\n root: {\n boxSizing: 'border-box',\n display: 'inline-flex',\n alignItems: 'center',\n gap: '_sm',\n minWidth: 0,\n minHeight: `max(${t.sizes.control}, ${t.sizes.minTarget})`,\n paddingInline: '_md',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: { default: '_border', ':hover': '_borderStrong' },\n borderRadius: '_md',\n backgroundColor: '_surface',\n color: '_text',\n lineHeight: '_normal',\n cursor: 'text',\n transition: `border-color ${t.durations.sm} ${t.easings.standard}`,\n },\n // 原生 input / textarea:透明、无边框,占满剩余宽度,字体继承外壳。\n // 参与基线对齐、高度撑满外壳:外壳(flex)的基线取输入框文字的基线,而不是排在前面的图标的底边,\n // 左标签(按基线对齐)才与输入的文字在同一条线上;原生输入框自己把文字竖直居中\n input: {\n alignSelf: 'baseline',\n boxSizing: 'border-box',\n flexGrow: 1,\n minWidth: 0,\n minHeight: `calc(max(${t.sizes.control}, ${t.sizes.minTarget}) - 2 * ${t.borderWidths.xs})`,\n margin: 0,\n paddingBlock: '_xs',\n paddingInline: 0,\n borderWidth: 0,\n outlineStyle: 'none',\n backgroundColor: 'transparent',\n color: 'inherit',\n font: 'inherit',\n cursor: 'inherit',\n '::placeholder': { color: '_textPlaceholder', opacity: 1 },\n },\n // 前后的图标:次要颜色\n icon: { flexShrink: 0, color: '_textMuted' },\n // 前后缀文字(如 https://、元):次要颜色,不换行\n affix: { flexShrink: 0, color: '_textMuted', whiteSpace: 'nowrap' },\n // 框里的小按钮:比独立的图标按钮紧凑,仍不小于 24px 的点击区域\n button: {\n flexShrink: 0,\n width: `max(1.5em, ${t.sizes.minTarget})`,\n minHeight: `max(1.5em, ${t.sizes.minTarget})`,\n marginInline: `calc(-1 * ${t.space.xs})`,\n color: '_textMuted',\n },\n },\n // 档位的先后就是覆盖的先后:只读、出错依次盖过样式的描边与底色\n variants: {\n variant: {\n surface: {},\n soft: {\n root: {\n borderColor: { default: 'transparent', ':hover': 'transparent' },\n backgroundColor: '_fill',\n },\n },\n },\n // 在横排的 ControlGroup 里:输入框分掉剩余宽度(选择框按内容宽,见 selectStyles.root)\n attached: { horizontal: { root: { flexGrow: 1 } }, vertical: {} },\n readonly: {\n true: {\n root: {\n borderColor: { default: '_borderMuted', ':hover': '_borderMuted' },\n backgroundColor: '_fill',\n },\n },\n },\n invalid: {\n true: {\n root: {\n borderColor: { default: '_danger', ':hover': '_danger' },\n outlineColor: '_danger',\n },\n },\n },\n disabled: { true: { root: { opacity: '_disabled', cursor: 'not-allowed' } } },\n // 多行(Textarea):内容从顶部开始,上下也留内边距\n multiline: { true: { root: { alignItems: 'stretch', paddingBlock: '_xs' } } },\n },\n});\n\n/** 输入框外壳的部件(createUi / Provider 的 styles.Input 按它定制) */\nexport type InputPart = (typeof inputRecipe.parts)[number];\n\n/**\n * 外壳各部件交给 mergeAttrs / mergeProps 的默认层:样式与部件标记(data-scope=\"input\")。\n * 要加样式时写 `{ ...s.root, sx: [s.root.sx, 别的] }`\n */\nexport type ControlParts = {\n readonly [Part in InputPart]: Omit<PartLayer, 'sx'> & { readonly sx: SxStyles };\n};\n\n/** 外壳里的图标(前置、后置):次要颜色、不被挤压;没有图标时不渲染 */\nexport function controlIcon(\n parts: ControlParts,\n icon: IconData | undefined,\n props?: Partial<IconProps>,\n): VNodeChild {\n return icon ? <Icon {...mergePartProps<IconProps>({ ...parts.icon, icon }, props)} /> : null;\n}\n\n/** 外壳里的清空按钮:圆形、名称取语言包(清空);有值、可编辑时才渲染由调用方决定 */\nexport function controlClear(\n parts: ControlParts,\n props: Partial<PresetIconButtonProps> | undefined,\n onClick: () => void,\n): VNodeChild {\n return (\n <ClearButton\n {...mergePartProps<PresetIconButtonProps>({ ...parts.button, radius: 'full' }, props, {\n onClick,\n })}\n />\n );\n}\n\n/**\n * 外壳里的前缀、后缀文字(币种、单位):用指向输入框的 label,读屏把单位念进名称(“年度预算 万元”),\n * 不可用时也算作不可用控件的文字(不要求对比度);没有内容时不渲染\n */\nexport function controlAffix(\n parts: ControlParts,\n content: VNodeChild,\n inputId: string,\n props?: PartProps<'label'>,\n): VNodeChild {\n return content == null ? null : (\n <label {...mergeAttrs<'label'>(parts.affix, props, { for: inputId })}>{content}</label>\n );\n}\n\n/** 合并后的外观(默认值已填上);在 ControlGroup 里时带上相连的方向 */\nexport type ControlAppearance = Required<Pick<ControlOptions, 'variant' | 'radius'>> &\n Pick<ControlOptions, 'size'> & {\n attached?: keyof AttachedOrientations;\n /** 外壳的配方,带上 createUi / Provider 里 styles.Input 的定制 */\n recipe: ReturnType<typeof useRecipe<InputPart, unknown>>;\n };\n\n/**\n * 输入框的外观:显式写的 prop > createUi / Provider 的 defaults.Input > 默认(surface)。\n * 在 setup 里调用,返回的函数在渲染时调用\n */\nexport function useControlAppearance(read: () => ControlOptions): () => ControlAppearance {\n const group = AttachedContext.inject(null);\n const recipe = useRecipe(inputRecipe);\n const appearance = useDefaults('Input', read, { variant: 'surface', radius: 'md' });\n return () => ({ ...appearance(), attached: group?.orientation, recipe });\n}\n\n/**\n * 外观与状态 → 外壳各部件的默认层;multiline 给 Textarea。\n * 外壳在配方之后叠上圆角、相连、字号;焦点环排在配方之前,出错档位的红色焦点环才盖得过它\n */\nexport function controlParts(\n { variant, size, radius, attached, recipe }: ControlAppearance,\n { invalid, disabled, readonly }: ControlState,\n multiline = false,\n): ControlParts {\n const parts = recipe({ variant, attached, readonly, invalid, disabled, multiline });\n return {\n ...parts,\n root: {\n ...parts.root,\n sx: [\n focusRingStyles.within,\n parts.root.sx,\n radiusStyles[radius],\n attached && attachedStyles[attached],\n size && fontSizeStyles[size],\n ],\n },\n };\n}\n\n/** 点在外壳的空白处(内边距、图标、标签上):不是主元素本身,也不是框里的按钮 */\nfunction isShellBlank(target: Element, element: HTMLElement): boolean {\n return target !== element && !element.contains(target) && !target.closest('button');\n}\n\n/**\n * 外壳的 onPointerdown:点在外壳的空白处时把焦点交给主元素(input、触发按钮),不让浏览器把焦点放到别处;\n * 点在主元素或框里的按钮上时照常\n */\nexport function focusOnShell(main: () => HTMLElement | null): (event: PointerEvent) => void {\n return (event) => {\n const element = main();\n if (!element || !isShellBlank(event.target as Element, element)) return;\n event.preventDefault();\n element.focus();\n };\n}\n\n/**\n * 外壳的 onClick:点在外壳的空白处时调用 action(Select、TreeSelect 据此切换打开,与点触发按钮一样)。\n * 不在 pointerdown 里打开:原生 popover=\"auto\" 在 pointerup 时把“按下时还没打开”的浮层当作点在外面关掉\n */\nexport function clickOnShell(\n main: () => HTMLElement | null,\n action: (event: MouseEvent) => void,\n): (event: MouseEvent) => void {\n return (event) => {\n const element = main();\n if (element && isShellBlank(event.target as Element, element)) action(event);\n };\n}\n"],"mappings":"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"}
|
package/dist/layout/Affix.d.ts
CHANGED
package/dist/layout/Affix.js
CHANGED
|
@@ -3,7 +3,7 @@ import { mergeAttrs } from "../utils/props.js";
|
|
|
3
3
|
import { useIntersectionObserver } from "../utils/dom/intersection.js";
|
|
4
4
|
import { Fragment, createVNode, ref, shallowRef } from "vue";
|
|
5
5
|
import { _component, childrenProp, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
6
|
-
import
|
|
6
|
+
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
7
7
|
//#region src/layout/Affix.tsx
|
|
8
8
|
/** onChange 换成报告是否贴住 */
|
|
9
9
|
/** 未声明的属性落到 sticky 的 div 上 */
|