@zerodep-dev/vue-tsx-pro-ui 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base/Badge.js +3 -3
- package/dist/base/Badge.js.map +1 -1
- package/dist/base/Can.d.ts +12 -0
- package/dist/base/Can.js +20 -0
- package/dist/base/Can.js.map +1 -0
- package/dist/base/ClientOnly.d.ts +10 -0
- package/dist/base/ClientOnly.js +18 -0
- package/dist/base/ClientOnly.js.map +1 -0
- package/dist/base/CloseButton.js +3 -3
- package/dist/base/CloseButton.js.map +1 -1
- package/dist/base/CodeBlock.js +5 -5
- package/dist/base/CodeBlock.js.map +1 -1
- package/dist/base/CopyButton.js +3 -3
- package/dist/base/CopyButton.js.map +1 -1
- package/dist/base/Icon.js +3 -3
- package/dist/base/Icon.js.map +1 -1
- package/dist/base/Indicator.js +3 -3
- package/dist/base/Indicator.js.map +1 -1
- package/dist/base/StatusDot.js +3 -3
- package/dist/base/StatusDot.js.map +1 -1
- package/dist/base/Tag.js +5 -5
- package/dist/base/Tag.js.map +1 -1
- package/dist/base/button-core.js +4 -4
- package/dist/base/button-core.js.map +1 -1
- package/dist/charts/AreaChart.js +3 -3
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.js +3 -3
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/ChordChart.js +3 -3
- package/dist/charts/ChordChart.js.map +1 -1
- package/dist/charts/ComboChart.js +3 -3
- package/dist/charts/ComboChart.js.map +1 -1
- package/dist/charts/DonutChart.js +3 -3
- package/dist/charts/DonutChart.js.map +1 -1
- package/dist/charts/FunnelChart.js +5 -5
- package/dist/charts/FunnelChart.js.map +1 -1
- package/dist/charts/GraphChart.js +3 -3
- package/dist/charts/GraphChart.js.map +1 -1
- package/dist/charts/LineChart.js +3 -3
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/MapChart.js +7 -7
- package/dist/charts/MapChart.js.map +1 -1
- package/dist/charts/RadarChart.js +16 -15
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/SankeyChart.js +3 -3
- package/dist/charts/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart.js +3 -3
- package/dist/charts/ScatterChart.js.map +1 -1
- package/dist/charts/TimelineChart.js +6 -5
- package/dist/charts/TimelineChart.js.map +1 -1
- package/dist/charts/TreemapChart.js +3 -3
- package/dist/charts/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart.js +3 -3
- package/dist/charts/WaterfallChart.js.map +1 -1
- package/dist/charts/XYChart.js +9 -7
- package/dist/charts/XYChart.js.map +1 -1
- package/dist/charts/frame.js +10 -8
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/single.js +4 -3
- package/dist/charts/single.js.map +1 -1
- package/dist/code-editor/CodeEditor.d.ts +18 -0
- package/dist/code-editor/CodeEditor.js +57 -0
- package/dist/code-editor/CodeEditor.js.map +1 -0
- package/dist/code-editor/editor.d.ts +52 -0
- package/dist/code-editor/editor.js +225 -0
- package/dist/code-editor/editor.js.map +1 -0
- package/dist/code-editor/index.d.ts +9 -0
- package/dist/code-editor/index.js +3 -0
- package/dist/config/Provider.d.ts +3 -1
- package/dist/config/Provider.js +9 -4
- package/dist/config/Provider.js.map +1 -1
- package/dist/config/context.d.ts +18 -0
- package/dist/config/context.js +16 -1
- package/dist/config/context.js.map +1 -1
- package/dist/config/createUi.d.ts +20 -3
- package/dist/config/createUi.js +80 -49
- package/dist/config/createUi.js.map +1 -1
- package/dist/config/lang/en-US.js +21 -3
- package/dist/config/lang/en-US.js.map +1 -1
- package/dist/config/lang/format.d.ts +2 -1
- package/dist/config/lang/format.js +9 -2
- package/dist/config/lang/format.js.map +1 -1
- package/dist/config/lang/lang.d.ts +19 -6
- package/dist/config/lang/lang.js +11 -2
- package/dist/config/lang/lang.js.map +1 -1
- package/dist/config/lang/zh-CN.js +21 -3
- package/dist/config/lang/zh-CN.js.map +1 -1
- package/dist/config/layout/preference.d.ts +43 -0
- package/dist/config/layout/preference.js +108 -0
- package/dist/config/layout/preference.js.map +1 -0
- package/dist/date/Calendar.js +3 -3
- package/dist/date/Calendar.js.map +1 -1
- package/dist/date/CalendarBoard.js +9 -9
- package/dist/date/CalendarBoard.js.map +1 -1
- package/dist/date/CalendarView.js +7 -7
- package/dist/date/CalendarView.js.map +1 -1
- package/dist/date/DateField.js +3 -3
- package/dist/date/DateField.js.map +1 -1
- package/dist/date/DatePicker.js +5 -5
- package/dist/date/DatePicker.js.map +1 -1
- package/dist/date/DateRangePicker.js +5 -5
- package/dist/date/DateRangePicker.js.map +1 -1
- package/dist/date/DateSegmentGroup.js +5 -5
- package/dist/date/DateSegmentGroup.js.map +1 -1
- package/dist/date/QuarterCalendar.js +6 -6
- package/dist/date/QuarterCalendar.js.map +1 -1
- package/dist/date/RangeCalendar.js +3 -3
- package/dist/date/RangeCalendar.js.map +1 -1
- package/dist/date/SegmentedField.js +3 -3
- package/dist/date/SegmentedField.js.map +1 -1
- package/dist/date/TimeField.js +3 -3
- package/dist/date/TimeField.js.map +1 -1
- package/dist/date/TimePicker.js +4 -4
- package/dist/date/TimePicker.js.map +1 -1
- package/dist/date/date-segments.js +1 -1
- package/dist/date/date-segments.js.map +1 -1
- package/dist/date/picker-popover.js +3 -2
- package/dist/date/picker-popover.js.map +1 -1
- package/dist/diagram/Diagram.js +12 -12
- package/dist/diagram/Diagram.js.map +1 -1
- package/dist/diagram/DiagramLanes.js +3 -3
- package/dist/diagram/DiagramLanes.js.map +1 -1
- package/dist/diagram/DiagramMinimap.js +4 -4
- package/dist/diagram/DiagramMinimap.js.map +1 -1
- package/dist/diagram/index.d.ts +2 -1
- package/dist/diagram/index.js +2 -1
- package/dist/diagram/layout.d.ts +57 -0
- package/dist/diagram/layout.js +50 -0
- package/dist/diagram/layout.js.map +1 -0
- package/dist/display/Accordion.js +6 -6
- package/dist/display/Accordion.js.map +1 -1
- package/dist/display/AnimatedNumber.js +4 -4
- package/dist/display/AnimatedNumber.js.map +1 -1
- package/dist/display/Avatar.js +4 -4
- package/dist/display/Avatar.js.map +1 -1
- package/dist/display/Checklist.js +7 -7
- package/dist/display/Checklist.js.map +1 -1
- package/dist/display/Collapse.js +8 -5
- package/dist/display/Collapse.js.map +1 -1
- package/dist/display/Collapsible.js +3 -3
- package/dist/display/Collapsible.js.map +1 -1
- package/dist/display/Descriptions.js +5 -5
- package/dist/display/Descriptions.js.map +1 -1
- package/dist/display/Ellipsis.js +3 -3
- package/dist/display/Ellipsis.js.map +1 -1
- package/dist/display/FieldCompare.js +4 -4
- package/dist/display/FieldCompare.js.map +1 -1
- package/dist/display/Gauge.js +11 -11
- package/dist/display/Gauge.js.map +1 -1
- package/dist/display/Image.js +4 -4
- package/dist/display/Image.js.map +1 -1
- package/dist/display/Marquee.js +3 -3
- package/dist/display/Marquee.js.map +1 -1
- package/dist/display/ProportionBar.js +4 -4
- package/dist/display/ProportionBar.js.map +1 -1
- package/dist/display/Sortable.js +4 -4
- package/dist/display/Sortable.js.map +1 -1
- package/dist/display/Sparkline.js +6 -6
- package/dist/display/Sparkline.js.map +1 -1
- package/dist/display/Stat.js +3 -3
- package/dist/display/Stat.js.map +1 -1
- package/dist/display/Timeline.js +7 -7
- package/dist/display/Timeline.js.map +1 -1
- package/dist/display/Tree.js +10 -10
- package/dist/display/Tree.js.map +1 -1
- package/dist/display/VirtualList.js +7 -7
- package/dist/display/VirtualList.js.map +1 -1
- package/dist/display/Watermark.js +3 -3
- package/dist/display/Watermark.js.map +1 -1
- package/dist/docs-kit/CodeGroup.js +5 -5
- package/dist/docs-kit/CodeGroup.js.map +1 -1
- package/dist/docs-kit/CodePreview.js +6 -6
- package/dist/docs-kit/CodePreview.js.map +1 -1
- package/dist/docs-kit/PropsTable.js +4 -4
- package/dist/docs-kit/PropsTable.js.map +1 -1
- package/dist/feedback/Alert.js +5 -5
- package/dist/feedback/Alert.js.map +1 -1
- package/dist/feedback/Banner.js +5 -5
- package/dist/feedback/Banner.js.map +1 -1
- package/dist/feedback/Empty.js +4 -4
- package/dist/feedback/Empty.js.map +1 -1
- package/dist/feedback/LoadingBar.js +20 -13
- package/dist/feedback/LoadingBar.js.map +1 -1
- package/dist/feedback/LoadingOverlay.js +3 -3
- package/dist/feedback/LoadingOverlay.js.map +1 -1
- package/dist/feedback/Progress.js +14 -14
- package/dist/feedback/Progress.js.map +1 -1
- package/dist/feedback/Result.js +4 -4
- package/dist/feedback/Result.js.map +1 -1
- package/dist/feedback/SkeletonText.js +3 -3
- package/dist/feedback/SkeletonText.js.map +1 -1
- package/dist/feedback/Toast.js +6 -6
- package/dist/feedback/Toast.js.map +1 -1
- package/dist/form/Field.d.ts +7 -0
- package/dist/form/Field.js +20 -9
- package/dist/form/Field.js.map +1 -1
- package/dist/form/Form.js +3 -3
- package/dist/form/Form.js.map +1 -1
- package/dist/form/FormErrorSummary.js +3 -3
- package/dist/form/FormErrorSummary.js.map +1 -1
- package/dist/form/FormSection.js +6 -6
- package/dist/form/FormSection.js.map +1 -1
- package/dist/form/useForm.d.ts +4 -1
- package/dist/form/useForm.js +35 -13
- package/dist/form/useForm.js.map +1 -1
- package/dist/index.d.ts +18 -10
- package/dist/index.js +17 -9
- package/dist/input/Autocomplete.js +3 -3
- package/dist/input/Autocomplete.js.map +1 -1
- package/dist/input/Cascader.js +7 -7
- package/dist/input/Cascader.js.map +1 -1
- package/dist/input/CharacterCount.js +3 -3
- package/dist/input/CharacterCount.js.map +1 -1
- package/dist/input/Checkbox.js +5 -5
- package/dist/input/Checkbox.js.map +1 -1
- package/dist/input/ColorField.js +4 -4
- package/dist/input/ColorField.js.map +1 -1
- package/dist/input/Combobox.js +5 -5
- package/dist/input/Combobox.js.map +1 -1
- package/dist/input/ConditionBuilder.js +15 -14
- package/dist/input/ConditionBuilder.js.map +1 -1
- package/dist/input/FileDrop.js +3 -3
- package/dist/input/FileDrop.js.map +1 -1
- package/dist/input/Listbox.js +9 -9
- package/dist/input/Listbox.js.map +1 -1
- package/dist/input/Mentions.js +4 -4
- package/dist/input/Mentions.js.map +1 -1
- package/dist/input/NumberField.js +3 -3
- package/dist/input/NumberField.js.map +1 -1
- package/dist/input/NumberRangeField.js +5 -5
- package/dist/input/NumberRangeField.js.map +1 -1
- package/dist/input/OtpField.js +5 -5
- package/dist/input/OtpField.js.map +1 -1
- package/dist/input/PeoplePicker.js +6 -6
- package/dist/input/PeoplePicker.js.map +1 -1
- package/dist/input/PeoplePickerPanel.js +15 -15
- package/dist/input/PeoplePickerPanel.js.map +1 -1
- package/dist/input/Radio.js +4 -4
- package/dist/input/Radio.js.map +1 -1
- package/dist/input/Rating.js +5 -5
- package/dist/input/Rating.js.map +1 -1
- package/dist/input/Select.js +5 -5
- package/dist/input/Select.js.map +1 -1
- package/dist/input/SelectedTags.js +4 -4
- package/dist/input/SelectedTags.js.map +1 -1
- package/dist/input/Slider.js +6 -6
- package/dist/input/Slider.js.map +1 -1
- package/dist/input/Switch.js +3 -3
- package/dist/input/Switch.js.map +1 -1
- package/dist/input/TagsInput.js +5 -5
- package/dist/input/TagsInput.js.map +1 -1
- package/dist/input/TextField.js +5 -5
- package/dist/input/TextField.js.map +1 -1
- package/dist/input/Textarea.js +4 -4
- package/dist/input/Textarea.js.map +1 -1
- package/dist/input/ToggleGroup.js +4 -4
- package/dist/input/ToggleGroup.js.map +1 -1
- package/dist/input/Transfer.js +8 -8
- package/dist/input/Transfer.js.map +1 -1
- package/dist/input/TreeSelect.js +7 -7
- package/dist/input/TreeSelect.js.map +1 -1
- package/dist/input/Upload.js +10 -9
- package/dist/input/Upload.js.map +1 -1
- package/dist/input/condition.d.ts +1 -1
- package/dist/input/condition.js +32 -14
- package/dist/input/condition.js.map +1 -1
- package/dist/input/people.d.ts +15 -14
- package/dist/input/people.js +5 -5
- package/dist/input/people.js.map +1 -1
- package/dist/input/remote-items.d.ts +4 -2
- package/dist/input/remote-items.js +7 -2
- package/dist/input/remote-items.js.map +1 -1
- package/dist/layout/Affix.js +4 -4
- package/dist/layout/Affix.js.map +1 -1
- package/dist/layout/ResizeHandle.d.ts +6 -2
- package/dist/layout/ResizeHandle.js +32 -9
- package/dist/layout/ResizeHandle.js.map +1 -1
- package/dist/layout/ScrollArea.js +3 -3
- package/dist/layout/ScrollArea.js.map +1 -1
- package/dist/layout/Separator.js +3 -3
- package/dist/layout/Separator.js.map +1 -1
- package/dist/layout/Splitter.js +3 -3
- package/dist/layout/Splitter.js.map +1 -1
- package/dist/layout/ViewportFill.d.ts +2 -2
- package/dist/layout/ViewportFill.js +4 -4
- package/dist/layout/ViewportFill.js.map +1 -1
- package/dist/navigation/Breadcrumbs.js +4 -4
- package/dist/navigation/Breadcrumbs.js.map +1 -1
- package/dist/navigation/NavBar.js +6 -6
- package/dist/navigation/NavBar.js.map +1 -1
- package/dist/navigation/NavList.d.ts +1 -0
- package/dist/navigation/NavList.js +20 -12
- package/dist/navigation/NavList.js.map +1 -1
- package/dist/navigation/NavMenu.d.ts +27 -0
- package/dist/navigation/NavMenu.js +54 -0
- package/dist/navigation/NavMenu.js.map +1 -0
- package/dist/navigation/PageJump.js +3 -3
- package/dist/navigation/PageJump.js.map +1 -1
- package/dist/navigation/PageSizeSelect.js +4 -4
- package/dist/navigation/PageSizeSelect.js.map +1 -1
- package/dist/navigation/Pagination.js +6 -6
- package/dist/navigation/Pagination.js.map +1 -1
- package/dist/navigation/PaginationBar.js +5 -5
- package/dist/navigation/PaginationBar.js.map +1 -1
- package/dist/navigation/Steps.js +4 -4
- package/dist/navigation/Steps.js.map +1 -1
- package/dist/navigation/TableOfContents.js +5 -5
- package/dist/navigation/TableOfContents.js.map +1 -1
- package/dist/navigation/Tabs.js +7 -7
- package/dist/navigation/Tabs.js.map +1 -1
- package/dist/navigation/Toolbar.js +3 -3
- package/dist/navigation/Toolbar.js.map +1 -1
- package/dist/overlay/AlertDialog.js +4 -4
- package/dist/overlay/AlertDialog.js.map +1 -1
- package/dist/overlay/CommandPalette.js +4 -4
- package/dist/overlay/CommandPalette.js.map +1 -1
- package/dist/overlay/ContextMenu.js +3 -3
- package/dist/overlay/ContextMenu.js.map +1 -1
- package/dist/overlay/Dialog.js +4 -4
- package/dist/overlay/Dialog.js.map +1 -1
- package/dist/overlay/Drawer.js +5 -5
- package/dist/overlay/Drawer.js.map +1 -1
- package/dist/overlay/HoverCard.js +5 -3
- package/dist/overlay/HoverCard.js.map +1 -1
- package/dist/overlay/Lightbox.js +5 -5
- package/dist/overlay/Lightbox.js.map +1 -1
- package/dist/overlay/Menu.js +7 -7
- package/dist/overlay/Menu.js.map +1 -1
- package/dist/overlay/ModalCore.js +9 -9
- package/dist/overlay/ModalCore.js.map +1 -1
- package/dist/overlay/Popconfirm.js +6 -6
- package/dist/overlay/Popconfirm.js.map +1 -1
- package/dist/overlay/Popover.js +5 -3
- package/dist/overlay/Popover.js.map +1 -1
- package/dist/overlay/Tooltip.js +5 -3
- package/dist/overlay/Tooltip.js.map +1 -1
- package/dist/overlay/Tour.js +8 -8
- package/dist/overlay/Tour.js.map +1 -1
- package/dist/overlay/detached.d.ts +2 -0
- package/dist/overlay/detached.js +73 -42
- package/dist/overlay/detached.js.map +1 -1
- package/dist/patterns/ActionBar.js +3 -3
- package/dist/patterns/ActionBar.js.map +1 -1
- package/dist/patterns/AppShell.d.ts +28 -1
- package/dist/patterns/AppShell.js +158 -52
- package/dist/patterns/AppShell.js.map +1 -1
- package/dist/patterns/AuthLayout.d.ts +28 -0
- package/dist/patterns/AuthLayout.js +77 -0
- package/dist/patterns/AuthLayout.js.map +1 -0
- package/dist/patterns/CommentThread.js +9 -9
- package/dist/patterns/CommentThread.js.map +1 -1
- package/dist/patterns/DataImport.js +4 -4
- package/dist/patterns/DataImport.js.map +1 -1
- package/dist/patterns/DeadlineBadge.js +3 -3
- package/dist/patterns/DeadlineBadge.js.map +1 -1
- package/dist/patterns/FilterBar.d.ts +11 -1
- package/dist/patterns/FilterBar.js +39 -10
- package/dist/patterns/FilterBar.js.map +1 -1
- package/dist/patterns/FormDialog.d.ts +18 -0
- package/dist/patterns/FormDialog.js +46 -0
- package/dist/patterns/FormDialog.js.map +1 -0
- package/dist/patterns/KanbanBoard.js +8 -8
- package/dist/patterns/KanbanBoard.js.map +1 -1
- package/dist/patterns/LayoutSwitcher.d.ts +12 -0
- package/dist/patterns/LayoutSwitcher.js +79 -0
- package/dist/patterns/LayoutSwitcher.js.map +1 -0
- package/dist/patterns/NotificationCenter.js +8 -8
- package/dist/patterns/NotificationCenter.js.map +1 -1
- package/dist/patterns/PageTabs.d.ts +12 -7
- package/dist/patterns/PageTabs.js +41 -29
- package/dist/patterns/PageTabs.js.map +1 -1
- package/dist/patterns/QueryTable.d.ts +10 -1
- package/dist/patterns/QueryTable.js +128 -68
- package/dist/patterns/QueryTable.js.map +1 -1
- package/dist/patterns/SlideCaptcha.d.ts +80 -0
- package/dist/patterns/SlideCaptcha.js +354 -0
- package/dist/patterns/SlideCaptcha.js.map +1 -0
- package/dist/patterns/StepsForm.js +7 -7
- package/dist/patterns/StepsForm.js.map +1 -1
- package/dist/patterns/ThemeSwitcher.js +3 -3
- package/dist/patterns/ThemeSwitcher.js.map +1 -1
- package/dist/patterns/index.d.ts +7 -3
- package/dist/patterns/index.js +5 -1
- package/dist/patterns/messages.d.ts +39 -1
- package/dist/patterns/messages.js +40 -2
- package/dist/patterns/messages.js.map +1 -1
- package/dist/table/ColumnHeaderActions.js +3 -3
- package/dist/table/ColumnHeaderActions.js.map +1 -1
- package/dist/table/ColumnResizer.js +3 -3
- package/dist/table/ColumnResizer.js.map +1 -1
- package/dist/table/ColumnSettings.js +5 -5
- package/dist/table/ColumnSettings.js.map +1 -1
- package/dist/table/ColumnTable.js +8 -8
- package/dist/table/ColumnTable.js.map +1 -1
- package/dist/table/DataTable.js +8 -8
- package/dist/table/DataTable.js.map +1 -1
- package/dist/table/DataTableView.js +21 -21
- package/dist/table/DataTableView.js.map +1 -1
- package/dist/table/PivotTable.js +3 -3
- package/dist/table/PivotTable.js.map +1 -1
- package/dist/table/SelectionBar.js +4 -4
- package/dist/table/SelectionBar.js.map +1 -1
- package/dist/table/TreeDataTable.js +5 -5
- package/dist/table/TreeDataTable.js.map +1 -1
- package/dist/theme-customize/ThemeCustomizer.js +7 -6
- package/dist/theme-customize/ThemeCustomizer.js.map +1 -1
- package/dist/theme-customize/ThemeThumbnail.js +3 -3
- package/dist/theme-customize/ThemeThumbnail.js.map +1 -1
- package/dist/three/background/AuroraBackground.js +3 -3
- package/dist/three/background/AuroraBackground.js.map +1 -1
- package/dist/three/background/MeshGradient.js +3 -3
- package/dist/three/background/MeshGradient.js.map +1 -1
- package/dist/three/background/ShaderBackground.js +3 -3
- package/dist/three/background/ShaderBackground.js.map +1 -1
- package/dist/three/core/EffectSurface.js +3 -3
- package/dist/three/core/EffectSurface.js.map +1 -1
- package/dist/three/core/ThreeCanvas.js +4 -4
- package/dist/three/core/ThreeCanvas.js.map +1 -1
- package/dist/three/effects/Confetti.js +3 -3
- package/dist/three/effects/Confetti.js.map +1 -1
- package/dist/three/effects/ParticleField.js +3 -3
- package/dist/three/effects/ParticleField.js.map +1 -1
- package/dist/three/effects/WaveGrid.js +3 -3
- package/dist/three/effects/WaveGrid.js.map +1 -1
- package/dist/three/globe/Globe.js +3 -3
- package/dist/three/globe/Globe.js.map +1 -1
- package/dist/three/model/ModelViewer.js +3 -3
- package/dist/three/model/ModelViewer.js.map +1 -1
- package/dist/utils/data/clone.d.ts +8 -0
- package/dist/utils/data/clone.js +21 -0
- package/dist/utils/data/clone.js.map +1 -0
- package/dist/utils/data/date.d.ts +10 -0
- package/dist/utils/data/date.js +13 -1
- package/dist/utils/data/date.js.map +1 -1
- package/dist/utils/data/number.d.ts +5 -0
- package/dist/utils/data/number.js +8 -1
- package/dist/utils/data/number.js.map +1 -1
- package/dist/utils/data/numeric.d.ts +7 -0
- package/dist/utils/data/numeric.js +46 -1
- package/dist/utils/data/numeric.js.map +1 -1
- package/dist/utils/dom/download.d.ts +8 -1
- package/dist/utils/dom/download.js +19 -2
- package/dist/utils/dom/download.js.map +1 -1
- package/dist/utils/dom/element.d.ts +3 -1
- package/dist/utils/dom/element.js +8 -4
- package/dist/utils/dom/element.js.map +1 -1
- package/dist/utils/dom/fullscreen.d.ts +1 -1
- package/dist/utils/dom/fullscreen.js +12 -8
- package/dist/utils/dom/fullscreen.js.map +1 -1
- package/dist/utils/dom/mounted.d.ts +7 -0
- package/dist/utils/dom/mounted.js +16 -0
- package/dist/utils/dom/mounted.js.map +1 -0
- package/dist/utils/dom/overflow.js +2 -1
- package/dist/utils/dom/overflow.js.map +1 -1
- package/dist/utils/dom/pan-zoom.js +2 -1
- package/dist/utils/dom/pan-zoom.js.map +1 -1
- package/dist/utils/props.js +3 -13
- package/dist/utils/props.js.map +1 -1
- package/dist/utils/request/error-message.d.ts +17 -0
- package/dist/utils/request/error-message.js +50 -0
- package/dist/utils/request/error-message.js.map +1 -0
- package/dist/utils/request/http.d.ts +80 -4
- package/dist/utils/request/http.js +121 -24
- package/dist/utils/request/http.js.map +1 -1
- package/dist/utils/request/use-autosave.d.ts +35 -0
- package/dist/utils/request/use-autosave.js +69 -0
- package/dist/utils/request/use-autosave.js.map +1 -0
- package/dist/utils/request/use-request.js +4 -2
- package/dist/utils/request/use-request.js.map +1 -1
- package/package.json +57 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleGroup.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/input/ToggleGroup.tsx"],"sourcesContent":["/**\n * 切换按钮组,复合组件:ToggleGroup(role=\"group\")> ToggleItem(带 aria-pressed 的 button)。\n * 单选像分段控件(视图切换、对齐方式),多选像格式按钮(加粗、斜体)。整组一个 Tab 位置,组内方向键移动(漫游焦点)。\n * 参考 Radix ToggleGroup、Ark UI SegmentGroup。\n *\n * <ToggleGroup _value={view} aria-label=\"视图\" required>\n * <ToggleItem value=\"list\" icon={List} aria-label=\"列表\" />\n * <ToggleItem value=\"grid\" icon={LayoutGrid} aria-label=\"网格\" />\n * </ToggleGroup>\n * <ToggleGroup selectionMode=\"multiple\" _value={marks} aria-label=\"格式\">…</ToggleGroup>\n */\nimport { createContext, _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport {\n buttonContent,\n buttonPart,\n buttonSx,\n useButtonAppearance,\n useButtonBehavior,\n type ButtonOptions,\n} from '../base/button-core';\nimport type { IconData, IconProps } from '../base/Icon';\nimport { useActiveIndicator } from '../utils/motion/active-indicator';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { rovingFocus } from '../utils/dom/roving-focus';\nimport { ToolbarContext } from '../navigation/Toolbar';\nimport { selectedValues, toggleSelection, type SelectionProps } from '../utils/data/selection';\nimport { useFieldControl } from '../form/Field';\nimport type { TextSize } from '../utils/style/typography';\n\n/** ToggleGroup 交给组内 ToggleGroupItem 的状态 */\nexport interface ToggleGroupState {\n /** 按下(选中)的项的值 */\n readonly selected: readonly string[];\n /** 字号档位;不写时继承 */\n readonly size: TextSize | undefined;\n /** 整组不可用 */\n readonly disabled: boolean;\n /** 整组只读:按钮照常显示与聚焦,点了不切换 */\n readonly readonly: boolean;\n /** 波纹;不写时沿用配置 */\n readonly ripple: boolean | undefined;\n /** 单选:选中底色由组里的滑块(Indicator)画,项本身不画底色 */\n readonly sliding: boolean;\n /** 切换一项(单选、多选的规则由组决定) */\n toggle(value: string): void;\n}\n\n/** ToggleGroup 的上下文:自定义的项可以 inject 它接入组 */\nexport const ToggleGroupContext = createContext<ToggleGroupState>('ToggleGroup');\n\n/** 方向 */\nexport interface ToggleGroupOrientations {\n /** 横排(默认),左右键移动 */\n horizontal: unknown;\n /** 竖排,上下键移动 */\n vertical: unknown;\n}\n\n/** 角色由组件管理(role=\"group\" 不允许 aria-orientation,方向只写在 data-orientation 上) */\nexport type ToggleGroupManaged = 'role';\n\n/** 两种选择方式共有的选项;未声明的属性落到 role=\"group\" 的 div 上,aria-label 是这组的名称 */\nexport interface ToggleGroupBaseProps extends PartProps<'div', ToggleGroupManaged> {\n /** 必须有选中项:最后一项不能取消(分段控件通常要求);在必填的 Field 里默认开启 */\n required?: boolean;\n /** 整组不可用 */\n disabled?: boolean;\n /** 整组只读:选中项照常显示、按钮能聚焦,点了不切换(查看详情、审批时) */\n readonly?: boolean;\n /** 方向,默认 horizontal */\n orientation?: keyof ToggleGroupOrientations;\n /** 字号档位,按钮随之缩放 */\n size?: TextSize;\n /** 按下时的波纹;不写时沿用全局配置 */\n ripple?: boolean;\n /** 单选时选中项下面的滑块(切换时滑过去)的部件属性 */\n propsIndicator?: PartProps<'span'>;\n children?: VNodeChild;\n}\n\n/** 单选或多选 */\nexport type ToggleGroupProps = ToggleGroupBaseProps & SelectionProps;\n\n/** ToggleGroup 的样式:root、vertical、indicator */\nexport const toggleGroupStyles = css.create({\n root: {\n // 滑块按项的 offsetLeft / offsetTop 定位;isolation 让 zIndex: -1 的滑块压在项下、组的底色之上\n position: 'relative',\n isolation: 'isolate',\n display: 'inline-flex',\n // 放在竖排的弹性容器里(Field 的控件列)时不被拉满整行\n width: 'fit-content',\n gap: '_xs',\n padding: '_xs',\n borderRadius: '_md',\n backgroundColor: '_fill',\n },\n vertical: { flexDirection: 'column' },\n // 只读、没选中的项:不像能点(悬停也不出底色)\n readonlyItem: { cursor: 'default', backgroundColor: 'transparent' },\n // 同按钮的 surface 外观;位置与宽高由脚本写(useActiveIndicator)\n indicator: {\n position: 'absolute',\n top: 0,\n left: 0,\n zIndex: -1,\n boxSizing: 'border-box',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_accentBorder',\n borderRadius: '_sm',\n backgroundColor: '_accentSoft',\n pointerEvents: 'none',\n },\n});\n\n/** 切换按钮组:单选或多选,整组一个 Tab 位置 */\nexport const ToggleGroup = _component(\n ({\n selectionMode = 'single',\n _value: value = _bindable<string | string[] | null>(null),\n required,\n disabled,\n readonly,\n orientation = 'horizontal',\n size,\n ripple,\n propsIndicator,\n children,\n id,\n ...rest\n }: ToggleGroupProps) => {\n // 在 Field 里时:标签作为组的名称、关联说明与错误、沿用不可用与只读\n const control = useFieldControl(() => ({ id, disabled, readonly, required }));\n let root = _state.raw<HTMLElement | null>(null);\n // 在工具栏里时焦点交给工具栏:整栏一个 Tab 位置,方向键跨过组内外的按钮(WAI-ARIA Toolbar 模式)\n const inToolbar = ToolbarContext.inject(null) != null;\n _effect(() =>\n root && !inToolbar\n ? rovingFocus(root, { items: 'button', orientation, loop: true })\n : undefined,\n );\n const selected = _derived(selectedValues(value));\n let indicator = _state.raw<HTMLElement | null>(null);\n useActiveIndicator(() => ({\n container: root,\n indicator,\n active: '[aria-pressed=\"true\"]',\n axis: 'both',\n value: selected[0],\n }));\n\n ToggleGroupContext.provide({\n get selected() {\n return selected;\n },\n get size() {\n return size;\n },\n get disabled() {\n return control().disabled;\n },\n get readonly() {\n return control().readonly;\n },\n get ripple() {\n return ripple;\n },\n get sliding() {\n return selectionMode === 'single';\n },\n toggle(item) {\n if (control().readonly) return;\n const next = toggleSelection(selected, item, {\n mode: selectionMode,\n required: control().required,\n });\n if (next === selected) return;\n value = selectionMode === 'multiple' ? [...next] : (next[0] ?? null);\n },\n });\n\n return () => {\n const field = control();\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n toggleGroupStyles.root,\n orientation === 'vertical' && toggleGroupStyles.vertical,\n ],\n },\n rest,\n {\n ref: _toRef(root),\n id: field.id,\n role: 'group',\n 'aria-labelledby': defaultLabelledBy(rest, field.labelledBy),\n 'aria-describedby': field.describedBy,\n },\n )}\n data-orientation={orientation}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readonly || undefined}\n >\n {selectionMode === 'single' && selected.length > 0 && (\n <span\n {...mergeAttrs<'span'>({ sx: toggleGroupStyles.indicator }, propsIndicator, {\n ref: _toRef(indicator),\n 'aria-hidden': true,\n })}\n />\n )}\n {children}\n </div>\n );\n };\n },\n);\n\n/** 选中、不可用由组件管理 */\nexport type ToggleGroupItemManaged = 'aria-pressed' | 'disabled' | 'type';\n\n/** 未声明的属性落到 button 上;只有图标时写 aria-label */\nexport interface ToggleItemProps\n extends PartProps<'button', ToggleGroupItemManaged>, Pick<ButtonOptions, 'radius'> {\n /** 这一项的值 */\n value: string;\n /** 图标 */\n icon?: IconData;\n /** 不可用 */\n disabled?: boolean;\n /** 图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 内容层的部件属性 */\n propsContent?: PartProps<'span'>;\n children?: VNodeChild;\n}\n\n/** 切换按钮组里的一项(button,aria-pressed 表示是否选中) */\nexport const ToggleItem = _component(\n ({\n value,\n icon,\n disabled = false,\n radius,\n propsIcon,\n propsContent,\n children,\n ...rest\n }: ToggleItemProps) => {\n const group = ToggleGroupContext.inject();\n // 与 Button 同一套行为:不可用、拦截点击、波纹、状态 data 属性;只读时不出波纹\n const behavior = useButtonBehavior(\n () => ({\n disabled: disabled || group.disabled,\n loading: false,\n ripple: group.readonly ? false : group.ripple,\n }),\n () => () => group.toggle(value),\n );\n // 选中的是浅色底,其余是幽灵按钮;尺寸跟随组\n const appearance = useButtonAppearance(\n () => ({ variant: undefined, tone: 'neutral', size: group.size, radius: radius ?? 'sm' }),\n 'ghost',\n );\n\n return () => {\n const pressed = group.selected.includes(value);\n const off = disabled || group.disabled;\n const base = appearance();\n return (\n <button\n {...mergeAttrs<'button'>(\n {\n ...buttonPart,\n sx: [\n buttonSx(\n {\n ...base,\n // 单选时选中底色由组的滑块画\n variant: pressed && !group.sliding ? 'surface' : 'ghost',\n tone: pressed ? 'accent' : 'neutral',\n },\n { disabled: off, square: children == null },\n ),\n group.readonly && !pressed && toggleGroupStyles.readonlyItem,\n ],\n },\n rest,\n {\n type: 'button',\n 'aria-pressed': pressed,\n // 使用方的 onClick 先执行,preventDefault 可以拦下切换(mergeProps 的规则)\n ...behavior(),\n },\n )}\n data-state={pressed ? 'on' : 'off'}\n >\n {buttonContent({ icon, propsIcon, propsContent, children }, { loading: false })}\n </button>\n );\n };\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ToggleGroup.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_childrenProp","_vtp_restProps","_vue_shallowRef","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/input/ToggleGroup.tsx"],"sourcesContent":["/**\n * 切换按钮组,复合组件:ToggleGroup(role=\"group\")> ToggleItem(带 aria-pressed 的 button)。\n * 单选像分段控件(视图切换、对齐方式),多选像格式按钮(加粗、斜体)。整组一个 Tab 位置,组内方向键移动(漫游焦点)。\n * 参考 Radix ToggleGroup、Ark UI SegmentGroup。\n *\n * <ToggleGroup _value={view} aria-label=\"视图\" required>\n * <ToggleItem value=\"list\" icon={List} aria-label=\"列表\" />\n * <ToggleItem value=\"grid\" icon={LayoutGrid} aria-label=\"网格\" />\n * </ToggleGroup>\n * <ToggleGroup selectionMode=\"multiple\" _value={marks} aria-label=\"格式\">…</ToggleGroup>\n */\nimport { createContext, _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport * as css from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport {\n buttonContent,\n buttonPart,\n buttonSx,\n useButtonAppearance,\n useButtonBehavior,\n type ButtonOptions,\n} from '../base/button-core';\nimport type { IconData, IconProps } from '../base/Icon';\nimport { useActiveIndicator } from '../utils/motion/active-indicator';\nimport { defaultLabelledBy, mergeAttrs, type PartProps } from '../utils/props';\nimport { rovingFocus } from '../utils/dom/roving-focus';\nimport { ToolbarContext } from '../navigation/Toolbar';\nimport { selectedValues, toggleSelection, type SelectionProps } from '../utils/data/selection';\nimport { useFieldControl } from '../form/Field';\nimport type { TextSize } from '../utils/style/typography';\n\n/** ToggleGroup 交给组内 ToggleGroupItem 的状态 */\nexport interface ToggleGroupState {\n /** 按下(选中)的项的值 */\n readonly selected: readonly string[];\n /** 字号档位;不写时继承 */\n readonly size: TextSize | undefined;\n /** 整组不可用 */\n readonly disabled: boolean;\n /** 整组只读:按钮照常显示与聚焦,点了不切换 */\n readonly readonly: boolean;\n /** 波纹;不写时沿用配置 */\n readonly ripple: boolean | undefined;\n /** 单选:选中底色由组里的滑块(Indicator)画,项本身不画底色 */\n readonly sliding: boolean;\n /** 切换一项(单选、多选的规则由组决定) */\n toggle(value: string): void;\n}\n\n/** ToggleGroup 的上下文:自定义的项可以 inject 它接入组 */\nexport const ToggleGroupContext = createContext<ToggleGroupState>('ToggleGroup');\n\n/** 方向 */\nexport interface ToggleGroupOrientations {\n /** 横排(默认),左右键移动 */\n horizontal: unknown;\n /** 竖排,上下键移动 */\n vertical: unknown;\n}\n\n/** 角色由组件管理(role=\"group\" 不允许 aria-orientation,方向只写在 data-orientation 上) */\nexport type ToggleGroupManaged = 'role';\n\n/** 两种选择方式共有的选项;未声明的属性落到 role=\"group\" 的 div 上,aria-label 是这组的名称 */\nexport interface ToggleGroupBaseProps extends PartProps<'div', ToggleGroupManaged> {\n /** 必须有选中项:最后一项不能取消(分段控件通常要求);在必填的 Field 里默认开启 */\n required?: boolean;\n /** 整组不可用 */\n disabled?: boolean;\n /** 整组只读:选中项照常显示、按钮能聚焦,点了不切换(查看详情、审批时) */\n readonly?: boolean;\n /** 方向,默认 horizontal */\n orientation?: keyof ToggleGroupOrientations;\n /** 字号档位,按钮随之缩放 */\n size?: TextSize;\n /** 按下时的波纹;不写时沿用全局配置 */\n ripple?: boolean;\n /** 单选时选中项下面的滑块(切换时滑过去)的部件属性 */\n propsIndicator?: PartProps<'span'>;\n children?: VNodeChild;\n}\n\n/** 单选或多选 */\nexport type ToggleGroupProps = ToggleGroupBaseProps & SelectionProps;\n\n/** ToggleGroup 的样式:root、vertical、indicator */\nexport const toggleGroupStyles = css.create({\n root: {\n // 滑块按项的 offsetLeft / offsetTop 定位;isolation 让 zIndex: -1 的滑块压在项下、组的底色之上\n position: 'relative',\n isolation: 'isolate',\n display: 'inline-flex',\n // 放在竖排的弹性容器里(Field 的控件列)时不被拉满整行\n width: 'fit-content',\n gap: '_xs',\n padding: '_xs',\n borderRadius: '_md',\n backgroundColor: '_fill',\n },\n vertical: { flexDirection: 'column' },\n // 只读、没选中的项:不像能点(悬停也不出底色)\n readonlyItem: { cursor: 'default', backgroundColor: 'transparent' },\n // 同按钮的 surface 外观;位置与宽高由脚本写(useActiveIndicator)\n indicator: {\n position: 'absolute',\n top: 0,\n left: 0,\n zIndex: -1,\n boxSizing: 'border-box',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_accentBorder',\n borderRadius: '_sm',\n backgroundColor: '_accentSoft',\n pointerEvents: 'none',\n },\n});\n\n/** 切换按钮组:单选或多选,整组一个 Tab 位置 */\nexport const ToggleGroup = _component(\n ({\n selectionMode = 'single',\n _value: value = _bindable<string | string[] | null>(null),\n required,\n disabled,\n readonly,\n orientation = 'horizontal',\n size,\n ripple,\n propsIndicator,\n children,\n id,\n ...rest\n }: ToggleGroupProps) => {\n // 在 Field 里时:标签作为组的名称、关联说明与错误、沿用不可用与只读\n const control = useFieldControl(() => ({ id, disabled, readonly, required }));\n let root = _state.raw<HTMLElement | null>(null);\n // 在工具栏里时焦点交给工具栏:整栏一个 Tab 位置,方向键跨过组内外的按钮(WAI-ARIA Toolbar 模式)\n const inToolbar = ToolbarContext.inject(null) != null;\n _effect(() =>\n root && !inToolbar\n ? rovingFocus(root, { items: 'button', orientation, loop: true })\n : undefined,\n );\n const selected = _derived(selectedValues(value));\n let indicator = _state.raw<HTMLElement | null>(null);\n useActiveIndicator(() => ({\n container: root,\n indicator,\n active: '[aria-pressed=\"true\"]',\n axis: 'both',\n value: selected[0],\n }));\n\n ToggleGroupContext.provide({\n get selected() {\n return selected;\n },\n get size() {\n return size;\n },\n get disabled() {\n return control().disabled;\n },\n get readonly() {\n return control().readonly;\n },\n get ripple() {\n return ripple;\n },\n get sliding() {\n return selectionMode === 'single';\n },\n toggle(item) {\n if (control().readonly) return;\n const next = toggleSelection(selected, item, {\n mode: selectionMode,\n required: control().required,\n });\n if (next === selected) return;\n value = selectionMode === 'multiple' ? [...next] : (next[0] ?? null);\n },\n });\n\n return () => {\n const field = control();\n return (\n <div\n {...mergeAttrs<'div'>(\n {\n sx: [\n toggleGroupStyles.root,\n orientation === 'vertical' && toggleGroupStyles.vertical,\n ],\n },\n rest,\n {\n ref: _toRef(root),\n id: field.id,\n role: 'group',\n 'aria-labelledby': defaultLabelledBy(rest, field.labelledBy),\n 'aria-describedby': field.describedBy,\n },\n )}\n data-orientation={orientation}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readonly || undefined}\n >\n {selectionMode === 'single' && selected.length > 0 && (\n <span\n {...mergeAttrs<'span'>({ sx: toggleGroupStyles.indicator }, propsIndicator, {\n ref: _toRef(indicator),\n 'aria-hidden': true,\n })}\n />\n )}\n {children}\n </div>\n );\n };\n },\n);\n\n/** 选中、不可用由组件管理 */\nexport type ToggleGroupItemManaged = 'aria-pressed' | 'disabled' | 'type';\n\n/** 未声明的属性落到 button 上;只有图标时写 aria-label */\nexport interface ToggleItemProps\n extends PartProps<'button', ToggleGroupItemManaged>, Pick<ButtonOptions, 'radius'> {\n /** 这一项的值 */\n value: string;\n /** 图标 */\n icon?: IconData;\n /** 不可用 */\n disabled?: boolean;\n /** 图标的部件属性 */\n propsIcon?: Partial<IconProps>;\n /** 内容层的部件属性 */\n propsContent?: PartProps<'span'>;\n children?: VNodeChild;\n}\n\n/** 切换按钮组里的一项(button,aria-pressed 表示是否选中) */\nexport const ToggleItem = _component(\n ({\n value,\n icon,\n disabled = false,\n radius,\n propsIcon,\n propsContent,\n children,\n ...rest\n }: ToggleItemProps) => {\n const group = ToggleGroupContext.inject();\n // 与 Button 同一套行为:不可用、拦截点击、波纹、状态 data 属性;只读时不出波纹\n const behavior = useButtonBehavior(\n () => ({\n disabled: disabled || group.disabled,\n loading: false,\n ripple: group.readonly ? false : group.ripple,\n }),\n () => () => group.toggle(value),\n );\n // 选中的是浅色底,其余是幽灵按钮;尺寸跟随组\n const appearance = useButtonAppearance(\n () => ({ variant: undefined, tone: 'neutral', size: group.size, radius: radius ?? 'sm' }),\n 'ghost',\n );\n\n return () => {\n const pressed = group.selected.includes(value);\n const off = disabled || group.disabled;\n const base = appearance();\n return (\n <button\n {...mergeAttrs<'button'>(\n {\n ...buttonPart,\n sx: [\n buttonSx(\n {\n ...base,\n // 单选时选中底色由组的滑块画\n variant: pressed && !group.sliding ? 'surface' : 'ghost',\n tone: pressed ? 'accent' : 'neutral',\n },\n { disabled: off, square: children == null },\n ),\n group.readonly && !pressed && toggleGroupStyles.readonlyItem,\n ],\n },\n rest,\n {\n type: 'button',\n 'aria-pressed': pressed,\n // 使用方的 onClick 先执行,preventDefault 可以拦下切换(mergeProps 的规则)\n ...behavior(),\n },\n )}\n data-state={pressed ? 'on' : 'off'}\n >\n {buttonContent({ icon, propsIcon, propsContent, children }, { loading: false })}\n </button>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;;AAkDA,IAAa,qBAAqB,cAAgC,aAAa;;;;;;AAoC/E,IAAa,oBAAoB,IAAI,OAAO;CAC1C,MAAM;EAEJ,UAAU;EACV,WAAW;EACX,SAAS;EAET,OAAO;EACP,KAAK;EACL,SAAS;EACT,cAAc;EACd,iBAAiB;CACnB;CACA,UAAU,EAAE,eAAe,SAAS;CAEpC,cAAc;EAAE,QAAQ;EAAW,iBAAiB;CAAc;CAElE,WAAW;EACT,UAAU;EACV,KAAK;EACL,MAAM;EACN,QAAQ;EACR,WAAW;EACX,aAAa;EACb,aAAa;EACb,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;CACjB;AACF,CAAC;;AAGD,IAAa,cAAc,0BACzB,QAAA,SAawB;CAAA,MAAA,gBAAAA,aAAA,QAAA,iBAZN,QAAQ;CAAA,MAAA,QAAAC,SAAA,QAAA,gBAC4B,MAAI,KAAA,IAAA;CAAA,MAAA,WAAAD,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,eAI1C,YAAY;CAAA,MAAA,OAAAA,aAAA,QAAA,MAAA;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,iBAAAA,aAAA,QAAA,gBAAA;CAAA,MAAA,WAAAE,aAAA,MAAA;CAAA,MAAA,KAAAF,aAAA,QAAA,IAAA;CAAA,MAMvB,OAAIG,UAAA,QAAA,MAAA,KAAA;CAGP,MAAM,UAAU,uBAAuB;EAAE,IAAE,GAAA;EAAE,UAAQ,SAAA;EAAE,UAAQ,SAAA;EAAE,UAAQ,SAAA;CAAC,EAAE;CAC5E,IAAI,OAAIC,WAAkC,IAAI;CAE9C,MAAM,YAAY,eAAe,OAAO,IAAI,KAAK;CACjD,aACE,KAAA,SAAQ,CAAC,YACL,YAAW,KAAA,OAAO;EAAE,OAAO;EAAU,aAAW,YAAA;EAAE,MAAM;CAAK,CAAC,IAC9D,KAAA,CAAS;CAEf,MAAM,WAAQC,eAAY,eAAc,MAAA,KAAM,CAAC;CAC/C,IAAI,YAASD,WAAkC,IAAI;CACnD,0BAA0B;EACxB,WAAS,KAAA;EACT,WAAS,UAAA;EACT,QAAQ;EACR,MAAM;EACN,OAAO,SAAA,MAAS;CAClB,EAAE;CAEF,mBAAmB,QAAQ;EACzB,IAAI,WAAW;GACb,OAAA,SAAA;EACF;EACA,IAAI,OAAO;GACT,OAAA,KAAA;EACF;EACA,IAAI,WAAW;GACb,OAAO,QAAQ,CAAC,CAAC;EACnB;EACA,IAAI,WAAW;GACb,OAAO,QAAQ,CAAC,CAAC;EACnB;EACA,IAAI,SAAS;GACX,OAAA,OAAA;EACF;EACA,IAAI,UAAU;GACZ,OAAO,cAAA,UAAkB;EAC3B;EACA,OAAO,MAAM;GACX,IAAI,QAAQ,CAAC,CAAC,UAAU;GACxB,MAAM,OAAO,gBAAe,SAAA,OAAW,MAAM;IAC3C,MAAI,cAAA;IACJ,UAAU,QAAQ,CAAC,CAAC;GACtB,CAAC;GACD,IAAI,SAAI,SAAA,OAAe;GACvB,MAAA,QAAQ,cAAA,UAAkB,aAAa,CAAC,GAAG,IAAI,IAAK,KAAK,MAAM;EACjE;CACF,CAAC;CAED,aAAa;EACX,MAAM,QAAQ,QAAQ;EACtB,OAAAE,YAAA,OAAAC,cAEQ,WACF,EACE,IAAI,CACF,kBAAkB,MAClB,YAAA,UAAgB,cAAc,kBAAkB,QAAQ,EAE5D,GACA,MACA;GACE,KAAG;GACH,IAAI,MAAM;GACV,MAAM;GACN,mBAAmB,kBAAkB,MAAM,MAAM,UAAU;GAC3D,oBAAoB,MAAM;EAC5B,CACF,GAAC;GAAA,oBAAA,YAAA;GAAA,iBAEc,MAAM,YAAY,KAAA;GAAS,iBAC3B,MAAM,YAAY,KAAA;EAAS,CAAA,GAAA,CAEzC,cAAA,UAAkB,YAAY,SAAA,MAAS,SAAS,KAACD,YAAA,QAE1C,WAAmB,EAAE,IAAI,kBAAkB,UAAU,GAAC,eAAA,OAAkB;GAC1E,KAAG;GACH,eAAe;EACjB,CAAC,GAAC,IAAA,GAEL,SAAA,KAAA,CAAA;CAIP;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH;;;;AAsBA,IAAa,aAAa,0BACxB,SAAA,UASuB;CAAA,MAAA,QAAAN,aAAA,SAAA,OAAA;CAAA,MAAA,OAAAA,aAAA,SAAA,MAAA;CAAA,MAAA,WAAAA,aAAA,SAAA,YANV,KAAK;CAAA,MAAA,SAAAA,aAAA,SAAA,QAAA;CAAA,MAAA,YAAAA,aAAA,SAAA,WAAA;CAAA,MAAA,eAAAA,aAAA,SAAA,cAAA;CAAA,MAAA,WAAAE,aAAA,OAAA;CAAA,MAKb,OAAIC,UAAA,SAAA,OAAA,KAAA;CAEP,MAAM,QAAQ,mBAAmB,OAAO;CAExC,MAAM,WAAW,yBACR;EACL,UAAU,SAAA,SAAY,MAAM;EAC5B,SAAS;EACT,QAAQ,MAAM,WAAW,QAAQ,MAAM;CACzC,gBACY,MAAM,OAAM,MAAA,KAAM,CAChC;CAEA,MAAM,aAAa,2BACV;EAAE,SAAS,KAAA;EAAW,MAAM;EAAW,MAAM,MAAM;EAAM,QAAQ,OAAA,SAAU;CAAK,IACvF,OACF;CAEA,aAAa;EACX,MAAM,UAAU,MAAM,SAAS,SAAQ,MAAA,KAAM;EAC7C,MAAM,MAAM,SAAA,SAAY,MAAM;EAC9B,MAAM,OAAO,WAAW;EACxB,OAAAG,YAAA,UAAAC,cAEQ,WACF;GACE,GAAG;GACH,IAAI,CACF,SACE;IACE,GAAG;IAEH,SAAS,WAAW,CAAC,MAAM,UAAU,YAAY;IACjD,MAAM,UAAU,WAAW;GAC7B,GACA;IAAE,UAAU;IAAK,QAAQ,SAAA,SAAY;GAAK,CAC5C,GACA,MAAM,YAAY,CAAC,WAAW,kBAAkB,YAAY;EAEhE,GACA,MACA;GACE,MAAM;GACN,gBAAgB;GAEhB,GAAG,SAAS;EACd,CACF,GAAC,EAAA,cACW,UAAU,OAAO,MAAK,CAAA,GAAA,CAEjC,cAAc;GAAE,MAAI,KAAA;GAAE,WAAS,UAAA;GAAE,cAAY,aAAA;GAAE,UAAQ,SAAA;EAAC,GAAG,EAAE,SAAS,MAAM,CAAC,CAAC,CAAA;CAGrF;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
package/dist/input/Transfer.js
CHANGED
|
@@ -10,8 +10,8 @@ import { checkedByStrategy, indexTree } from "../utils/data/tree.js";
|
|
|
10
10
|
import { Tree } from "../display/Tree.js";
|
|
11
11
|
import { Listbox } from "./Listbox.js";
|
|
12
12
|
import { TextField } from "./TextField.js";
|
|
13
|
-
import { computed, createVNode, isVNode,
|
|
14
|
-
import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
13
|
+
import { computed, createVNode, isVNode, ref, useId } from "vue";
|
|
14
|
+
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
15
15
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
16
16
|
import { ChevronLeft, ChevronRight, Search } from "@lucide/icons";
|
|
17
17
|
//#region src/input/Transfer.tsx
|
|
@@ -119,10 +119,10 @@ function renderPanel(lang, options) {
|
|
|
119
119
|
"disabled": options.disabled || options.selectable.length === 0,
|
|
120
120
|
"aria-label": lang.transferSelectAll(options.title)
|
|
121
121
|
}, null),
|
|
122
|
-
createVNode("span",
|
|
122
|
+
createVNode("span", mergeJsxProps({ "id": options.titleId }, css.attrs(transferStyles.title)), [options.title]),
|
|
123
123
|
createVNode(Small, { "tone": "muted" }, _isSlot(_slot = lang.transferCount(options.checked.length, options.total)) ? _slot : { default: () => [_slot] })
|
|
124
124
|
]),
|
|
125
|
-
options.searchable && createVNode("div", css.attrs(transferStyles.search), [createVNode(TextField,
|
|
125
|
+
options.searchable && createVNode("div", css.attrs(transferStyles.search), [createVNode(TextField, mergeJsxProps(mergePartProps({
|
|
126
126
|
icon: Search,
|
|
127
127
|
variant: "soft",
|
|
128
128
|
size: "sm",
|
|
@@ -140,7 +140,7 @@ function renderPanel(lang, options) {
|
|
|
140
140
|
}
|
|
141
141
|
/** 中间的两个按钮 */
|
|
142
142
|
function renderActions(lang, titles, enabled, move, propsAction) {
|
|
143
|
-
return createVNode("div", css.attrs(transferStyles.actions), [[1, 0].map((to) => createVNode(IconButton,
|
|
143
|
+
return createVNode("div", css.attrs(transferStyles.actions), [[1, 0].map((to) => createVNode(IconButton, mergeJsxProps({ "key": to }, mergePartProps({
|
|
144
144
|
icon: to === 1 ? ChevronRight : ChevronLeft,
|
|
145
145
|
"aria-label": lang.transferMoveTo(titles[to]),
|
|
146
146
|
variant: "soft",
|
|
@@ -206,7 +206,7 @@ var Transfer = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
206
206
|
}
|
|
207
207
|
return () => {
|
|
208
208
|
const state = field();
|
|
209
|
-
const list = (side) => createVNode(Listbox,
|
|
209
|
+
const list = (side) => createVNode(Listbox, mergeJsxProps(mergePartProps({
|
|
210
210
|
items: shownEntries(side).map((entry) => entry.item),
|
|
211
211
|
toOption: (item) => toListboxOption(item, toOption.value),
|
|
212
212
|
selectionMode: "multiple",
|
|
@@ -329,7 +329,7 @@ var TreeTransfer = /*#__PURE__*/ _component((_props2, _ctx2) => {
|
|
|
329
329
|
return () => {
|
|
330
330
|
const state = field();
|
|
331
331
|
const sourceChecked = checked.value[0];
|
|
332
|
-
const tree = createVNode(Tree,
|
|
332
|
+
const tree = createVNode(Tree, mergeJsxProps(mergePartProps({
|
|
333
333
|
items: items.value,
|
|
334
334
|
getKey: getKey.value,
|
|
335
335
|
getLabel: getLabel.value,
|
|
@@ -344,7 +344,7 @@ var TreeTransfer = /*#__PURE__*/ _component((_props2, _ctx2) => {
|
|
|
344
344
|
"_expanded": expanded.value,
|
|
345
345
|
"onUpdate:_expanded": _cache[1] || (_cache[1] = ($event) => expanded.value = $event)
|
|
346
346
|
}), null);
|
|
347
|
-
const list = createVNode(Listbox,
|
|
347
|
+
const list = createVNode(Listbox, mergeJsxProps(mergePartProps({
|
|
348
348
|
items: targetOptions().filter((option) => matchesSearch(option.value, 1)),
|
|
349
349
|
selectionMode: "multiple",
|
|
350
350
|
sx: transferStyles.list,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transfer.js","names":["_isVNode","_createVNode","_mergeProps","_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_ref","_vue_computed"],"sources":["../../src/input/Transfer.tsx"],"sourcesContent":["/**\n * 穿梭框:左边是可选的,右边是已选的,勾上之后点中间的按钮移过去(分配权限、指派成员、挑选导出的列)。\n *\n * <Transfer items={users} toOption={(user) => ({ value: user.id, label: user.name })} _value={memberIds} searchable />\n * <TreeTransfer items={orgs} getKey={…} getLabel={…} getChildren={…} _value={teamIds} /> 左边是一棵树\n *\n * - 每一边是一个可多选的 Listbox(焦点、方向键、空格勾选、虚拟滚动同 Listbox),上方是全选框、标题与“勾上 / 总数”,\n * searchable 时带搜索框(按选项文字,认 createUi 的 textMatcher)。全选只管当前看得见(搜索后留下)的项。\n * - 中间两个按钮把勾上的项移到另一边(没有勾上的时不可用),双击一项直接移过去;移动后读屏播报移了几项。\n * 不可用的选项(ListboxOption 的 disabled)勾不上,也就移不动。\n * - value 是右边的值,按移过去的先后排列;items 里找不到的值不显示(也不会被删掉)。\n * - TreeTransfer:左边是勾选的 Tree(父子联动、可搜索),已经移过去的节点勾上且不可用;只移叶子,value 是叶子的 key。\n * - 在 Field 里时整体是一组(role=\"group\",名称是 Field 的标签),两边的列表各以自己的标题为名。\n *\n * 部件:Root(div,role=\"group\")、Panel(section,每一边)、Header、SelectAll(Checkbox)、Title、Count、\n * Search(TextField)、List(Listbox / Tree)、Actions(中间的按钮)。\n */\nimport { ChevronLeft, ChevronRight, 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 type { UpdateHandlers } from '@zerodep-dev/vue-tsx-pro-tsx/jsx-runtime';\nimport { useId, type VNodeChild } from 'vue';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { Small } from '../base/Text';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { Tree, type TreeProps } from '../display/Tree';\nimport { useFieldControl } from '../form/Field';\nimport { checkedByStrategy, indexTree } from '../utils/data/tree';\nimport { announce } from '../utils/dom/announcer';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { Checkbox } from './Checkbox';\nimport { Listbox, type ListboxBaseProps, type ListboxProps } from './Listbox';\nimport type { MultipleSelectionProps } from '../utils/data/selection';\nimport { toListboxOption, type ListboxOption, type OptionMapping } from './list-state';\nimport { TextField, type TextFieldProps } from './TextField';\n\n/** 两边的列表(可多选的 Listbox)的属性:propsList 用它 */\nexport type TransferListProps<T> = ListboxBaseProps<T> & MultipleSelectionProps & OptionMapping<T>;\n\n/** Transfer 与 TreeTransfer 共有的属性;未声明的属性落到外层 div(role=\"group\")上 */\nexport interface TransferBaseProps extends PartProps<'div', 'role'> {\n /** 右边(已选)的值,按移过去的先后排列:父级写 _value={keys} */\n _value?: string[];\n /** 左右两边的标题,默认取语言包(可选、已选) */\n titles?: readonly [string, string];\n /** 两边带搜索框 */\n searchable?: boolean;\n /** 不可用:勾不了、移不了 */\n disabled?: boolean;\n /** 每一边的部件属性(section;列表的高度给它的 sx) */\n propsPanel?: PartProps<'section'>;\n /** 搜索框的部件属性 */\n propsSearch?: Partial<TextFieldProps>;\n /** 中间两个按钮的部件属性 */\n propsAction?: Partial<IconButtonProps>;\n}\n\n/** 选项是 ListboxOption、字符串,或任意数据加 toOption */\nexport type TransferProps<T = ListboxOption> = TransferBaseProps &\n OptionMapping<T> & {\n /** 全部数据(两边一起):右边显示 value 里的那些 */\n items: readonly T[];\n /** 搜索时怎样算匹配;默认选项文字包含输入(忽略大小写与重音,或 createUi 的 textMatcher) */\n filter?: (item: T, query: string) => boolean;\n /** 两边列表的部件属性 */\n propsList?: Partial<TransferListProps<T>>;\n };\n\n/** 左边是一棵树的穿梭框 */\nexport interface TreeTransferProps<T> extends TransferBaseProps {\n /** 第一层的节点 */\n items: readonly T[];\n /** 节点的 key,整棵树里唯一 */\n getKey: (node: T) => string;\n /** 节点的文字 */\n getLabel: (node: T) => string;\n /** 子节点 */\n getChildren: (node: T) => readonly T[] | undefined;\n /** 左边的树的部件属性 */\n propsTree?: Partial<TreeProps<T>>;\n /** 右边列表的部件属性 */\n propsList?: Partial<TransferListProps<ListboxOption>>;\n}\n\n/** Transfer 的样式:root、panel、header、title、search、list、actions、actionIcon */\nexport const transferStyles = css.create({\n // 窄屏时上下排,按钮换成上下箭头\n root: {\n display: 'grid',\n gridTemplateColumns: {\n default: 'minmax(0, 1fr) auto minmax(0, 1fr)',\n '@media (max-width: 40rem)': 'minmax(0, 1fr)',\n },\n alignItems: 'stretch',\n gap: '_md',\n },\n panel: {\n display: 'flex',\n flexDirection: 'column',\n minWidth: 0,\n height: '20em',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_border',\n borderRadius: '_md',\n backgroundColor: '_surface',\n overflow: 'hidden',\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n gap: '_sm',\n paddingBlock: '_xs',\n paddingInline: '_sm',\n borderBlockEndWidth: '_xs',\n borderBlockEndStyle: 'solid',\n borderBlockEndColor: '_borderMuted',\n },\n title: { flexGrow: 1, minWidth: 0, fontWeight: '_semibold' },\n search: { padding: '_xs', flexShrink: 0 },\n searchField: { width: '_full' },\n // 列表占满剩下的高度,自己滚动(虚拟滚动要有确定的高度)\n list: { flexGrow: 1, minHeight: 0, borderWidth: 0, borderRadius: 0 },\n actions: {\n display: 'flex',\n flexDirection: { default: 'column', '@media (max-width: 40rem)': 'row' },\n justifyContent: 'center',\n gap: '_sm',\n },\n actionIcon: { rotate: { default: null, '@media (max-width: 40rem)': '90deg' } },\n});\n\ninterface PanelOptions {\n title: string;\n titleId: string;\n /** 看得见的、能勾的项 */\n selectable: readonly string[];\n /** 勾上的 */\n checked: readonly string[];\n /** 这一边一共几项 */\n total: number;\n onCheckAll: (keys: string[]) => void;\n search: string;\n onSearch: (text: string) => void;\n searchable: boolean;\n disabled: boolean;\n propsPanel?: PartProps<'section'>;\n propsSearch?: Partial<TextFieldProps>;\n list: VNodeChild;\n}\n\n/** 一边:全选框、标题、计数、搜索框与列表 */\nfunction renderPanel(lang: ReturnType<typeof useLang>, options: PanelOptions) {\n const visibleChecked = options.selectable.filter((key) => options.checked.includes(key));\n const all = options.selectable.length > 0 && visibleChecked.length === options.selectable.length;\n return (\n <section\n {...mergeAttrs<'section'>({ sx: transferStyles.panel }, options.propsPanel, {\n 'aria-labelledby': options.titleId,\n })}\n >\n <div {...css.attrs(transferStyles.header)}>\n <Checkbox\n _checked={all}\n onUpdate:_checked={(next: boolean) => {\n const others = options.checked.filter((key) => !options.selectable.includes(key));\n options.onCheckAll(next ? [...others, ...options.selectable] : others);\n }}\n indeterminate={!all && visibleChecked.length > 0}\n disabled={options.disabled || options.selectable.length === 0}\n aria-label={lang.transferSelectAll(options.title)}\n />\n <span id={options.titleId} {...css.attrs(transferStyles.title)}>\n {options.title}\n </span>\n <Small tone=\"muted\">{lang.transferCount(options.checked.length, options.total)}</Small>\n </div>\n {options.searchable && (\n <div {...css.attrs(transferStyles.search)}>\n <TextField\n {...mergePartProps<TextFieldProps>(\n {\n icon: Search,\n variant: 'soft',\n size: 'sm',\n placeholder: lang.selectSearch,\n 'aria-label': `${lang.selectSearch} ${options.title}`,\n propsRoot: { sx: transferStyles.searchField },\n },\n options.propsSearch,\n )}\n type=\"search\"\n _value={options.search}\n onUpdate:_value={options.onSearch}\n disabled={options.disabled}\n />\n </div>\n )}\n {options.list}\n </section>\n );\n}\n\n/** 中间的两个按钮 */\nfunction renderActions(\n lang: ReturnType<typeof useLang>,\n titles: readonly [string, string],\n enabled: readonly [boolean, boolean],\n move: readonly [() => void, () => void],\n propsAction: Partial<IconButtonProps> | undefined,\n) {\n return (\n <div {...css.attrs(transferStyles.actions)}>\n {([1, 0] as const).map((to) => (\n <IconButton\n key={to}\n {...mergePartProps<IconButtonProps>(\n {\n icon: to === 1 ? ChevronRight : ChevronLeft,\n 'aria-label': lang.transferMoveTo(titles[to]),\n variant: 'soft',\n size: 'sm',\n propsIcon: { flipInRtl: true, sx: transferStyles.actionIcon },\n },\n propsAction,\n { disabled: !enabled[to], onClick: move[to] },\n )}\n />\n ))}\n </div>\n );\n}\n\n/** 穿梭框:两个可多选的列表,勾上之后移到另一边 */\nexport const Transfer = _component(\n <T,>({\n items,\n toOption,\n _value: value = _bindable<string[]>([]),\n titles,\n searchable = false,\n filter,\n disabled,\n propsPanel,\n propsSearch,\n propsAction,\n propsList,\n ...rest\n }: TransferProps<T>) => {\n const lang = useLang();\n const textMatcher = useTextMatcher();\n const field = useFieldControl(() => ({ disabled }));\n const baseId = useId();\n let checked = _state<[string[], string[]]>([[], []]);\n let searches = _state<[string, string]>(['', '']);\n\n const entries = _derived.by(() =>\n items.map((item) => ({ item, option: toListboxOption(item, toOption) })),\n );\n const byValue = _derived.by(() => new Map(entries.map((entry) => [entry.option.value, entry])));\n const chosen = _derived.by(() => new Set(value));\n const titleOf = (side: 0 | 1) =>\n titles?.[side] ?? (side === 0 ? lang.transferSource : lang.transferTarget);\n\n const matches = (entry: (typeof entries)[number], query: string) => {\n const text = query.trim();\n if (!text) return true;\n return filter ? filter(entry.item, text) : textMatcher()(entry.option.label, text);\n };\n /** 一边的全部项(左边按 items 的顺序,右边按移过去的先后) */\n const sideEntries = (side: 0 | 1) =>\n side === 0\n ? entries.filter((entry) => !chosen.has(entry.option.value))\n : value.flatMap((key) => byValue.get(key) ?? []);\n const shownEntries = (side: 0 | 1) =>\n sideEntries(side).filter((entry) => matches(entry, searches[side]));\n\n function setChecked(side: 0 | 1, keys: string[]) {\n checked = side === 0 ? [keys, checked[1]] : [checked[0], keys];\n }\n\n /** 把 keys 从 from 这一边移到另一边 */\n function move(from: 0 | 1, keys: readonly string[]) {\n const movable = keys.filter((key) => {\n const entry = byValue.get(key);\n return entry && !entry.option.disabled && chosen.has(key) === (from === 1);\n });\n if (field().disabled || movable.length === 0) return;\n const moving = new Set(movable);\n value = from === 0 ? [...value, ...movable] : value.filter((key) => !moving.has(key));\n setChecked(\n from,\n checked[from].filter((key) => !moving.has(key)),\n );\n announce(lang.transferMoved(movable.length, titleOf(from === 0 ? 1 : 0)));\n }\n\n return () => {\n const state = field();\n const list = (side: 0 | 1) => (\n <Listbox\n {...(mergePartProps<TransferListProps<T>>(\n {\n items: shownEntries(side).map((entry) => entry.item),\n toOption: (item: T) => toListboxOption(item, toOption),\n selectionMode: 'multiple',\n sx: transferStyles.list,\n propsOption: (item: T) => ({\n // 双击直接移过去\n onDblclick: () => move(side, [toListboxOption(item, toOption).value]),\n }),\n } as TransferListProps<T>,\n propsList,\n {\n disabled: state.disabled,\n id: `${baseId}-${side}`,\n 'aria-labelledby': `${baseId}-title-${side}`,\n } as Partial<TransferListProps<T>>,\n ) as ListboxProps<T> & UpdateHandlers<ListboxProps<T>>)}\n _value={checked[side]}\n onUpdate:_value={(next: string[]) => setChecked(side, next)}\n />\n );\n const panel = (side: 0 | 1) =>\n renderPanel(lang, {\n title: titleOf(side),\n titleId: `${baseId}-title-${side}`,\n selectable: shownEntries(side)\n .filter((entry) => !entry.option.disabled)\n .map((entry) => entry.option.value),\n checked: checked[side],\n total: sideEntries(side).length,\n onCheckAll: (keys) => setChecked(side, keys),\n search: searches[side],\n onSearch: (text) => (searches = side === 0 ? [text, searches[1]] : [searches[0], text]),\n searchable,\n disabled: state.disabled,\n propsPanel,\n propsSearch,\n list: list(side),\n });\n return (\n <div\n {...mergeAttrs<'div'>({ sx: transferStyles.root }, rest, {\n role: 'group',\n 'aria-labelledby': rest['aria-labelledby'] ?? state.labelledBy,\n 'aria-describedby': state.describedBy,\n })}\n >\n {panel(0)}\n {renderActions(\n lang,\n [titleOf(0), titleOf(1)],\n [!state.disabled && checked[1].length > 0, !state.disabled && checked[0].length > 0],\n [() => move(1, checked[1]), () => move(0, checked[0])],\n propsAction,\n )}\n {panel(1)}\n </div>\n );\n };\n },\n);\n\n/** 左边是一棵树的穿梭框:勾选叶子(父子联动)移到右边 */\nexport const TreeTransfer = _component(\n <T,>({\n items,\n getKey,\n getLabel,\n getChildren,\n _value: value = _bindable<string[]>([]),\n titles,\n searchable = false,\n disabled,\n propsPanel,\n propsSearch,\n propsAction,\n propsTree,\n propsList,\n ...rest\n }: TreeTransferProps<T>) => {\n const lang = useLang();\n const textMatcher = useTextMatcher();\n const field = useFieldControl(() => ({ disabled }));\n const baseId = useId();\n let checked = _state<[string[], string[]]>([[], []]);\n let searches = _state<[string, string]>(['', '']);\n let expanded = _state<string[]>([]);\n\n const index = _derived.by(() =>\n indexTree(items, { getKey: (node) => getKey(node), getChildren }),\n );\n // key → 节点:右边的文字、左边“不可用”的判断都用它\n const nodes = _derived.by(() => {\n const map = new Map<string, T>();\n const visit = (level: readonly T[]) =>\n level.forEach((node) => {\n map.set(getKey(node), node);\n visit(getChildren(node) ?? []);\n });\n visit(items);\n return map;\n });\n const leaves = _derived.by(() => index.order.filter((key) => !index.children.get(key)?.length));\n const chosen = _derived.by(() => new Set(value));\n const titleOf = (side: 0 | 1) =>\n titles?.[side] ?? (side === 0 ? lang.transferSource : lang.transferTarget);\n const matchesSearch = (key: string, side: 0 | 1) => {\n const text = searches[side].trim();\n const node = nodes.get(key);\n return !text || (!!node && textMatcher()(getLabel(node), text));\n };\n // 左边能勾的叶子:还没移过去的(搜索时只算匹配的)\n const sourceLeaves = () => leaves.filter((key) => !chosen.has(key));\n const targetOptions = () =>\n value.flatMap((key) => {\n const node = nodes.get(key);\n return node ? [{ value: key, label: getLabel(node) }] : [];\n });\n\n function setChecked(side: 0 | 1, keys: string[]) {\n checked = side === 0 ? [keys, checked[1]] : [checked[0], keys];\n }\n\n function move(from: 0 | 1, keys: readonly string[]) {\n const movable = keys.filter((key) => nodes.has(key) && chosen.has(key) === (from === 1));\n if (field().disabled || movable.length === 0) return;\n const moving = new Set(movable);\n value = from === 0 ? [...value, ...movable] : value.filter((key) => !moving.has(key));\n setChecked(\n from,\n checked[from].filter((key) => !moving.has(key)),\n );\n announce(lang.transferMoved(movable.length, titleOf(from === 0 ? 1 : 0)));\n }\n\n return () => {\n const state = field();\n const sourceChecked = checked[0];\n const tree = (\n <Tree\n {...mergePartProps<TreeProps<T>>(\n {\n items,\n getKey,\n getLabel,\n getChildren,\n checkable: true,\n // 已经移过去的叶子勾上且不可用\n isDisabled: (node: T) => state.disabled || chosen.has(getKey(node)),\n filter: searches[0],\n propsScrollArea: { sx: transferStyles.list },\n },\n propsTree,\n { 'aria-labelledby': `${baseId}-title-0` },\n )}\n _checked={[...value, ...sourceChecked]}\n onUpdate:_checked={(next: string[]) =>\n setChecked(\n 0,\n checkedByStrategy(index, next, 'child').filter((key) => !chosen.has(key)),\n )\n }\n _expanded={expanded}\n />\n );\n const list = (\n <Listbox\n {...mergePartProps<TransferListProps<ListboxOption>>(\n {\n items: targetOptions().filter((option) => matchesSearch(option.value, 1)),\n selectionMode: 'multiple',\n sx: transferStyles.list,\n propsOption: (option: ListboxOption) => ({\n onDblclick: () => move(1, [option.value]),\n }),\n } as TransferListProps<ListboxOption>,\n propsList,\n {\n disabled: state.disabled,\n id: `${baseId}-1`,\n 'aria-labelledby': `${baseId}-title-1`,\n } as Partial<TransferListProps<ListboxOption>>,\n )}\n _value={checked[1]}\n onUpdate:_value={(next: string[]) => setChecked(1, next)}\n />\n );\n const panel = (side: 0 | 1, selectable: string[], total: number, body: VNodeChild) =>\n renderPanel(lang, {\n title: titleOf(side),\n titleId: `${baseId}-title-${side}`,\n selectable,\n checked: checked[side],\n total,\n onCheckAll: (keys) => setChecked(side, keys),\n search: searches[side],\n onSearch: (text) => (searches = side === 0 ? [text, searches[1]] : [searches[0], text]),\n searchable,\n disabled: state.disabled,\n propsPanel,\n propsSearch,\n list: body,\n });\n return (\n <div\n {...mergeAttrs<'div'>({ sx: transferStyles.root }, rest, {\n role: 'group',\n 'aria-labelledby': rest['aria-labelledby'] ?? state.labelledBy,\n 'aria-describedby': state.describedBy,\n })}\n >\n {panel(\n 0,\n sourceLeaves().filter((key) => matchesSearch(key, 0)),\n sourceLeaves().length,\n tree,\n )}\n {renderActions(\n lang,\n [titleOf(0), titleOf(1)],\n [!state.disabled && checked[1].length > 0, !state.disabled && sourceChecked.length > 0],\n [() => move(1, checked[1]), () => move(0, sourceChecked)],\n propsAction,\n )}\n {panel(\n 1,\n value.filter((key) => matchesSearch(key, 1)),\n targetOptions().length,\n list,\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,SAAA,QAAA,GAAA;CAAA,OAAA,OAAA,MAAA,cAAA,OAAA,UAAA,SAAA,KAAA,CAAA,MAAA,qBAAA,CAAAA,QAAA,CAAA;AAAA;;AAiBA,IAAa,iBAAiB,IAAI,OAAO;CAEvC,MAAM;EACJ,SAAS;EACT,qBAAqB;GACnB,SAAS;GACT,6BAA6B;EAC/B;EACA,YAAY;EACZ,KAAK;CACP;CACA,OAAO;EACL,SAAS;EACT,eAAe;EACf,UAAU;EACV,QAAQ;EACR,aAAa;EACb,aAAa;EACb,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,UAAU;CACZ;CACA,QAAQ;EACN,SAAS;EACT,YAAY;EACZ,KAAK;EACL,cAAc;EACd,eAAe;EACf,qBAAqB;EACrB,qBAAqB;EACrB,qBAAqB;CACvB;CACA,OAAO;EAAE,UAAU;EAAG,UAAU;EAAG,YAAY;CAAY;CAC3D,QAAQ;EAAE,SAAS;EAAO,YAAY;CAAE;CACxC,aAAa,EAAE,OAAO,QAAQ;CAE9B,MAAM;EAAE,UAAU;EAAG,WAAW;EAAG,aAAa;EAAG,cAAc;CAAE;CACnE,SAAS;EACP,SAAS;EACT,eAAe;GAAE,SAAS;GAAU,6BAA6B;EAAM;EACvE,gBAAgB;EAChB,KAAK;CACP;CACA,YAAY,EAAE,QAAQ;EAAE,SAAS;EAAM,6BAA6B;CAAQ,EAAE;AAChF,CAAC;;AAsBD,SAAS,YAAY,MAAkC,SAAuB;CAAA,IAAA;CAC5E,MAAM,iBAAiB,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,QAAQ,SAAS,GAAG,CAAC;CACvF,MAAM,MAAM,QAAQ,WAAW,SAAS,KAAK,eAAe,WAAW,QAAQ,WAAW;CAC1F,OAAAC,YAAA,WAEQ,WAAsB,EAAE,IAAI,eAAe,MAAM,GAAG,QAAQ,YAAY,EAC1E,mBAAmB,QAAQ,QAC7B,CAAC,GAAC;EAAAA,YAAA,OAEO,IAAI,MAAM,eAAe,MAAM,GAAC;GAAAA,YAAA,UAAA;IAAA,YAE3B;IAAG,sBACO,SAAkB;KACpC,MAAM,SAAS,QAAQ,QAAQ,QAAQ,QAAQ,CAAC,QAAQ,WAAW,SAAS,GAAG,CAAC;KAChF,QAAQ,WAAW,OAAO,CAAC,GAAG,QAAQ,GAAG,QAAQ,UAAU,IAAI,MAAM;IACvE;IAAC,iBACc,CAAC,OAAO,eAAe,SAAS;IAAC,YACtC,QAAQ,YAAY,QAAQ,WAAW,WAAW;IAAC,cACjD,KAAK,kBAAkB,QAAQ,KAAK;GAAC,GAAA,IAAA;GAAAA,YAAA,QAAAC,WAAA,EAAA,MAEzC,QAAQ,QAAO,GAAM,IAAI,MAAM,eAAe,KAAK,CAAC,GAAA,CAC3D,QAAQ,KAAK,CAAA;GAAAD,YAAA,OAAA,EAAA,QAAA,QAAA,GAAA,QAAA,QAEK,KAAK,cAAc,QAAQ,QAAQ,QAAQ,QAAQ,KAAK,CAAC,IAAA,QAAA,EAAA,eAAA,CAAA,KAAA,EAAA,CAAA;EAAA,CAAA;EAE/E,QAAQ,cAAUA,YAAA,OACR,IAAI,MAAM,eAAe,MAAM,GAAC,CAAAA,YAAA,WAAAC,WAEjC,eACF;GACE,MAAM;GACN,SAAS;GACT,MAAM;GACN,aAAa,KAAK;GAClB,cAAc,GAAG,KAAK,aAAY,GAAI,QAAQ;GAC9C,WAAW,EAAE,IAAI,eAAe,YAAY;EAC9C,GACA,QAAQ,WACV,GAAC;GAAA,QAAA;GAAA,UAEO,QAAQ;GAAM,mBACL,QAAQ;GAAQ,YACvB,QAAQ;EAAQ,CAAA,GAAA,IAAA,CAAA,CAAA;EAI/B,QAAQ;CAAI,CAAA;AAGnB;;AAGA,SAAS,cACP,MACA,QACA,SACA,MACA,aACA;CACA,OAAAD,YAAA,OACW,IAAI,MAAM,eAAe,OAAO,GAAC,CACtC,CAAC,GAAG,CAAC,CAAC,CAAW,KAAK,OAAEA,YAAA,YAAAC,WAAA,EAAA,OAEjB,GAAE,GACH,eACF;EACE,MAAM,OAAO,IAAI,eAAe;EAChC,cAAc,KAAK,eAAe,OAAO,GAAG;EAC5C,SAAS;EACT,MAAM;EACN,WAAW;GAAE,WAAW;GAAM,IAAI,eAAe;EAAW;CAC9D,GACA,aACA;EAAE,UAAU,CAAC,QAAQ;EAAK,SAAS,KAAK;CAAI,CAC9C,CAAC,GAAA,IAAA,CAEJ,CAAC,CAAA;AAGR;;AAGA,IAAa,WAAW,0BACtB,QAAA,SAawB;CAAA,MAAA,QAAAC,aAAA,QAAA,OAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,QAAAC,SAAA,QAAA,gBAVc,CAAA,GAAE,KAAA,IAAA;CAAA,MAAA,SAAAD,aAAA,QAAA,QAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,cAEzB,KAAK;CAAA,MAAA,SAAAA,aAAA,QAAA,QAAA;CAAA,MAAA,WAAAA,aAAA,QAAA,UAAA;CAAA,MAAA,aAAAA,aAAA,QAAA,YAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,cAAAA,aAAA,QAAA,aAAA;CAAA,MAAA,YAAAA,aAAA,QAAA,WAAA;CAAA,MAOf,OAAIE,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,OAAO,QAAQ;CACrB,MAAM,cAAc,eAAe;CACnC,MAAM,QAAQ,uBAAuB,EAAE,UAAQ,SAAA,MAAC,EAAE;CAClD,MAAM,SAAS,MAAM;CACrB,IAAI,UAAOC,IAAgC,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC;CACnD,IAAI,WAAQA,IAA4B,CAAC,IAAI,EAAE,CAAC;CAEhD,MAAM,UAAOC,eACX,MAAA,MAAM,KAAK,UAAU;EAAE;EAAM,QAAQ,gBAAgB,MAAI,SAAA,KAAU;CAAE,EAAE,CAAC;CAE1E,MAAM,UAAOA,eAAqB,IAAI,IAAI,QAAA,MAAQ,KAAK,UAAU,CAAC,MAAM,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC;CAC9F,MAAM,SAAMA,eAAqB,IAAI,IAAG,MAAA,KAAM,CAAC;CAC/C,MAAM,WAAW,SACf,OAAA,QAAS,UAAU,SAAS,IAAI,KAAK,iBAAiB,KAAK;CAE7D,MAAM,WAAW,OAAiC,UAAkB;EAClE,MAAM,OAAO,MAAM,KAAK;EACxB,IAAI,CAAC,MAAM,OAAO;EAClB,OAAO,OAAA,QAAS,OAAA,MAAO,MAAM,MAAM,IAAI,IAAI,YAAY,CAAC,CAAC,MAAM,OAAO,OAAO,IAAI;CACnF;;CAEA,MAAM,eAAe,SACnB,SAAS,IACL,QAAA,MAAQ,QAAQ,UAAU,CAAC,OAAA,MAAO,IAAI,MAAM,OAAO,KAAK,CAAC,IACzD,MAAA,MAAM,SAAS,QAAQ,QAAA,MAAQ,IAAI,GAAG,KAAK,CAAA,CAAE;CACnD,MAAM,gBAAgB,SACpB,YAAY,IAAI,CAAC,CAAC,QAAQ,UAAU,QAAQ,OAAO,SAAA,MAAS,KAAK,CAAC;CAEpE,SAAS,WAAW,MAAa,MAAgB;EAC/C,QAAA,QAAU,SAAS,IAAI,CAAC,MAAM,QAAA,MAAQ,EAAE,IAAI,CAAC,QAAA,MAAQ,IAAI,IAAI;CAC/D;;CAGA,SAAS,KAAK,MAAa,MAAyB;EAClD,MAAM,UAAU,KAAK,QAAQ,QAAQ;GACnC,MAAM,QAAQ,QAAA,MAAQ,IAAI,GAAG;GAC7B,OAAO,SAAS,CAAC,MAAM,OAAO,YAAY,OAAA,MAAO,IAAI,GAAG,OAAO,SAAS;EAC1E,CAAC;EACD,IAAI,MAAM,CAAC,CAAC,YAAY,QAAQ,WAAW,GAAG;EAC9C,MAAM,SAAS,IAAI,IAAI,OAAO;EAC9B,MAAA,QAAQ,SAAS,IAAI,CAAC,GAAA,MAAA,OAAU,GAAG,OAAO,IAAI,MAAA,MAAM,QAAQ,QAAQ,CAAC,OAAO,IAAI,GAAG,CAAC;EACpF,WACE,MACA,QAAA,MAAQ,KAAK,CAAC,QAAQ,QAAQ,CAAC,OAAO,IAAI,GAAG,CAAC,CAChD;EACA,SAAS,KAAK,cAAc,QAAQ,QAAQ,QAAQ,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC;CAC1E;CAEA,aAAa;EACX,MAAM,QAAQ,MAAM;EACpB,MAAM,QAAQ,SAAWN,YAAA,SAAAC,WAEhB,eACH;GACE,OAAO,aAAa,IAAI,CAAC,CAAC,KAAK,UAAU,MAAM,IAAI;GACnD,WAAW,SAAY,gBAAgB,MAAI,SAAA,KAAU;GACrD,eAAe;GACf,IAAI,eAAe;GACnB,cAAc,UAAa,EAEzB,kBAAkB,KAAK,MAAM,CAAC,gBAAgB,MAAI,SAAA,KAAU,CAAC,CAAC,KAAK,CAAC,EACtE;EACF,GAAC,UAAA,OAED;GACE,UAAU,MAAM;GAChB,IAAI,GAAG,OAAM,GAAI;GACjB,mBAAmB,GAAG,OAAM,SAAU;EACxC,CACF,GAAC;GAAA,UACO,QAAA,MAAQ;GAAK,oBACH,SAAmB,WAAW,MAAM,IAAI;EAAC,CAAA,GAAA,IAAA;EAG/D,MAAM,SAAS,SACb,YAAY,MAAM;GAChB,OAAO,QAAQ,IAAI;GACnB,SAAS,GAAG,OAAM,SAAU;GAC5B,YAAY,aAAa,IAAI,CAAC,CAC3B,QAAQ,UAAU,CAAC,MAAM,OAAO,QAAQ,CAAC,CACzC,KAAK,UAAU,MAAM,OAAO,KAAK;GACpC,SAAS,QAAA,MAAQ;GACjB,OAAO,YAAY,IAAI,CAAC,CAAC;GACzB,aAAa,SAAS,WAAW,MAAM,IAAI;GAC3C,QAAQ,SAAA,MAAS;GACjB,WAAW,SAAU,SAAA,QAAW,SAAS,IAAI,CAAC,MAAM,SAAA,MAAS,EAAE,IAAI,CAAC,SAAA,MAAS,IAAI,IAAI;GACrF,YAAU,WAAA;GACV,UAAU,MAAM;GAChB,YAAU,WAAA;GACV,aAAW,YAAA;GACX,MAAM,KAAK,IAAI;EACjB,CAAC;EACH,OAAAD,YAAA,OAEQ,WAAkB,EAAE,IAAI,eAAe,KAAK,GAAG,MAAM;GACvD,MAAM;GACN,mBAAmB,KAAK,sBAAsB,MAAM;GACpD,oBAAoB,MAAM;EAC5B,CAAC,GAAC;GAED,MAAM,CAAC;GACP,cACC,MACA,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,GACvB,CAAC,CAAC,MAAM,YAAY,QAAA,MAAQ,EAAE,CAAC,SAAS,GAAG,CAAC,MAAM,YAAY,QAAA,MAAQ,EAAE,CAAC,SAAS,CAAC,GACnF,OAAO,KAAK,GAAG,QAAA,MAAQ,EAAE,SAAS,KAAK,GAAG,QAAA,MAAQ,EAAE,CAAC,GAAC,YAAA,KAExD;GACC,MAAM,CAAC;EAAC,CAAA;CAGf;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH;;AAGA,IAAa,eAAe,0BAC1B,SAAA,UAe4B;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,QAAAE,aAAA,SAAA,OAAA;CAAA,MAAA,SAAAA,aAAA,SAAA,QAAA;CAAA,MAAA,WAAAA,aAAA,SAAA,UAAA;CAAA,MAAA,cAAAA,aAAA,SAAA,aAAA;CAAA,MAAA,QAAAC,SAAA,SAAA,gBAVU,CAAA,GAAE,MAAA,IAAA;CAAA,MAAA,SAAAD,aAAA,SAAA,QAAA;CAAA,MAAA,aAAAA,aAAA,SAAA,cAEzB,KAAK;CAAA,MAAA,WAAAA,aAAA,SAAA,UAAA;CAAA,MAAA,aAAAA,aAAA,SAAA,YAAA;CAAA,MAAA,cAAAA,aAAA,SAAA,aAAA;CAAA,MAAA,cAAAA,aAAA,SAAA,aAAA;CAAA,MAAA,YAAAA,aAAA,SAAA,WAAA;CAAA,MAAA,YAAAA,aAAA,SAAA,WAAA;CAAA,MAOf,OAAIE,UAAA,SAAA,OAAA,IAAA;CAEP,MAAM,OAAO,QAAQ;CACrB,MAAM,cAAc,eAAe;CACnC,MAAM,QAAQ,uBAAuB,EAAE,UAAQ,SAAA,MAAC,EAAE;CAClD,MAAM,SAAS,MAAM;CACrB,IAAI,UAAOC,IAAgC,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC;CACnD,IAAI,WAAQA,IAA4B,CAAC,IAAI,EAAE,CAAC;CAChD,IAAI,WAAQA,IAAoB,CAAA,CAAE;CAElC,MAAM,QAAKC,eACT,UAAS,MAAA,OAAQ;EAAE,SAAS,SAAS,OAAA,MAAO,IAAI;EAAG,aAAW,YAAA;CAAC,CAAC,CAAC;CAGnE,MAAM,QAAKA,eAAqB;EAC9B,MAAM,sBAAM,IAAI,IAAe;EAC/B,MAAM,SAAS,UACb,MAAM,SAAS,SAAS;GACtB,IAAI,IAAI,OAAA,MAAO,IAAI,GAAG,IAAI;GAC1B,MAAM,YAAA,MAAY,IAAI,KAAK,CAAA,CAAE;EAC/B,CAAC;EACH,MAAK,MAAA,KAAM;EACX,OAAO;CACT,CAAC;CACD,MAAM,SAAMA,eAAqB,MAAA,MAAM,MAAM,QAAQ,QAAQ,CAAC,MAAA,MAAM,SAAS,IAAI,GAAG,CAAC,EAAE,MAAM,CAAC;CAC9F,MAAM,SAAMA,eAAqB,IAAI,IAAG,MAAA,KAAM,CAAC;CAC/C,MAAM,WAAW,SACf,OAAA,QAAS,UAAU,SAAS,IAAI,KAAK,iBAAiB,KAAK;CAC7D,MAAM,iBAAiB,KAAa,SAAgB;EAClD,MAAM,OAAO,SAAA,MAAS,KAAK,CAAC,KAAK;EACjC,MAAM,OAAO,MAAA,MAAM,IAAI,GAAG;EAC1B,OAAO,CAAC,QAAS,CAAC,CAAC,QAAQ,YAAY,CAAC,CAAC,SAAA,MAAS,IAAI,GAAG,IAAI;CAC/D;CAEA,MAAM,qBAAqB,OAAA,MAAO,QAAQ,QAAQ,CAAC,OAAA,MAAO,IAAI,GAAG,CAAC;CAClE,MAAM,sBACJ,MAAA,MAAM,SAAS,QAAQ;EACrB,MAAM,OAAO,MAAA,MAAM,IAAI,GAAG;EAC1B,OAAO,OAAO,CAAC;GAAE,OAAO;GAAK,OAAO,SAAA,MAAS,IAAI;EAAE,CAAC,IAAI,CAAA;CAC1D,CAAC;CAEH,SAAS,WAAW,MAAa,MAAgB;EAC/C,QAAA,QAAU,SAAS,IAAI,CAAC,MAAM,QAAA,MAAQ,EAAE,IAAI,CAAC,QAAA,MAAQ,IAAI,IAAI;CAC/D;CAEA,SAAS,KAAK,MAAa,MAAyB;EAClD,MAAM,UAAU,KAAK,QAAQ,QAAQ,MAAA,MAAM,IAAI,GAAG,KAAK,OAAA,MAAO,IAAI,GAAG,OAAO,SAAS,EAAE;EACvF,IAAI,MAAM,CAAC,CAAC,YAAY,QAAQ,WAAW,GAAG;EAC9C,MAAM,SAAS,IAAI,IAAI,OAAO;EAC9B,MAAA,QAAQ,SAAS,IAAI,CAAC,GAAA,MAAA,OAAU,GAAG,OAAO,IAAI,MAAA,MAAM,QAAQ,QAAQ,CAAC,OAAO,IAAI,GAAG,CAAC;EACpF,WACE,MACA,QAAA,MAAQ,KAAK,CAAC,QAAQ,QAAQ,CAAC,OAAO,IAAI,GAAG,CAAC,CAChD;EACA,SAAS,KAAK,cAAc,QAAQ,QAAQ,QAAQ,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC;CAC1E;CAEA,aAAa;EACX,MAAM,QAAQ,MAAM;EACpB,MAAM,gBAAgB,QAAA,MAAQ;EAC9B,MAAM,OAAIN,YAAA,MAAAC,WAEF,eACF;GACE,OAAK,MAAA;GACL,QAAM,OAAA;GACN,UAAQ,SAAA;GACR,aAAW,YAAA;GACX,WAAW;GAEX,aAAa,SAAY,MAAM,YAAY,OAAA,MAAO,IAAI,OAAA,MAAO,IAAI,CAAC;GAClE,QAAQ,SAAA,MAAS;GACjB,iBAAiB,EAAE,IAAI,eAAe,KAAK;EAC7C,GAAC,UAAA,OAED,EAAE,mBAAmB,GAAG,OAAM,UAAW,CAC3C,GAAC;GAAA,YACS,CAAC,GAAA,MAAA,OAAU,GAAG,aAAa;GAAC,qBAAA,OAAA,OAAA,OAAA,MAClB,SAClB,WACE,GACA,kBAAiB,MAAA,OAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,QAAQ,CAAC,OAAA,MAAO,IAAI,GAAG,CAAC,CAC1E;GAAC,aAAA,SAAA;GAAA,sBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,SAAA,QAAA;EAAA,CAAA,GAAA,IAAA;EAKP,MAAM,OAAID,YAAA,SAAAC,WAEF,eACF;GACE,OAAO,cAAc,CAAC,CAAC,QAAQ,WAAW,cAAc,OAAO,OAAO,CAAC,CAAC;GACxE,eAAe;GACf,IAAI,eAAe;GACnB,cAAc,YAA2B,EACvC,kBAAkB,KAAK,GAAG,CAAC,OAAO,KAAK,CAAC,EAC1C;EACF,GAAC,UAAA,OAED;GACE,UAAU,MAAM;GAChB,IAAI,GAAG,OAAM;GACb,mBAAmB,GAAG,OAAM;EAC9B,CACF,GAAC;GAAA,UACO,QAAA,MAAQ;GAAE,mBAAA,OAAA,OAAA,OAAA,MACA,SAAmB,WAAW,GAAG,IAAI;EAAC,CAAA,GAAA,IAAA;EAG5D,MAAM,SAAS,MAAa,YAAsB,OAAe,SAC/D,YAAY,MAAM;GAChB,OAAO,QAAQ,IAAI;GACnB,SAAS,GAAG,OAAM,SAAU;GAC5B;GACA,SAAS,QAAA,MAAQ;GACjB;GACA,aAAa,SAAS,WAAW,MAAM,IAAI;GAC3C,QAAQ,SAAA,MAAS;GACjB,WAAW,SAAU,SAAA,QAAW,SAAS,IAAI,CAAC,MAAM,SAAA,MAAS,EAAE,IAAI,CAAC,SAAA,MAAS,IAAI,IAAI;GACrF,YAAU,WAAA;GACV,UAAU,MAAM;GAChB,YAAU,WAAA;GACV,aAAW,YAAA;GACX,MAAM;EACR,CAAC;EACH,OAAAD,YAAA,OAEQ,WAAkB,EAAE,IAAI,eAAe,KAAK,GAAG,MAAM;GACvD,MAAM;GACN,mBAAmB,KAAK,sBAAsB,MAAM;GACpD,oBAAoB,MAAM;EAC5B,CAAC,GAAC;GAED,MACC,GACA,aAAa,CAAC,CAAC,QAAQ,QAAQ,cAAc,KAAK,CAAC,CAAC,GACpD,aAAa,CAAC,CAAC,QACf,IACF;GACC,cACC,MACA,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,GACvB,CAAC,CAAC,MAAM,YAAY,QAAA,MAAQ,EAAE,CAAC,SAAS,GAAG,CAAC,MAAM,YAAY,cAAc,SAAS,CAAC,GACtF,OAAO,KAAK,GAAG,QAAA,MAAQ,EAAE,SAAS,KAAK,GAAG,aAAa,CAAC,GAAC,YAAA,KAE3D;GACC,MACC,GACA,MAAA,MAAM,QAAQ,QAAQ,cAAc,KAAK,CAAC,CAAC,GAC3C,cAAc,CAAC,CAAC,QAChB,IACF;EAAC,CAAA;CAGP;AACF,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
|
1
|
+
{"version":3,"file":"Transfer.js","names":["_isVNode","_createVNode","_mergeProps","_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_ref","_vue_computed"],"sources":["../../src/input/Transfer.tsx"],"sourcesContent":["/**\n * 穿梭框:左边是可选的,右边是已选的,勾上之后点中间的按钮移过去(分配权限、指派成员、挑选导出的列)。\n *\n * <Transfer items={users} toOption={(user) => ({ value: user.id, label: user.name })} _value={memberIds} searchable />\n * <TreeTransfer items={orgs} getKey={…} getLabel={…} getChildren={…} _value={teamIds} /> 左边是一棵树\n *\n * - 每一边是一个可多选的 Listbox(焦点、方向键、空格勾选、虚拟滚动同 Listbox),上方是全选框、标题与“勾上 / 总数”,\n * searchable 时带搜索框(按选项文字,认 createUi 的 textMatcher)。全选只管当前看得见(搜索后留下)的项。\n * - 中间两个按钮把勾上的项移到另一边(没有勾上的时不可用),双击一项直接移过去;移动后读屏播报移了几项。\n * 不可用的选项(ListboxOption 的 disabled)勾不上,也就移不动。\n * - value 是右边的值,按移过去的先后排列;items 里找不到的值不显示(也不会被删掉)。\n * - TreeTransfer:左边是勾选的 Tree(父子联动、可搜索),已经移过去的节点勾上且不可用;只移叶子,value 是叶子的 key。\n * - 在 Field 里时整体是一组(role=\"group\",名称是 Field 的标签),两边的列表各以自己的标题为名。\n *\n * 部件:Root(div,role=\"group\")、Panel(section,每一边)、Header、SelectAll(Checkbox)、Title、Count、\n * Search(TextField)、List(Listbox / Tree)、Actions(中间的按钮)。\n */\nimport { ChevronLeft, ChevronRight, 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 type { UpdateHandlers } from '@zerodep-dev/vue-tsx-pro-tsx/jsx-runtime';\nimport { useId, type VNodeChild } from 'vue';\nimport { IconButton, type IconButtonProps } from '../base/IconButton';\nimport { Small } from '../base/Text';\nimport { useLang, useTextMatcher } from '../config/context';\nimport { Tree, type TreeProps } from '../display/Tree';\nimport { useFieldControl } from '../form/Field';\nimport { checkedByStrategy, indexTree } from '../utils/data/tree';\nimport { announce } from '../utils/dom/announcer';\nimport { mergeAttrs, mergePartProps, type PartProps } from '../utils/props';\nimport { Checkbox } from './Checkbox';\nimport { Listbox, type ListboxBaseProps, type ListboxProps } from './Listbox';\nimport type { MultipleSelectionProps } from '../utils/data/selection';\nimport { toListboxOption, type ListboxOption, type OptionMapping } from './list-state';\nimport { TextField, type TextFieldProps } from './TextField';\n\n/** 两边的列表(可多选的 Listbox)的属性:propsList 用它 */\nexport type TransferListProps<T> = ListboxBaseProps<T> & MultipleSelectionProps & OptionMapping<T>;\n\n/** Transfer 与 TreeTransfer 共有的属性;未声明的属性落到外层 div(role=\"group\")上 */\nexport interface TransferBaseProps extends PartProps<'div', 'role'> {\n /** 右边(已选)的值,按移过去的先后排列:父级写 _value={keys} */\n _value?: string[];\n /** 左右两边的标题,默认取语言包(可选、已选) */\n titles?: readonly [string, string];\n /** 两边带搜索框 */\n searchable?: boolean;\n /** 不可用:勾不了、移不了 */\n disabled?: boolean;\n /** 每一边的部件属性(section;列表的高度给它的 sx) */\n propsPanel?: PartProps<'section'>;\n /** 搜索框的部件属性 */\n propsSearch?: Partial<TextFieldProps>;\n /** 中间两个按钮的部件属性 */\n propsAction?: Partial<IconButtonProps>;\n}\n\n/** 选项是 ListboxOption、字符串,或任意数据加 toOption */\nexport type TransferProps<T = ListboxOption> = TransferBaseProps &\n OptionMapping<T> & {\n /** 全部数据(两边一起):右边显示 value 里的那些 */\n items: readonly T[];\n /** 搜索时怎样算匹配;默认选项文字包含输入(忽略大小写与重音,或 createUi 的 textMatcher) */\n filter?: (item: T, query: string) => boolean;\n /** 两边列表的部件属性 */\n propsList?: Partial<TransferListProps<T>>;\n };\n\n/** 左边是一棵树的穿梭框 */\nexport interface TreeTransferProps<T> extends TransferBaseProps {\n /** 第一层的节点 */\n items: readonly T[];\n /** 节点的 key,整棵树里唯一 */\n getKey: (node: T) => string;\n /** 节点的文字 */\n getLabel: (node: T) => string;\n /** 子节点 */\n getChildren: (node: T) => readonly T[] | undefined;\n /** 左边的树的部件属性 */\n propsTree?: Partial<TreeProps<T>>;\n /** 右边列表的部件属性 */\n propsList?: Partial<TransferListProps<ListboxOption>>;\n}\n\n/** Transfer 的样式:root、panel、header、title、search、list、actions、actionIcon */\nexport const transferStyles = css.create({\n // 窄屏时上下排,按钮换成上下箭头\n root: {\n display: 'grid',\n gridTemplateColumns: {\n default: 'minmax(0, 1fr) auto minmax(0, 1fr)',\n '@media (max-width: 40rem)': 'minmax(0, 1fr)',\n },\n alignItems: 'stretch',\n gap: '_md',\n },\n panel: {\n display: 'flex',\n flexDirection: 'column',\n minWidth: 0,\n height: '20em',\n borderWidth: '_xs',\n borderStyle: 'solid',\n borderColor: '_border',\n borderRadius: '_md',\n backgroundColor: '_surface',\n overflow: 'hidden',\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n gap: '_sm',\n paddingBlock: '_xs',\n paddingInline: '_sm',\n borderBlockEndWidth: '_xs',\n borderBlockEndStyle: 'solid',\n borderBlockEndColor: '_borderMuted',\n },\n title: { flexGrow: 1, minWidth: 0, fontWeight: '_semibold' },\n search: { padding: '_xs', flexShrink: 0 },\n searchField: { width: '_full' },\n // 列表占满剩下的高度,自己滚动(虚拟滚动要有确定的高度)\n list: { flexGrow: 1, minHeight: 0, borderWidth: 0, borderRadius: 0 },\n actions: {\n display: 'flex',\n flexDirection: { default: 'column', '@media (max-width: 40rem)': 'row' },\n justifyContent: 'center',\n gap: '_sm',\n },\n actionIcon: { rotate: { default: null, '@media (max-width: 40rem)': '90deg' } },\n});\n\ninterface PanelOptions {\n title: string;\n titleId: string;\n /** 看得见的、能勾的项 */\n selectable: readonly string[];\n /** 勾上的 */\n checked: readonly string[];\n /** 这一边一共几项 */\n total: number;\n onCheckAll: (keys: string[]) => void;\n search: string;\n onSearch: (text: string) => void;\n searchable: boolean;\n disabled: boolean;\n propsPanel?: PartProps<'section'>;\n propsSearch?: Partial<TextFieldProps>;\n list: VNodeChild;\n}\n\n/** 一边:全选框、标题、计数、搜索框与列表 */\nfunction renderPanel(lang: ReturnType<typeof useLang>, options: PanelOptions) {\n const visibleChecked = options.selectable.filter((key) => options.checked.includes(key));\n const all = options.selectable.length > 0 && visibleChecked.length === options.selectable.length;\n return (\n <section\n {...mergeAttrs<'section'>({ sx: transferStyles.panel }, options.propsPanel, {\n 'aria-labelledby': options.titleId,\n })}\n >\n <div {...css.attrs(transferStyles.header)}>\n <Checkbox\n _checked={all}\n onUpdate:_checked={(next: boolean) => {\n const others = options.checked.filter((key) => !options.selectable.includes(key));\n options.onCheckAll(next ? [...others, ...options.selectable] : others);\n }}\n indeterminate={!all && visibleChecked.length > 0}\n disabled={options.disabled || options.selectable.length === 0}\n aria-label={lang.transferSelectAll(options.title)}\n />\n <span id={options.titleId} {...css.attrs(transferStyles.title)}>\n {options.title}\n </span>\n <Small tone=\"muted\">{lang.transferCount(options.checked.length, options.total)}</Small>\n </div>\n {options.searchable && (\n <div {...css.attrs(transferStyles.search)}>\n <TextField\n {...mergePartProps<TextFieldProps>(\n {\n icon: Search,\n variant: 'soft',\n size: 'sm',\n placeholder: lang.selectSearch,\n 'aria-label': `${lang.selectSearch} ${options.title}`,\n propsRoot: { sx: transferStyles.searchField },\n },\n options.propsSearch,\n )}\n type=\"search\"\n _value={options.search}\n onUpdate:_value={options.onSearch}\n disabled={options.disabled}\n />\n </div>\n )}\n {options.list}\n </section>\n );\n}\n\n/** 中间的两个按钮 */\nfunction renderActions(\n lang: ReturnType<typeof useLang>,\n titles: readonly [string, string],\n enabled: readonly [boolean, boolean],\n move: readonly [() => void, () => void],\n propsAction: Partial<IconButtonProps> | undefined,\n) {\n return (\n <div {...css.attrs(transferStyles.actions)}>\n {([1, 0] as const).map((to) => (\n <IconButton\n key={to}\n {...mergePartProps<IconButtonProps>(\n {\n icon: to === 1 ? ChevronRight : ChevronLeft,\n 'aria-label': lang.transferMoveTo(titles[to]),\n variant: 'soft',\n size: 'sm',\n propsIcon: { flipInRtl: true, sx: transferStyles.actionIcon },\n },\n propsAction,\n { disabled: !enabled[to], onClick: move[to] },\n )}\n />\n ))}\n </div>\n );\n}\n\n/** 穿梭框:两个可多选的列表,勾上之后移到另一边 */\nexport const Transfer = _component(\n <T,>({\n items,\n toOption,\n _value: value = _bindable<string[]>([]),\n titles,\n searchable = false,\n filter,\n disabled,\n propsPanel,\n propsSearch,\n propsAction,\n propsList,\n ...rest\n }: TransferProps<T>) => {\n const lang = useLang();\n const textMatcher = useTextMatcher();\n const field = useFieldControl(() => ({ disabled }));\n const baseId = useId();\n let checked = _state<[string[], string[]]>([[], []]);\n let searches = _state<[string, string]>(['', '']);\n\n const entries = _derived.by(() =>\n items.map((item) => ({ item, option: toListboxOption(item, toOption) })),\n );\n const byValue = _derived.by(() => new Map(entries.map((entry) => [entry.option.value, entry])));\n const chosen = _derived.by(() => new Set(value));\n const titleOf = (side: 0 | 1) =>\n titles?.[side] ?? (side === 0 ? lang.transferSource : lang.transferTarget);\n\n const matches = (entry: (typeof entries)[number], query: string) => {\n const text = query.trim();\n if (!text) return true;\n return filter ? filter(entry.item, text) : textMatcher()(entry.option.label, text);\n };\n /** 一边的全部项(左边按 items 的顺序,右边按移过去的先后) */\n const sideEntries = (side: 0 | 1) =>\n side === 0\n ? entries.filter((entry) => !chosen.has(entry.option.value))\n : value.flatMap((key) => byValue.get(key) ?? []);\n const shownEntries = (side: 0 | 1) =>\n sideEntries(side).filter((entry) => matches(entry, searches[side]));\n\n function setChecked(side: 0 | 1, keys: string[]) {\n checked = side === 0 ? [keys, checked[1]] : [checked[0], keys];\n }\n\n /** 把 keys 从 from 这一边移到另一边 */\n function move(from: 0 | 1, keys: readonly string[]) {\n const movable = keys.filter((key) => {\n const entry = byValue.get(key);\n return entry && !entry.option.disabled && chosen.has(key) === (from === 1);\n });\n if (field().disabled || movable.length === 0) return;\n const moving = new Set(movable);\n value = from === 0 ? [...value, ...movable] : value.filter((key) => !moving.has(key));\n setChecked(\n from,\n checked[from].filter((key) => !moving.has(key)),\n );\n announce(lang.transferMoved(movable.length, titleOf(from === 0 ? 1 : 0)));\n }\n\n return () => {\n const state = field();\n const list = (side: 0 | 1) => (\n <Listbox\n {...(mergePartProps<TransferListProps<T>>(\n {\n items: shownEntries(side).map((entry) => entry.item),\n toOption: (item: T) => toListboxOption(item, toOption),\n selectionMode: 'multiple',\n sx: transferStyles.list,\n propsOption: (item: T) => ({\n // 双击直接移过去\n onDblclick: () => move(side, [toListboxOption(item, toOption).value]),\n }),\n } as TransferListProps<T>,\n propsList,\n {\n disabled: state.disabled,\n id: `${baseId}-${side}`,\n 'aria-labelledby': `${baseId}-title-${side}`,\n } as Partial<TransferListProps<T>>,\n ) as ListboxProps<T> & UpdateHandlers<ListboxProps<T>>)}\n _value={checked[side]}\n onUpdate:_value={(next: string[]) => setChecked(side, next)}\n />\n );\n const panel = (side: 0 | 1) =>\n renderPanel(lang, {\n title: titleOf(side),\n titleId: `${baseId}-title-${side}`,\n selectable: shownEntries(side)\n .filter((entry) => !entry.option.disabled)\n .map((entry) => entry.option.value),\n checked: checked[side],\n total: sideEntries(side).length,\n onCheckAll: (keys) => setChecked(side, keys),\n search: searches[side],\n onSearch: (text) => (searches = side === 0 ? [text, searches[1]] : [searches[0], text]),\n searchable,\n disabled: state.disabled,\n propsPanel,\n propsSearch,\n list: list(side),\n });\n return (\n <div\n {...mergeAttrs<'div'>({ sx: transferStyles.root }, rest, {\n role: 'group',\n 'aria-labelledby': rest['aria-labelledby'] ?? state.labelledBy,\n 'aria-describedby': state.describedBy,\n })}\n >\n {panel(0)}\n {renderActions(\n lang,\n [titleOf(0), titleOf(1)],\n [!state.disabled && checked[1].length > 0, !state.disabled && checked[0].length > 0],\n [() => move(1, checked[1]), () => move(0, checked[0])],\n propsAction,\n )}\n {panel(1)}\n </div>\n );\n };\n },\n);\n\n/** 左边是一棵树的穿梭框:勾选叶子(父子联动)移到右边 */\nexport const TreeTransfer = _component(\n <T,>({\n items,\n getKey,\n getLabel,\n getChildren,\n _value: value = _bindable<string[]>([]),\n titles,\n searchable = false,\n disabled,\n propsPanel,\n propsSearch,\n propsAction,\n propsTree,\n propsList,\n ...rest\n }: TreeTransferProps<T>) => {\n const lang = useLang();\n const textMatcher = useTextMatcher();\n const field = useFieldControl(() => ({ disabled }));\n const baseId = useId();\n let checked = _state<[string[], string[]]>([[], []]);\n let searches = _state<[string, string]>(['', '']);\n let expanded = _state<string[]>([]);\n\n const index = _derived.by(() =>\n indexTree(items, { getKey: (node) => getKey(node), getChildren }),\n );\n // key → 节点:右边的文字、左边“不可用”的判断都用它\n const nodes = _derived.by(() => {\n const map = new Map<string, T>();\n const visit = (level: readonly T[]) =>\n level.forEach((node) => {\n map.set(getKey(node), node);\n visit(getChildren(node) ?? []);\n });\n visit(items);\n return map;\n });\n const leaves = _derived.by(() => index.order.filter((key) => !index.children.get(key)?.length));\n const chosen = _derived.by(() => new Set(value));\n const titleOf = (side: 0 | 1) =>\n titles?.[side] ?? (side === 0 ? lang.transferSource : lang.transferTarget);\n const matchesSearch = (key: string, side: 0 | 1) => {\n const text = searches[side].trim();\n const node = nodes.get(key);\n return !text || (!!node && textMatcher()(getLabel(node), text));\n };\n // 左边能勾的叶子:还没移过去的(搜索时只算匹配的)\n const sourceLeaves = () => leaves.filter((key) => !chosen.has(key));\n const targetOptions = () =>\n value.flatMap((key) => {\n const node = nodes.get(key);\n return node ? [{ value: key, label: getLabel(node) }] : [];\n });\n\n function setChecked(side: 0 | 1, keys: string[]) {\n checked = side === 0 ? [keys, checked[1]] : [checked[0], keys];\n }\n\n function move(from: 0 | 1, keys: readonly string[]) {\n const movable = keys.filter((key) => nodes.has(key) && chosen.has(key) === (from === 1));\n if (field().disabled || movable.length === 0) return;\n const moving = new Set(movable);\n value = from === 0 ? [...value, ...movable] : value.filter((key) => !moving.has(key));\n setChecked(\n from,\n checked[from].filter((key) => !moving.has(key)),\n );\n announce(lang.transferMoved(movable.length, titleOf(from === 0 ? 1 : 0)));\n }\n\n return () => {\n const state = field();\n const sourceChecked = checked[0];\n const tree = (\n <Tree\n {...mergePartProps<TreeProps<T>>(\n {\n items,\n getKey,\n getLabel,\n getChildren,\n checkable: true,\n // 已经移过去的叶子勾上且不可用\n isDisabled: (node: T) => state.disabled || chosen.has(getKey(node)),\n filter: searches[0],\n propsScrollArea: { sx: transferStyles.list },\n },\n propsTree,\n { 'aria-labelledby': `${baseId}-title-0` },\n )}\n _checked={[...value, ...sourceChecked]}\n onUpdate:_checked={(next: string[]) =>\n setChecked(\n 0,\n checkedByStrategy(index, next, 'child').filter((key) => !chosen.has(key)),\n )\n }\n _expanded={expanded}\n />\n );\n const list = (\n <Listbox\n {...mergePartProps<TransferListProps<ListboxOption>>(\n {\n items: targetOptions().filter((option) => matchesSearch(option.value, 1)),\n selectionMode: 'multiple',\n sx: transferStyles.list,\n propsOption: (option: ListboxOption) => ({\n onDblclick: () => move(1, [option.value]),\n }),\n } as TransferListProps<ListboxOption>,\n propsList,\n {\n disabled: state.disabled,\n id: `${baseId}-1`,\n 'aria-labelledby': `${baseId}-title-1`,\n } as Partial<TransferListProps<ListboxOption>>,\n )}\n _value={checked[1]}\n onUpdate:_value={(next: string[]) => setChecked(1, next)}\n />\n );\n const panel = (side: 0 | 1, selectable: string[], total: number, body: VNodeChild) =>\n renderPanel(lang, {\n title: titleOf(side),\n titleId: `${baseId}-title-${side}`,\n selectable,\n checked: checked[side],\n total,\n onCheckAll: (keys) => setChecked(side, keys),\n search: searches[side],\n onSearch: (text) => (searches = side === 0 ? [text, searches[1]] : [searches[0], text]),\n searchable,\n disabled: state.disabled,\n propsPanel,\n propsSearch,\n list: body,\n });\n return (\n <div\n {...mergeAttrs<'div'>({ sx: transferStyles.root }, rest, {\n role: 'group',\n 'aria-labelledby': rest['aria-labelledby'] ?? state.labelledBy,\n 'aria-describedby': state.describedBy,\n })}\n >\n {panel(\n 0,\n sourceLeaves().filter((key) => matchesSearch(key, 0)),\n sourceLeaves().length,\n tree,\n )}\n {renderActions(\n lang,\n [titleOf(0), titleOf(1)],\n [!state.disabled && checked[1].length > 0, !state.disabled && sourceChecked.length > 0],\n [() => move(1, checked[1]), () => move(0, sourceChecked)],\n propsAction,\n )}\n {panel(\n 1,\n value.filter((key) => matchesSearch(key, 1)),\n targetOptions().length,\n list,\n )}\n </div>\n );\n };\n },\n);\n"],"mappings":"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"}
|
package/dist/input/TreeSelect.js
CHANGED
|
@@ -17,8 +17,8 @@ import { useRemoteItems } from "./remote-items.js";
|
|
|
17
17
|
import { SelectedTags } from "./SelectedTags.js";
|
|
18
18
|
import { TextField } from "./TextField.js";
|
|
19
19
|
import { selectStyles } from "./Select.js";
|
|
20
|
-
import { Fragment, computed, createVNode,
|
|
21
|
-
import { _component, bindable, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
20
|
+
import { Fragment, computed, createVNode, ref, shallowRef, useId, watch } from "vue";
|
|
21
|
+
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
22
22
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
23
23
|
import { ChevronDown, Search } from "@lucide/icons";
|
|
24
24
|
//#region src/input/TreeSelect.tsx
|
|
@@ -241,7 +241,7 @@ var TreeSelect = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
241
241
|
filter: treeFilter(),
|
|
242
242
|
loadChildren: loadChildren.value,
|
|
243
243
|
loading: remote.loading(),
|
|
244
|
-
empty: remote.
|
|
244
|
+
empty: remote.failure() ?? (search.value.trim() ? lang.selectNoMatch : void 0),
|
|
245
245
|
isDisabled: isDisabled.value,
|
|
246
246
|
propsScrollArea: { sx: treeSelectStyles.tree },
|
|
247
247
|
"aria-labelledby": labelledBy,
|
|
@@ -258,7 +258,7 @@ var TreeSelect = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
258
258
|
const shownKeys = displayKeys();
|
|
259
259
|
const tagged = multiple() && shownKeys.length > 0;
|
|
260
260
|
const shown = shownKeys.length === 0 ? createVNode("span", css.attrs(selectStyles.placeholder), [placeholder.value ?? lang.selectPlaceholder]) : tagged ? createVNode("span", css.attrs(visuallyHiddenStyles.hidden), [lang.selectSummary(shownKeys.map(labelOf))]) : labelOf(shownKeys[0]);
|
|
261
|
-
return createVNode(Fragment, null, [createVNode("div",
|
|
261
|
+
return createVNode(Fragment, null, [createVNode("div", mergeJsxProps(mergeAttrs({
|
|
262
262
|
...s.root,
|
|
263
263
|
sx: [s.root.sx, selectStyles.root]
|
|
264
264
|
}, propsRoot.value, {
|
|
@@ -329,7 +329,7 @@ var TreeSelect = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
329
329
|
ref: panel,
|
|
330
330
|
popover: "auto",
|
|
331
331
|
onToggle: onPanelToggle
|
|
332
|
-
}), [searchable.value && createVNode("div", css.attrs(listPopoverStyles.header), [createVNode(TextField,
|
|
332
|
+
}), [searchable.value && createVNode("div", css.attrs(listPopoverStyles.header), [createVNode(TextField, mergeJsxProps(mergePartProps({
|
|
333
333
|
icon: Search,
|
|
334
334
|
variant: "soft",
|
|
335
335
|
placeholder: lang.selectSearch,
|
|
@@ -341,13 +341,13 @@ var TreeSelect = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
341
341
|
"onUpdate:_value": _cache[0] || (_cache[0] = ($event) => search.value = $event),
|
|
342
342
|
"aria-controls": treeId,
|
|
343
343
|
"onKeydown": onSearchKeydown
|
|
344
|
-
}), null)]), open.value && (multiple() ? createVNode(Tree,
|
|
344
|
+
}), null)]), open.value && (multiple() ? createVNode(Tree, mergeJsxProps(treeProps(state.labelledBy), {
|
|
345
345
|
"checkable": true,
|
|
346
346
|
"_checked": [...values()],
|
|
347
347
|
"onUpdate:_checked": _cache[1] || (_cache[1] = (next) => setChecked(next)),
|
|
348
348
|
"_expanded": shownExpanded(),
|
|
349
349
|
"onUpdate:_expanded": _cache[2] || (_cache[2] = (next) => expanded.value = remoteResults() ? expanded.value : next)
|
|
350
|
-
}), null) : createVNode(Tree,
|
|
350
|
+
}), null) : createVNode(Tree, mergeJsxProps(treeProps(state.labelledBy), {
|
|
351
351
|
"selectionMode": "single",
|
|
352
352
|
"_selected": [...values()],
|
|
353
353
|
"onUpdate:_selected": _cache[3] || (_cache[3] = (next) => {
|
|
@@ -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.error()\n ? lang.listLoadFailed\n : search.trim()\n ? lang.selectNoMatch\n : 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 * 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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"}
|
package/dist/input/Upload.js
CHANGED
|
@@ -13,9 +13,10 @@ import { useSortable } from "../utils/dom/sortable.js";
|
|
|
13
13
|
import { useFieldControl } from "../form/Field.js";
|
|
14
14
|
import { itemStyles } from "../utils/style/item-styles.js";
|
|
15
15
|
import { useHttp } from "../utils/request/http.js";
|
|
16
|
+
import { errorCodeText } from "../utils/request/error-message.js";
|
|
16
17
|
import { FileDrop, matchesAccept } from "./FileDrop.js";
|
|
17
|
-
import { Fragment, createVNode, isVNode,
|
|
18
|
-
import { _component, bindable, effect, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
18
|
+
import { Fragment, createVNode, isVNode, onBeforeUnmount, shallowRef, watch } from "vue";
|
|
19
|
+
import { _component, bindable, effect, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
19
20
|
import * as css from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
20
21
|
import { CircleAlert, CircleCheck, File, GripVertical, ImagePlus, RotateCw, X } from "@lucide/icons";
|
|
21
22
|
//#region src/input/Upload.tsx
|
|
@@ -267,7 +268,7 @@ var Upload$1 = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
267
268
|
});
|
|
268
269
|
} catch (error) {
|
|
269
270
|
if (controller.signal.aborted) return;
|
|
270
|
-
const message = error instanceof Error && error.message ? error.message : lang.uploadFailed;
|
|
271
|
+
const message = errorCodeText(error, lang) ?? (error instanceof Error && error.message ? error.message : lang.uploadFailed);
|
|
271
272
|
patch(item.id, {
|
|
272
273
|
status: "error",
|
|
273
274
|
error: message
|
|
@@ -365,7 +366,7 @@ var Upload$1 = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
365
366
|
const own = typeof propsItem.value === "function" ? propsItem.value(item) : propsItem.value;
|
|
366
367
|
const fileName = item.name;
|
|
367
368
|
const failed = item.status === "error";
|
|
368
|
-
return createVNode("li",
|
|
369
|
+
return createVNode("li", mergeJsxProps({ "key": item.id }, mergeAttrs({ sx: [itemStyles.row, uploadStyles.item] }, own), { "data-state": item.status }), [
|
|
369
370
|
createVNode(Icon, mergePartProps({
|
|
370
371
|
icon: failed ? CircleAlert : item.status === "done" ? CircleCheck : File,
|
|
371
372
|
sx: [
|
|
@@ -409,7 +410,7 @@ var Upload$1 = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
409
410
|
const state = control();
|
|
410
411
|
const failed = item.status === "error";
|
|
411
412
|
const src = previewOf(item);
|
|
412
|
-
return createVNode("div",
|
|
413
|
+
return createVNode("div", mergeJsxProps({ "key": item.id }, mergeAttrs({ sx: [
|
|
413
414
|
uploadStyles.card,
|
|
414
415
|
uploadDynamicStyles.square(thumbnailSize.value),
|
|
415
416
|
failed && uploadStyles.cardError
|
|
@@ -432,13 +433,13 @@ var Upload$1 = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
432
433
|
value: item.progress == null ? null : Math.round(item.progress * 100),
|
|
433
434
|
"aria-label": item.name
|
|
434
435
|
}), null)]),
|
|
435
|
-
failed && src && !item.rejected && createVNode("div",
|
|
436
|
+
failed && src && !item.rejected && createVNode("div", mergeJsxProps(css.attrs(uploadStyles.overlay), { "title": item.error }), [item.error]),
|
|
436
437
|
item.status === "done" && createVNode(VisuallyHidden, null, {
|
|
437
438
|
default: () => [lang.uploadDone],
|
|
438
439
|
$stable: true
|
|
439
440
|
}),
|
|
440
441
|
!state.readonly && createVNode("div", css.attrs(uploadStyles.actions), [
|
|
441
|
-
sortable.value && createVNode(ButtonBase,
|
|
442
|
+
sortable.value && createVNode(ButtonBase, mergeJsxProps({
|
|
442
443
|
"sx": uploadStyles.handle,
|
|
443
444
|
"ripple": false,
|
|
444
445
|
"disabled": state.disabled,
|
|
@@ -502,7 +503,7 @@ var Upload$1 = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
502
503
|
"sx": uploadStyles.wall,
|
|
503
504
|
"key": "__site0"
|
|
504
505
|
}, {
|
|
505
|
-
default: () => [createVNode("div",
|
|
506
|
+
default: () => [createVNode("div", mergeJsxProps({
|
|
506
507
|
"ref": wall,
|
|
507
508
|
"role": "list",
|
|
508
509
|
"aria-live": "polite"
|
|
@@ -548,7 +549,7 @@ var Upload$1 = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
548
549
|
"tabindex": -1,
|
|
549
550
|
"aria-hidden": "true"
|
|
550
551
|
}, null),
|
|
551
|
-
value.value.length > 0 && createVNode(GridList,
|
|
552
|
+
value.value.length > 0 && createVNode(GridList, mergeJsxProps(mergePartProps({ gap: "xs" }, propsList.value), {
|
|
552
553
|
"aria-live": "polite",
|
|
553
554
|
"key": "__site3"
|
|
554
555
|
}), {
|